Add visual IconSelect selectors for effect, palette, gradient, waveform dropdowns
Replace plain <select> dropdowns with rich visual selectors: - Effect type: icon grid with descriptions - Effect/audio palette: gradient strip previews from color data - Gradient preset: gradient strip previews (13 presets) - Audio visualization: icon grid with descriptions - Notification effect: icon grid with descriptions - Waveform (value source): inline SVG shape previews Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -78,6 +78,27 @@ function _buildVSTypeItems() {
|
||||
}
|
||||
|
||||
let _vsTypeIconSelect = null;
|
||||
let _waveformIconSelect = null;
|
||||
|
||||
const _WAVEFORM_SVG = {
|
||||
sine: '<svg viewBox="0 0 60 24" width="60" height="24" fill="none" stroke="currentColor" stroke-width="2"><path d="M0 12 Q15 -4 30 12 Q45 28 60 12"/></svg>',
|
||||
triangle: '<svg viewBox="0 0 60 24" width="60" height="24" fill="none" stroke="currentColor" stroke-width="2"><path d="M0 12 L15 2 L45 22 L60 12"/></svg>',
|
||||
square: '<svg viewBox="0 0 60 24" width="60" height="24" fill="none" stroke="currentColor" stroke-width="2"><path d="M0 20 L0 4 L30 4 L30 20 L60 20 L60 4"/></svg>',
|
||||
sawtooth: '<svg viewBox="0 0 60 24" width="60" height="24" fill="none" stroke="currentColor" stroke-width="2"><path d="M0 20 L30 4 L30 20 L60 4"/></svg>',
|
||||
};
|
||||
|
||||
function _ensureWaveformIconSelect() {
|
||||
const sel = document.getElementById('value-source-waveform');
|
||||
if (!sel) return;
|
||||
const items = [
|
||||
{ value: 'sine', icon: _WAVEFORM_SVG.sine, label: t('value_source.waveform.sine') },
|
||||
{ value: 'triangle', icon: _WAVEFORM_SVG.triangle, label: t('value_source.waveform.triangle') },
|
||||
{ value: 'square', icon: _WAVEFORM_SVG.square, label: t('value_source.waveform.square') },
|
||||
{ value: 'sawtooth', icon: _WAVEFORM_SVG.sawtooth, label: t('value_source.waveform.sawtooth') },
|
||||
];
|
||||
if (_waveformIconSelect) { _waveformIconSelect.updateItems(items); return; }
|
||||
_waveformIconSelect = new IconSelect({ target: sel, items, columns: 4 });
|
||||
}
|
||||
|
||||
function _ensureVSTypeIconSelect() {
|
||||
const sel = document.getElementById('value-source-type');
|
||||
@@ -111,6 +132,7 @@ export async function showValueSourceModal(editData) {
|
||||
_setSlider('value-source-value', editData.value ?? 1.0);
|
||||
} else if (editData.source_type === 'animated') {
|
||||
document.getElementById('value-source-waveform').value = editData.waveform || 'sine';
|
||||
if (_waveformIconSelect) _waveformIconSelect.setValue(editData.waveform || 'sine');
|
||||
_setSlider('value-source-speed', editData.speed ?? 10);
|
||||
_setSlider('value-source-min-value', editData.min_value ?? 0);
|
||||
_setSlider('value-source-max-value', editData.max_value ?? 1);
|
||||
@@ -174,6 +196,7 @@ export function onValueSourceTypeChange() {
|
||||
if (_vsTypeIconSelect) _vsTypeIconSelect.setValue(type);
|
||||
document.getElementById('value-source-static-section').style.display = type === 'static' ? '' : 'none';
|
||||
document.getElementById('value-source-animated-section').style.display = type === 'animated' ? '' : 'none';
|
||||
if (type === 'animated') _ensureWaveformIconSelect();
|
||||
document.getElementById('value-source-audio-section').style.display = type === 'audio' ? '' : 'none';
|
||||
document.getElementById('value-source-adaptive-time-section').style.display = type === 'adaptive_time' ? '' : 'none';
|
||||
document.getElementById('value-source-adaptive-scene-section').style.display = type === 'adaptive_scene' ? '' : 'none';
|
||||
|
||||
Reference in New Issue
Block a user