feat: expand color strip sources with new effects, gradient improvements, and daylight/candlelight enhancements
Some checks failed
Lint & Test / test (push) Failing after 29s
Some checks failed
Lint & Test / test (push) Failing after 29s
Effects: add 7 new procedural effects (rain, comet, bouncing ball, fireworks, sparkle rain, lava lamp, wave interference) and custom palette support via user-defined [[pos,R,G,B],...] stops. Gradient: add easing functions (linear, ease_in_out, step, cubic) for stop interpolation, plus noise_perturb and hue_rotate animation types. Daylight: add longitude field and NOAA solar equations for accurate sunrise/sunset based on latitude, longitude, and day of year. Candlelight: add wind simulation (correlated gusts), candle type presets (taper/votive/bonfire), and wax drip effect with localized brightness dips. Also fixes editor preview to include all new fields for inline LED test.
This commit is contained in:
@@ -118,7 +118,7 @@ import {
|
||||
// Layer 5: color-strip sources
|
||||
import {
|
||||
showCSSEditor, closeCSSEditorModal, forceCSSEditorClose, saveCSSEditor, deleteColorStrip,
|
||||
onCSSTypeChange, onEffectTypeChange, onAnimationTypeChange, onCSSClockChange, onDaylightRealTimeChange,
|
||||
onCSSTypeChange, onEffectTypeChange, onEffectPaletteChange, onAnimationTypeChange, onCSSClockChange, onDaylightRealTimeChange,
|
||||
colorCycleAddColor, colorCycleRemoveColor,
|
||||
compositeAddLayer, compositeRemoveLayer,
|
||||
mappedAddZone, mappedRemoveZone,
|
||||
@@ -430,6 +430,7 @@ Object.assign(window, {
|
||||
deleteColorStrip,
|
||||
onCSSTypeChange,
|
||||
onEffectTypeChange,
|
||||
onEffectPaletteChange,
|
||||
onCSSClockChange,
|
||||
onAnimationTypeChange,
|
||||
onDaylightRealTimeChange,
|
||||
|
||||
@@ -31,18 +31,19 @@ function _collectPreviewConfig() {
|
||||
} else if (sourceType === 'gradient') {
|
||||
const stops = getGradientStops();
|
||||
if (stops.length < 2) return null;
|
||||
config = { source_type: 'gradient', stops: stops.map(s => ({ position: s.position, color: s.color, ...(s.colorRight ? { color_right: s.colorRight } : {}) })), animation: _getAnimationPayload() };
|
||||
config = { source_type: 'gradient', stops: stops.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 };
|
||||
} else if (sourceType === 'color_cycle') {
|
||||
const colors = _colorCycleGetColors();
|
||||
if (colors.length < 2) return null;
|
||||
config = { source_type: 'color_cycle', colors };
|
||||
} else if (sourceType === 'effect') {
|
||||
config = { source_type: 'effect', effect_type: (document.getElementById('css-editor-effect-type') as HTMLInputElement).value, palette: (document.getElementById('css-editor-effect-palette') as HTMLInputElement).value, intensity: parseFloat((document.getElementById('css-editor-effect-intensity') as HTMLInputElement).value), scale: parseFloat((document.getElementById('css-editor-effect-scale') as HTMLInputElement).value), mirror: (document.getElementById('css-editor-effect-mirror') as HTMLInputElement).checked };
|
||||
if (config.effect_type === 'meteor') { const hex = (document.getElementById('css-editor-effect-color') as HTMLInputElement).value; config.color = [parseInt(hex.slice(1, 3), 16), parseInt(hex.slice(3, 5), 16), parseInt(hex.slice(5, 7), 16)]; }
|
||||
if (['meteor', 'comet', 'bouncing_ball'].includes(config.effect_type)) { const hex = (document.getElementById('css-editor-effect-color') as HTMLInputElement).value; config.color = [parseInt(hex.slice(1, 3), 16), parseInt(hex.slice(3, 5), 16), parseInt(hex.slice(5, 7), 16)]; }
|
||||
if (config.palette === 'custom') { const cpText = (document.getElementById('css-editor-effect-custom-palette') as HTMLTextAreaElement)?.value?.trim(); if (cpText) { try { config.custom_palette = JSON.parse(cpText); } catch {} } }
|
||||
} else if (sourceType === 'daylight') {
|
||||
config = { source_type: 'daylight', speed: parseFloat((document.getElementById('css-editor-daylight-speed') as HTMLInputElement).value), use_real_time: (document.getElementById('css-editor-daylight-real-time') as HTMLInputElement).checked, latitude: parseFloat((document.getElementById('css-editor-daylight-latitude') as HTMLInputElement).value) };
|
||||
config = { source_type: 'daylight', speed: parseFloat((document.getElementById('css-editor-daylight-speed') as HTMLInputElement).value), use_real_time: (document.getElementById('css-editor-daylight-real-time') as HTMLInputElement).checked, latitude: parseFloat((document.getElementById('css-editor-daylight-latitude') as HTMLInputElement).value), longitude: parseFloat((document.getElementById('css-editor-daylight-longitude') as HTMLInputElement).value) };
|
||||
} else if (sourceType === 'candlelight') {
|
||||
config = { source_type: 'candlelight', color: hexToRgbArray((document.getElementById('css-editor-candlelight-color') as HTMLInputElement).value), intensity: parseFloat((document.getElementById('css-editor-candlelight-intensity') as HTMLInputElement).value), num_candles: parseInt((document.getElementById('css-editor-candlelight-num-candles') as HTMLInputElement).value) || 3, speed: parseFloat((document.getElementById('css-editor-candlelight-speed') as HTMLInputElement).value) };
|
||||
config = { source_type: 'candlelight', color: hexToRgbArray((document.getElementById('css-editor-candlelight-color') as HTMLInputElement).value), intensity: parseFloat((document.getElementById('css-editor-candlelight-intensity') as HTMLInputElement).value), num_candles: parseInt((document.getElementById('css-editor-candlelight-num-candles') as HTMLInputElement).value) || 3, speed: parseFloat((document.getElementById('css-editor-candlelight-speed') as HTMLInputElement).value), wind_strength: parseFloat((document.getElementById('css-editor-candlelight-wind') as HTMLInputElement).value), candle_type: (document.getElementById('css-editor-candlelight-type') as HTMLSelectElement).value };
|
||||
}
|
||||
const clockEl = document.getElementById('css-editor-clock') as HTMLSelectElement | null;
|
||||
if (clockEl && clockEl.value) config.clock_id = clockEl.value;
|
||||
|
||||
@@ -194,11 +194,12 @@ export function onCSSTypeChange() {
|
||||
_ensureAudioPaletteIconSelect();
|
||||
onAudioVizChange();
|
||||
}
|
||||
if (type === 'gradient') { _ensureGradientPresetIconSelect(); _renderCustomPresetList(); }
|
||||
if (type === 'gradient') { _ensureGradientPresetIconSelect(); _ensureGradientEasingIconSelect(); _renderCustomPresetList(); }
|
||||
if (type === 'notification') {
|
||||
ensureNotificationEffectIconSelect();
|
||||
ensureNotificationFilterModeIconSelect();
|
||||
}
|
||||
if (type === 'candlelight') _ensureCandleTypeIconSelect();
|
||||
|
||||
// Animation section — shown for static/gradient only
|
||||
const animSection = document.getElementById('css-editor-animation-section') as HTMLElement;
|
||||
@@ -206,7 +207,7 @@ export function onCSSTypeChange() {
|
||||
if (type === 'static' || type === 'gradient') {
|
||||
animSection.style.display = '';
|
||||
const opts = type === 'gradient'
|
||||
? ['none','breathing','gradient_shift','wave','strobe','sparkle','pulse','candle','rainbow_fade']
|
||||
? ['none','breathing','gradient_shift','wave','noise_perturb','hue_rotate','strobe','sparkle','pulse','candle','rainbow_fade']
|
||||
: ['none','breathing','strobe','sparkle','pulse','candle','rainbow_fade'];
|
||||
animTypeSelect.innerHTML = opts.map(v =>
|
||||
`<option value="${v}">${t('color_strip.animation.type.' + v)}</option>`
|
||||
@@ -373,6 +374,8 @@ let _effectPaletteIconSelect: any = null;
|
||||
let _audioPaletteIconSelect: any = null;
|
||||
let _audioVizIconSelect: any = null;
|
||||
let _gradientPresetIconSelect: any = null;
|
||||
let _gradientEasingIconSelect: any = null;
|
||||
let _candleTypeIconSelect: any = null;
|
||||
const _icon = (d: any) => `<svg class="icon" viewBox="0 0 24 24">${d}</svg>`;
|
||||
|
||||
function _ensureInterpolationIconSelect() {
|
||||
@@ -391,11 +394,18 @@ function _ensureEffectTypeIconSelect() {
|
||||
const sel = document.getElementById('css-editor-effect-type') as HTMLSelectElement | null;
|
||||
if (!sel) return;
|
||||
const items = [
|
||||
{ value: 'fire', icon: _icon(P.zap), label: t('color_strip.effect.fire'), desc: t('color_strip.effect.fire.desc') },
|
||||
{ value: 'meteor', icon: _icon(P.sparkles), label: t('color_strip.effect.meteor'), desc: t('color_strip.effect.meteor.desc') },
|
||||
{ value: 'plasma', icon: _icon(P.rainbow), label: t('color_strip.effect.plasma'), desc: t('color_strip.effect.plasma.desc') },
|
||||
{ value: 'noise', icon: _icon(P.activity), label: t('color_strip.effect.noise'), desc: t('color_strip.effect.noise.desc') },
|
||||
{ value: 'aurora', icon: _icon(P.sparkles), label: t('color_strip.effect.aurora'), desc: t('color_strip.effect.aurora.desc') },
|
||||
{ value: 'fire', icon: _icon(P.zap), label: t('color_strip.effect.fire'), desc: t('color_strip.effect.fire.desc') },
|
||||
{ value: 'meteor', icon: _icon(P.sparkles), label: t('color_strip.effect.meteor'), desc: t('color_strip.effect.meteor.desc') },
|
||||
{ value: 'plasma', icon: _icon(P.rainbow), label: t('color_strip.effect.plasma'), desc: t('color_strip.effect.plasma.desc') },
|
||||
{ value: 'noise', icon: _icon(P.activity), label: t('color_strip.effect.noise'), desc: t('color_strip.effect.noise.desc') },
|
||||
{ value: 'aurora', icon: _icon(P.sparkles), label: t('color_strip.effect.aurora'), desc: t('color_strip.effect.aurora.desc') },
|
||||
{ value: 'rain', icon: _icon(P.cloudSun), label: t('color_strip.effect.rain'), desc: t('color_strip.effect.rain.desc') },
|
||||
{ value: 'comet', icon: _icon(P.rocket), label: t('color_strip.effect.comet'), desc: t('color_strip.effect.comet.desc') },
|
||||
{ value: 'bouncing_ball', icon: _icon(P.activity), label: t('color_strip.effect.bouncing_ball'), desc: t('color_strip.effect.bouncing_ball.desc') },
|
||||
{ value: 'fireworks', icon: _icon(P.sparkles), label: t('color_strip.effect.fireworks'), desc: t('color_strip.effect.fireworks.desc') },
|
||||
{ value: 'sparkle_rain', icon: _icon(P.star), label: t('color_strip.effect.sparkle_rain'), desc: t('color_strip.effect.sparkle_rain.desc') },
|
||||
{ value: 'lava_lamp', icon: _icon(P.flame), label: t('color_strip.effect.lava_lamp'), desc: t('color_strip.effect.lava_lamp.desc') },
|
||||
{ value: 'wave_interference',icon: _icon(P.rainbow), label: t('color_strip.effect.wave_interference'),desc: t('color_strip.effect.wave_interference.desc') },
|
||||
];
|
||||
if (_effectTypeIconSelect) { _effectTypeIconSelect.updateItems(items); return; }
|
||||
_effectTypeIconSelect = new IconSelect({ target: sel, items, columns: 2 });
|
||||
@@ -407,10 +417,37 @@ function _ensureEffectPaletteIconSelect() {
|
||||
const items = Object.entries(_PALETTE_COLORS).map(([key, pts]) => ({
|
||||
value: key, icon: _gradientStripHTML(pts), label: t(`color_strip.palette.${key}`),
|
||||
}));
|
||||
items.push({ value: 'custom', icon: _icon(P.pencil), label: t('color_strip.palette.custom') });
|
||||
if (_effectPaletteIconSelect) { _effectPaletteIconSelect.updateItems(items); return; }
|
||||
_effectPaletteIconSelect = new IconSelect({ target: sel, items, columns: 2 });
|
||||
}
|
||||
|
||||
function _ensureGradientEasingIconSelect() {
|
||||
const sel = document.getElementById('css-editor-gradient-easing') as HTMLSelectElement | null;
|
||||
if (!sel) return;
|
||||
const items = [
|
||||
{ value: 'linear', icon: _icon(P.trendingUp), label: t('color_strip.gradient.easing.linear'), desc: t('color_strip.gradient.easing.linear.desc') },
|
||||
{ value: 'ease_in_out', icon: _icon(P.activity), label: t('color_strip.gradient.easing.ease_in_out'), desc: t('color_strip.gradient.easing.ease_in_out.desc') },
|
||||
{ value: 'step', icon: _icon(P.layoutDashboard), label: t('color_strip.gradient.easing.step'), desc: t('color_strip.gradient.easing.step.desc') },
|
||||
{ value: 'cubic', icon: _icon(P.slidersHorizontal), label: t('color_strip.gradient.easing.cubic'), desc: t('color_strip.gradient.easing.cubic.desc') },
|
||||
];
|
||||
if (_gradientEasingIconSelect) { _gradientEasingIconSelect.updateItems(items); return; }
|
||||
_gradientEasingIconSelect = new IconSelect({ target: sel, items, columns: 2 });
|
||||
}
|
||||
|
||||
function _ensureCandleTypeIconSelect() {
|
||||
const sel = document.getElementById('css-editor-candlelight-type') as HTMLSelectElement | null;
|
||||
if (!sel) return;
|
||||
const items = [
|
||||
{ value: 'default', icon: _icon(P.flame), label: t('color_strip.candlelight.type.default'), desc: t('color_strip.candlelight.type.default.desc') },
|
||||
{ value: 'taper', icon: _icon(P.activity), label: t('color_strip.candlelight.type.taper'), desc: t('color_strip.candlelight.type.taper.desc') },
|
||||
{ value: 'votive', icon: _icon(P.lightbulb), label: t('color_strip.candlelight.type.votive'), desc: t('color_strip.candlelight.type.votive.desc') },
|
||||
{ value: 'bonfire', icon: _icon(P.zap), label: t('color_strip.candlelight.type.bonfire'), desc: t('color_strip.candlelight.type.bonfire.desc') },
|
||||
];
|
||||
if (_candleTypeIconSelect) { _candleTypeIconSelect.updateItems(items); return; }
|
||||
_candleTypeIconSelect = new IconSelect({ target: sel, items, columns: 2 });
|
||||
}
|
||||
|
||||
function _ensureAudioPaletteIconSelect() {
|
||||
const sel = document.getElementById('css-editor-audio-palette') as HTMLSelectElement | null;
|
||||
if (!sel) return;
|
||||
@@ -500,6 +537,8 @@ function _buildAnimationTypeItems(cssType: any) {
|
||||
items.push(
|
||||
{ value: 'gradient_shift', icon: _icon(P.fastForward), label: t('color_strip.animation.type.gradient_shift'), desc: t('color_strip.animation.type.gradient_shift.desc') },
|
||||
{ value: 'wave', icon: _icon(P.rainbow), label: t('color_strip.animation.type.wave'), desc: t('color_strip.animation.type.wave.desc') },
|
||||
{ value: 'noise_perturb', icon: _icon(P.activity), label: t('color_strip.animation.type.noise_perturb'), desc: t('color_strip.animation.type.noise_perturb.desc') },
|
||||
{ value: 'hue_rotate', icon: _icon(P.rotateCw), label: t('color_strip.animation.type.hue_rotate'), desc: t('color_strip.animation.type.hue_rotate.desc') },
|
||||
);
|
||||
}
|
||||
items.push(
|
||||
@@ -572,18 +611,23 @@ const _PALETTE_COLORS = {
|
||||
// Default palette per effect type
|
||||
export function onEffectTypeChange() {
|
||||
const et = (document.getElementById('css-editor-effect-type') as HTMLInputElement).value;
|
||||
// palette: all except meteor
|
||||
(document.getElementById('css-editor-effect-palette-group') as HTMLElement).style.display = et !== 'meteor' ? '' : 'none';
|
||||
// color picker: meteor only
|
||||
(document.getElementById('css-editor-effect-color-group') as HTMLElement).style.display = et === 'meteor' ? '' : 'none';
|
||||
// intensity: fire, meteor, aurora
|
||||
(document.getElementById('css-editor-effect-intensity-group') as HTMLElement).style.display =
|
||||
['fire', 'meteor', 'aurora'].includes(et) ? '' : 'none';
|
||||
// scale: plasma, noise, aurora
|
||||
(document.getElementById('css-editor-effect-scale-group') as HTMLElement).style.display =
|
||||
['plasma', 'noise', 'aurora'].includes(et) ? '' : 'none';
|
||||
// mirror: meteor only
|
||||
(document.getElementById('css-editor-effect-mirror-group') as HTMLElement).style.display = et === 'meteor' ? '' : 'none';
|
||||
// palette: all except meteor, comet, bouncing_ball (which use color picker)
|
||||
const usesColorPicker = ['meteor', 'comet', 'bouncing_ball'].includes(et);
|
||||
(document.getElementById('css-editor-effect-palette-group') as HTMLElement).style.display = !usesColorPicker ? '' : 'none';
|
||||
// color picker: meteor, comet, bouncing_ball
|
||||
(document.getElementById('css-editor-effect-color-group') as HTMLElement).style.display = usesColorPicker ? '' : 'none';
|
||||
// intensity: most effects use it
|
||||
const usesIntensity = ['fire', 'meteor', 'aurora', 'rain', 'comet', 'bouncing_ball', 'fireworks', 'sparkle_rain'].includes(et);
|
||||
(document.getElementById('css-editor-effect-intensity-group') as HTMLElement).style.display = usesIntensity ? '' : 'none';
|
||||
// scale: effects with spatial parameters
|
||||
const usesScale = ['plasma', 'noise', 'aurora', 'rain', 'lava_lamp', 'wave_interference'].includes(et);
|
||||
(document.getElementById('css-editor-effect-scale-group') as HTMLElement).style.display = usesScale ? '' : 'none';
|
||||
// mirror: meteor, comet
|
||||
(document.getElementById('css-editor-effect-mirror-group') as HTMLElement).style.display =
|
||||
['meteor', 'comet'].includes(et) ? '' : 'none';
|
||||
// custom palette visibility
|
||||
if (!usesColorPicker) onEffectPaletteChange();
|
||||
else (document.getElementById('css-editor-effect-custom-palette-group') as HTMLElement).style.display = 'none';
|
||||
// description
|
||||
const descEl = document.getElementById('css-editor-effect-type-desc') as HTMLElement | null;
|
||||
if (descEl) {
|
||||
@@ -594,6 +638,12 @@ export function onEffectTypeChange() {
|
||||
_autoGenerateCSSName();
|
||||
}
|
||||
|
||||
export function onEffectPaletteChange() {
|
||||
const palette = (document.getElementById('css-editor-effect-palette') as HTMLInputElement).value;
|
||||
const customGroup = document.getElementById('css-editor-effect-custom-palette-group') as HTMLElement;
|
||||
if (customGroup) customGroup.style.display = palette === 'custom' ? '' : 'none';
|
||||
}
|
||||
|
||||
/* ── Color Cycle helpers ──────────────────────────────────────── */
|
||||
|
||||
const _DEFAULT_CYCLE_COLORS = ['#ff0000', '#ffff00', '#00ff00', '#00ffff', '#0000ff', '#ff00ff'];
|
||||
@@ -1074,7 +1124,7 @@ export function createColorStripCard(source: ColorStripSource, pictureSourceMap:
|
||||
content: `
|
||||
<div class="card-header">
|
||||
<div class="card-title" title="${escapeHtml(source.name)}">
|
||||
${icon} ${escapeHtml(source.name)}
|
||||
${icon} <span class="card-title-text">${escapeHtml(source.name)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stream-card-props">
|
||||
@@ -1166,6 +1216,8 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
{ position: 1.0, color: [0, 0, 255] },
|
||||
]);
|
||||
_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 = '';
|
||||
@@ -1174,6 +1226,8 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
{ position: 1.0, color: [0, 0, 255] },
|
||||
]);
|
||||
_loadAnimationState(null);
|
||||
(document.getElementById('css-editor-gradient-easing') as HTMLSelectElement).value = 'linear';
|
||||
if (_gradientEasingIconSelect) _gradientEasingIconSelect.setValue('linear');
|
||||
},
|
||||
getPayload(name) {
|
||||
const gStops = getGradientStops();
|
||||
@@ -1189,6 +1243,7 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
...(s.colorRight ? { color_right: s.colorRight } : {}),
|
||||
})),
|
||||
animation: _getAnimationPayload(),
|
||||
easing: (document.getElementById('css-editor-gradient-easing') as HTMLSelectElement).value,
|
||||
};
|
||||
},
|
||||
},
|
||||
@@ -1205,6 +1260,10 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
(document.getElementById('css-editor-effect-scale') as HTMLInputElement).value = css.scale ?? 1.0;
|
||||
(document.getElementById('css-editor-effect-scale-val') as HTMLElement).textContent = parseFloat(css.scale ?? 1.0).toFixed(1);
|
||||
(document.getElementById('css-editor-effect-mirror') as HTMLInputElement).checked = css.mirror || false;
|
||||
// Custom palette
|
||||
const cpTextarea = document.getElementById('css-editor-effect-custom-palette') as HTMLTextAreaElement;
|
||||
if (cpTextarea) cpTextarea.value = css.custom_palette ? JSON.stringify(css.custom_palette) : '';
|
||||
onEffectPaletteChange();
|
||||
},
|
||||
reset() {
|
||||
(document.getElementById('css-editor-effect-type') as HTMLInputElement).value = 'fire';
|
||||
@@ -1215,6 +1274,8 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
(document.getElementById('css-editor-effect-scale') as HTMLInputElement).value = 1.0 as any;
|
||||
(document.getElementById('css-editor-effect-scale-val') as HTMLElement).textContent = '1.0';
|
||||
(document.getElementById('css-editor-effect-mirror') as HTMLInputElement).checked = false;
|
||||
const cpTextarea = document.getElementById('css-editor-effect-custom-palette') as HTMLTextAreaElement;
|
||||
if (cpTextarea) cpTextarea.value = '';
|
||||
},
|
||||
getPayload(name) {
|
||||
const payload: any = {
|
||||
@@ -1225,11 +1286,23 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
scale: parseFloat((document.getElementById('css-editor-effect-scale') as HTMLInputElement).value),
|
||||
mirror: (document.getElementById('css-editor-effect-mirror') as HTMLInputElement).checked,
|
||||
};
|
||||
// Meteor uses a color picker
|
||||
if (payload.effect_type === 'meteor') {
|
||||
// Meteor/comet/bouncing_ball use a color picker
|
||||
if (['meteor', 'comet', 'bouncing_ball'].includes(payload.effect_type)) {
|
||||
const hex = (document.getElementById('css-editor-effect-color') as HTMLInputElement).value;
|
||||
payload.color = [parseInt(hex.slice(1, 3), 16), parseInt(hex.slice(3, 5), 16), parseInt(hex.slice(5, 7), 16)];
|
||||
}
|
||||
// Custom palette
|
||||
if (payload.palette === 'custom') {
|
||||
const cpText = (document.getElementById('css-editor-effect-custom-palette') as HTMLTextAreaElement).value.trim();
|
||||
if (cpText) {
|
||||
try {
|
||||
payload.custom_palette = JSON.parse(cpText);
|
||||
} catch {
|
||||
cssEditorModal.showError('Invalid custom palette JSON');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return payload;
|
||||
},
|
||||
},
|
||||
@@ -1345,6 +1418,8 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
(document.getElementById('css-editor-daylight-real-time') as HTMLInputElement).checked = css.use_real_time || false;
|
||||
(document.getElementById('css-editor-daylight-latitude') as HTMLInputElement).value = css.latitude ?? 50.0;
|
||||
(document.getElementById('css-editor-daylight-latitude-val') as HTMLElement).textContent = parseFloat(css.latitude ?? 50.0).toFixed(0);
|
||||
(document.getElementById('css-editor-daylight-longitude') as HTMLInputElement).value = css.longitude ?? 0.0;
|
||||
(document.getElementById('css-editor-daylight-longitude-val') as HTMLElement).textContent = parseFloat(css.longitude ?? 0.0).toFixed(0);
|
||||
_syncDaylightSpeedVisibility();
|
||||
},
|
||||
reset() {
|
||||
@@ -1353,6 +1428,8 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
(document.getElementById('css-editor-daylight-real-time') as HTMLInputElement).checked = false;
|
||||
(document.getElementById('css-editor-daylight-latitude') as HTMLInputElement).value = 50.0 as any;
|
||||
(document.getElementById('css-editor-daylight-latitude-val') as HTMLElement).textContent = '50';
|
||||
(document.getElementById('css-editor-daylight-longitude') as HTMLInputElement).value = 0.0 as any;
|
||||
(document.getElementById('css-editor-daylight-longitude-val') as HTMLElement).textContent = '0';
|
||||
},
|
||||
getPayload(name) {
|
||||
return {
|
||||
@@ -1360,6 +1437,7 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
speed: parseFloat((document.getElementById('css-editor-daylight-speed') as HTMLInputElement).value),
|
||||
use_real_time: (document.getElementById('css-editor-daylight-real-time') as HTMLInputElement).checked,
|
||||
latitude: parseFloat((document.getElementById('css-editor-daylight-latitude') as HTMLInputElement).value),
|
||||
longitude: parseFloat((document.getElementById('css-editor-daylight-longitude') as HTMLInputElement).value),
|
||||
};
|
||||
},
|
||||
},
|
||||
@@ -1371,6 +1449,10 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
(document.getElementById('css-editor-candlelight-num-candles') as HTMLInputElement).value = css.num_candles ?? 3;
|
||||
(document.getElementById('css-editor-candlelight-speed') as HTMLInputElement).value = css.speed ?? 1.0;
|
||||
(document.getElementById('css-editor-candlelight-speed-val') as HTMLElement).textContent = parseFloat(css.speed ?? 1.0).toFixed(1);
|
||||
(document.getElementById('css-editor-candlelight-wind') as HTMLInputElement).value = css.wind_strength ?? 0.0;
|
||||
(document.getElementById('css-editor-candlelight-wind-val') as HTMLElement).textContent = parseFloat(css.wind_strength ?? 0.0).toFixed(1);
|
||||
(document.getElementById('css-editor-candlelight-type') as HTMLSelectElement).value = css.candle_type || 'default';
|
||||
if (_candleTypeIconSelect) _candleTypeIconSelect.setValue(css.candle_type || 'default');
|
||||
},
|
||||
reset() {
|
||||
(document.getElementById('css-editor-candlelight-color') as HTMLInputElement).value = '#ff9329';
|
||||
@@ -1379,6 +1461,10 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
(document.getElementById('css-editor-candlelight-num-candles') as HTMLInputElement).value = 3 as any;
|
||||
(document.getElementById('css-editor-candlelight-speed') as HTMLInputElement).value = 1.0 as any;
|
||||
(document.getElementById('css-editor-candlelight-speed-val') as HTMLElement).textContent = '1.0';
|
||||
(document.getElementById('css-editor-candlelight-wind') as HTMLInputElement).value = 0.0 as any;
|
||||
(document.getElementById('css-editor-candlelight-wind-val') as HTMLElement).textContent = '0.0';
|
||||
(document.getElementById('css-editor-candlelight-type') as HTMLSelectElement).value = 'default';
|
||||
if (_candleTypeIconSelect) _candleTypeIconSelect.setValue('default');
|
||||
},
|
||||
getPayload(name) {
|
||||
return {
|
||||
@@ -1387,6 +1473,8 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
|
||||
intensity: parseFloat((document.getElementById('css-editor-candlelight-intensity') as HTMLInputElement).value),
|
||||
num_candles: parseInt((document.getElementById('css-editor-candlelight-num-candles') as HTMLInputElement).value) || 3,
|
||||
speed: parseFloat((document.getElementById('css-editor-candlelight-speed') as HTMLInputElement).value),
|
||||
wind_strength: parseFloat((document.getElementById('css-editor-candlelight-wind') as HTMLInputElement).value),
|
||||
candle_type: (document.getElementById('css-editor-candlelight-type') as HTMLSelectElement).value,
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user