175 lines
6.2 KiB
JavaScript
175 lines
6.2 KiB
JavaScript
const colors = ['#ff0000', '#00ff00', '#0000ff'];
|
|
let colorsChanged = true;
|
|
|
|
// Copied from https://github.com/revoltchat/backend/blob/master/crates/quark/src/util/regex.rs
|
|
const RE_COLOUR = "^(?:[a-z ]+|var\(--[a-z\d-]+\)|rgba?\([\d, ]+\)|#[a-f0-9]+|(repeating-)?(linear|conic|radial)-gradient\(([a-z ]+|var\(--[a-z\d-]+\)|rgba?\([\d, ]+\)|#[a-f0-9]+|\d+deg)([ ]+(\d{1,3}%|0))?(,[ ]*([a-z ]+|var\(--[a-z\d-]+\)|rgba?\([\d, ]+\)|#[a-f0-9]+)([ ]+(\d{1,3}%|0))?)+\))$";
|
|
|
|
function updateUi() {
|
|
const radios = document.getElementsByName('gradient_type');
|
|
document.getElementById('config_linear').style.display = radios[0].checked ? 'unset' : 'none';
|
|
document.getElementById('config_radial').style.display = radios[1].checked ? 'unset' : 'none';
|
|
document.getElementById('config_conic').style.display = radios[2].checked ? 'unset' : 'none';
|
|
|
|
if (colorsChanged) {
|
|
colorsChanged = false;
|
|
const list = document.getElementById('color-list');
|
|
while (list.lastChild) list.lastChild.remove();
|
|
for (let i in colors) {
|
|
i = Number(i);
|
|
const color = colors[i];
|
|
|
|
let colorInput = document.createElement('input');
|
|
colorInput.type = 'color';
|
|
colorInput.value = color;
|
|
colorInput.onchange = (e) => changeColor(i, e.currentTarget.value);
|
|
list.appendChild(colorInput);
|
|
|
|
let button1 = document.createElement('button');
|
|
button1.innerText = '^';
|
|
button1.disabled = i == 0;
|
|
button1.onclick = () => moveUp(i);
|
|
list.appendChild(button1);
|
|
|
|
let button2 = document.createElement('button');
|
|
button2.innerText = 'v';
|
|
button2.disabled = i == colors.length - 1;
|
|
button2.onclick = () => moveDown(i);
|
|
list.appendChild(button2);
|
|
|
|
let button3 = document.createElement('button');
|
|
button3.innerText = 'Delete';
|
|
button3.onclick = () => removeColor(i);
|
|
list.appendChild(button3);
|
|
|
|
// Dynamic distance scaling between color nodes, too much effort to implement rn
|
|
/*
|
|
let sliderValue = document.createElement('span');
|
|
sliderValue.innerText = '50%';
|
|
|
|
let slider = document.createElement('input');
|
|
slider.type = 'range';
|
|
slider.min = 0;
|
|
slider.max = 100;
|
|
slider.value = 50;
|
|
slider.autocomplete = 'off';
|
|
slider.oninput = (e) => sliderValue.innerText = `${e.currentTarget.value}%`;
|
|
|
|
list.appendChild(slider);
|
|
list.appendChild(sliderValue);
|
|
*/
|
|
|
|
list.appendChild(document.createElement('br'));
|
|
}
|
|
}
|
|
|
|
document.getElementById('custom_pos_inputs').hidden = !document.getElementById('conic_custom_position').checked;
|
|
|
|
const css = generateCss();
|
|
if (css) {
|
|
document.getElementById('preview').style.backgroundImage = css;
|
|
document.getElementById('output').value = css;
|
|
|
|
if (css.length > 128) {
|
|
document.getElementById('output_error').innerText = `Warning: The generated CSS is ${css.length} characters long, which exceeds Revolt's limit of 128 characters. You will not be able to use this gradient on Revolt.`;
|
|
}
|
|
// for some reason this won't work
|
|
//else if (!css.match(new RegExp(RE_COLOUR, 'i'))) {
|
|
// document.getElementById('output_error').innerText = `Warning: The generated CSS doesn't match against the validation regex. This means that Revolt will not accept one of the set parameters.`;
|
|
//}
|
|
else document.getElementById('output_error').innerText = '';
|
|
}
|
|
}
|
|
|
|
function removeColor(index) {
|
|
colorsChanged = true;
|
|
colors.splice(index, 1);
|
|
updateUi();
|
|
}
|
|
|
|
function appendColor() {
|
|
colorsChanged = true;
|
|
colors.push('#ffbbaa');
|
|
updateUi();
|
|
}
|
|
|
|
function changeColor(index, color) {
|
|
colorsChanged = true;
|
|
colors[index] = color;
|
|
updateUi();
|
|
}
|
|
|
|
function moveUp(index) {
|
|
colorsChanged = true;
|
|
[colors[index], colors[index - 1]] = [colors[index - 1], colors[index]];
|
|
updateUi();
|
|
}
|
|
|
|
function moveDown(index) {
|
|
colorsChanged = true;
|
|
[colors[index], colors[index + 1]] = [colors[index + 1], colors[index]];
|
|
updateUi();
|
|
}
|
|
|
|
/**
|
|
* @returns {string}
|
|
*/
|
|
function generateColorList() {
|
|
const noTransition = document.getElementById('no_transition').checked;
|
|
if (noTransition) {
|
|
const distance = 100 / colors.length;
|
|
const colorCodes = [];
|
|
for (let i = 0; i < colors.length; i++) {
|
|
colorCodes.push(i == 0 ? colors[i] : `${colors[i]} ${Math.round(distance * i * 10) / 10}%`);
|
|
colorCodes.push(i == colors.length - 1 ? colors[i] : `${colors[i]} ${Math.round(distance * (i+1) * 10) / 10}%`);
|
|
}
|
|
return colorCodes.join(',');
|
|
}
|
|
else return colors.join(',');
|
|
}
|
|
|
|
/**
|
|
* @returns {string}
|
|
*/
|
|
function generateCss() {
|
|
const radios = document.getElementsByName('gradient_type');
|
|
if (radios[0].checked) return generateCssLinear();
|
|
if (radios[1].checked) return generateCssRadial();
|
|
if (radios[2].checked) return generateCssConic();
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* @returns {string}
|
|
*/
|
|
function generateCssLinear() {
|
|
const rotation = document.getElementById('rotation').value;
|
|
return `linear-gradient(${rotation}deg,${generateColorList()})`;
|
|
}
|
|
/**
|
|
* @returns {string}
|
|
*/
|
|
function generateCssRadial() {
|
|
let radios = document.getElementsByName('radial_mode');
|
|
const mode = Array.from(radios).find(r => r.checked).value ?? 'circle';
|
|
radios = document.getElementsByName('radial_pos');
|
|
const pos = Array.from(radios).find(r => r.checked).value ?? 'center';
|
|
return `radial-gradient(${mode} at ${pos}, ${generateColorList()})`;
|
|
}
|
|
/**
|
|
* @returns {string}
|
|
*/
|
|
function generateCssConic() {
|
|
const rotation = document.getElementById('rotation_conic').value;
|
|
const showCustomPos = document.getElementById('conic_custom_position').checked;
|
|
const x = document.getElementById('conic_x').value;
|
|
const y = document.getElementById('conic_y').value;
|
|
// have to remove all of this because Revolt doesn't allow it, smh
|
|
// from ${rotation}deg${showCustomPos ? ` at ${x}% ${y}%` : ''},
|
|
return `conic-gradient(${generateColorList()})`;
|
|
}
|
|
|
|
// Initial update
|
|
window.onload = () => {
|
|
updateUi();
|
|
};
|