refactor: remove inline gradient editor from CSS modal, use entity picker
Some checks failed
Lint & Test / test (push) Failing after 30s
Some checks failed
Lint & Test / test (push) Failing after 30s
Replace the gradient stop editor (canvas, markers, stop list) in the CSS editor gradient section with a simple gradient entity selector. Gradients are now created/edited exclusively in the Gradients tab. Fix effect and audio palette pickers to populate from gradient entities dynamically instead of hardcoded HTML options. Unify all gradient/palette pickers via _buildGradientEntityItems(). Also: rename "None (use own speed)" → "None (no sync)" for sync clocks. Add i18n keys for gradient selector and missing error messages.
This commit is contained in:
@@ -398,10 +398,7 @@ function _ensureEffectTypeIconSelect() {
|
||||
function _ensureEffectPaletteIconSelect() {
|
||||
const sel = document.getElementById('css-editor-effect-palette') as HTMLSelectElement | null;
|
||||
if (!sel) return;
|
||||
const gradients = _getGradients();
|
||||
const items = gradients.map(g => ({
|
||||
value: g.id, icon: _gradientEntityStripHTML(g.stops), label: g.name,
|
||||
}));
|
||||
const items = _buildGradientEntityItems();
|
||||
if (_effectPaletteIconSelect) { _effectPaletteIconSelect.updateItems(items); return; }
|
||||
_effectPaletteIconSelect = new IconSelect({ target: sel, items, columns: 2 });
|
||||
}
|
||||
@@ -435,10 +432,7 @@ function _ensureCandleTypeIconSelect() {
|
||||
function _ensureAudioPaletteIconSelect() {
|
||||
const sel = document.getElementById('css-editor-audio-palette') as HTMLSelectElement | null;
|
||||
if (!sel) return;
|
||||
const gradients = _getGradients();
|
||||
const items = gradients.map(g => ({
|
||||
value: g.id, icon: _gradientEntityStripHTML(g.stops), label: g.name,
|
||||
}));
|
||||
const items = _buildGradientEntityItems();
|
||||
if (_audioPaletteIconSelect) { _audioPaletteIconSelect.updateItems(items); return; }
|
||||
_audioPaletteIconSelect = new IconSelect({ target: sel, items, columns: 2 });
|
||||
}
|
||||
@@ -455,37 +449,27 @@ function _ensureAudioVizIconSelect() {
|
||||
_audioVizIconSelect = new IconSelect({ target: sel, items, columns: 3 });
|
||||
}
|
||||
|
||||
function _buildGradientPresetItems() {
|
||||
function _buildGradientEntityItems() {
|
||||
const gradients = _getGradients();
|
||||
const builtInItems = gradients.filter(g => g.is_builtin).map(g => ({
|
||||
return gradients.map(g => ({
|
||||
value: g.id, icon: _gradientEntityStripHTML(g.stops), label: g.name,
|
||||
}));
|
||||
const userItems = gradients.filter(g => !g.is_builtin).map(g => ({
|
||||
value: g.id, icon: _gradientEntityStripHTML(g.stops), label: g.name,
|
||||
isCustom: true,
|
||||
}));
|
||||
return [
|
||||
{ value: '', icon: _icon(P.palette), label: t('color_strip.gradient.preset.custom') },
|
||||
...builtInItems,
|
||||
...userItems,
|
||||
];
|
||||
}
|
||||
|
||||
function _ensureGradientPresetIconSelect() {
|
||||
const sel = document.getElementById('css-editor-gradient-preset') as HTMLSelectElement | null;
|
||||
if (!sel) return;
|
||||
const items = _buildGradientPresetItems();
|
||||
const items = _buildGradientEntityItems();
|
||||
if (_gradientPresetIconSelect) { _gradientPresetIconSelect.updateItems(items); return; }
|
||||
_gradientPresetIconSelect = new IconSelect({ target: sel, items, columns: 3, onChange: (v) => onGradientPresetChange(v) });
|
||||
_gradientPresetIconSelect = new IconSelect({ target: sel, items, columns: 3 });
|
||||
}
|
||||
|
||||
/** Rebuild the preset picker after adding/removing custom presets. */
|
||||
/** Rebuild the gradient picker after entity changes. */
|
||||
export function refreshGradientPresetPicker() {
|
||||
if (_gradientPresetIconSelect) {
|
||||
_gradientPresetIconSelect.updateItems(_buildGradientPresetItems());
|
||||
_gradientPresetIconSelect.setValue('');
|
||||
}
|
||||
_renderCustomPresetList();
|
||||
const items = _buildGradientEntityItems();
|
||||
if (_gradientPresetIconSelect) _gradientPresetIconSelect.updateItems(items);
|
||||
if (_effectPaletteIconSelect) _effectPaletteIconSelect.updateItems(items);
|
||||
if (_audioPaletteIconSelect) _audioPaletteIconSelect.updateItems(items);
|
||||
}
|
||||
|
||||
/** Render the user-created gradient list below the save button. */
|
||||
@@ -1209,49 +1193,34 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
},
|
||||
gradient: {
|
||||
load(css) {
|
||||
const presetId = css.gradient_id || '';
|
||||
(document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value = presetId;
|
||||
if (_gradientPresetIconSelect) _gradientPresetIconSelect.setValue(presetId);
|
||||
// If gradient_id is set, load stops from the gradient entity
|
||||
let stops = css.stops || [
|
||||
{ position: 0.0, color: [255, 0, 0] },
|
||||
{ position: 1.0, color: [0, 0, 255] },
|
||||
];
|
||||
if (presetId) {
|
||||
const g = _findGradient(presetId);
|
||||
if (g) stops = g.stops;
|
||||
}
|
||||
gradientInit(stops);
|
||||
const gradientId = css.gradient_id || '';
|
||||
_ensureGradientPresetIconSelect();
|
||||
(document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value = gradientId;
|
||||
if (_gradientPresetIconSelect) _gradientPresetIconSelect.setValue(gradientId);
|
||||
_loadAnimationState(css.animation);
|
||||
(document.getElementById('css-editor-gradient-easing') as HTMLSelectElement).value = css.easing || 'linear';
|
||||
if (_gradientEasingIconSelect) _gradientEasingIconSelect.setValue(css.easing || 'linear');
|
||||
},
|
||||
reset() {
|
||||
(document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value = '';
|
||||
if (_gradientPresetIconSelect) _gradientPresetIconSelect.setValue('');
|
||||
gradientInit([
|
||||
{ position: 0.0, color: [255, 0, 0] },
|
||||
{ position: 1.0, color: [0, 0, 255] },
|
||||
]);
|
||||
_ensureGradientPresetIconSelect();
|
||||
// Default to first gradient
|
||||
const gradients = _getGradients();
|
||||
const defaultId = gradients.length > 0 ? gradients[0].id : '';
|
||||
(document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value = defaultId;
|
||||
if (_gradientPresetIconSelect) _gradientPresetIconSelect.setValue(defaultId);
|
||||
_loadAnimationState(null);
|
||||
(document.getElementById('css-editor-gradient-easing') as HTMLSelectElement).value = 'linear';
|
||||
if (_gradientEasingIconSelect) _gradientEasingIconSelect.setValue('linear');
|
||||
},
|
||||
getPayload(name) {
|
||||
const gStops = getGradientStops();
|
||||
if (gStops.length < 2) {
|
||||
cssEditorModal.showError(t('color_strip.gradient.min_stops'));
|
||||
const gradientId = (document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value;
|
||||
if (!gradientId) {
|
||||
cssEditorModal.showError(t('color_strip.gradient.error.no_gradient'));
|
||||
return null;
|
||||
}
|
||||
const gradientId = (document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value || null;
|
||||
return {
|
||||
name,
|
||||
gradient_id: gradientId,
|
||||
stops: gStops.map(s => ({
|
||||
position: s.position,
|
||||
color: s.color,
|
||||
...(s.colorRight ? { color_right: s.colorRight } : {}),
|
||||
})),
|
||||
animation: _getAnimationPayload(),
|
||||
easing: (document.getElementById('css-editor-gradient-easing') as HTMLSelectElement).value,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user