Add command palette entity selector for all editor dropdowns
Replace plain <select> dropdowns with a searchable command palette modal for 16 entity selectors across 6 editors (targets, streams, CSS sources, value sources, audio sources, pattern templates). Unified EntityPalette singleton + EntitySelect wrapper in core/entity-palette.js. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,11 +20,12 @@ import { _splitOpenrgbZone } from './device-discovery.js';
|
||||
import { createKCTargetCard, patchKCTargetMetrics, connectKCWebSocket, disconnectKCWebSocket } from './kc-targets.js';
|
||||
import { createColorStripCard } from './color-strips.js';
|
||||
import {
|
||||
getValueSourceIcon, getTargetTypeIcon,
|
||||
getValueSourceIcon, getTargetTypeIcon, getDeviceTypeIcon, getColorStripIcon,
|
||||
ICON_CLONE, ICON_EDIT, ICON_START, ICON_STOP,
|
||||
ICON_LED, ICON_FPS, ICON_OVERLAY, ICON_LED_PREVIEW,
|
||||
ICON_GLOBE, ICON_RADIO, ICON_PLUG, ICON_FILM, ICON_SUN_DIM, ICON_TARGET_ICON, ICON_HELP,
|
||||
} from '../core/icons.js';
|
||||
import { EntitySelect } from '../core/entity-palette.js';
|
||||
import { wrapCard } from '../core/card-colors.js';
|
||||
import { CardSection } from '../core/card-sections.js';
|
||||
import { updateSubTabHash, updateTabBadge } from './tabs.js';
|
||||
@@ -224,6 +225,11 @@ function _updateBrightnessThresholdVisibility() {
|
||||
document.getElementById('target-editor-brightness-threshold-group').style.display = '';
|
||||
}
|
||||
|
||||
// ── EntitySelect instances for target editor ──
|
||||
let _deviceEntitySelect = null;
|
||||
let _cssEntitySelect = null;
|
||||
let _brightnessVsEntitySelect = null;
|
||||
|
||||
function _populateCssDropdown(selectedId = '') {
|
||||
const select = document.getElementById('target-editor-css-source');
|
||||
select.innerHTML = _editorCssSources.map(s =>
|
||||
@@ -235,12 +241,54 @@ function _populateBrightnessVsDropdown(selectedId = '') {
|
||||
const select = document.getElementById('target-editor-brightness-vs');
|
||||
let html = `<option value="">${t('targets.brightness_vs.none')}</option>`;
|
||||
_cachedValueSources.forEach(vs => {
|
||||
const icon = getValueSourceIcon(vs.source_type);
|
||||
html += `<option value="${vs.id}"${vs.id === selectedId ? ' selected' : ''}>${icon} ${escapeHtml(vs.name)}</option>`;
|
||||
html += `<option value="${vs.id}"${vs.id === selectedId ? ' selected' : ''}>${escapeHtml(vs.name)}</option>`;
|
||||
});
|
||||
select.innerHTML = html;
|
||||
}
|
||||
|
||||
function _ensureTargetEntitySelects() {
|
||||
// Device
|
||||
if (_deviceEntitySelect) _deviceEntitySelect.destroy();
|
||||
_deviceEntitySelect = new EntitySelect({
|
||||
target: document.getElementById('target-editor-device'),
|
||||
getItems: () => _targetEditorDevices.map(d => ({
|
||||
value: d.id,
|
||||
label: d.name,
|
||||
icon: getDeviceTypeIcon(d.device_type),
|
||||
desc: (d.device_type || 'wled').toUpperCase() + (d.url ? ` · ${d.url.replace(/^https?:\/\//, '')}` : ''),
|
||||
})),
|
||||
placeholder: t('palette.search'),
|
||||
});
|
||||
|
||||
// CSS source
|
||||
if (_cssEntitySelect) _cssEntitySelect.destroy();
|
||||
_cssEntitySelect = new EntitySelect({
|
||||
target: document.getElementById('target-editor-css-source'),
|
||||
getItems: () => _editorCssSources.map(s => ({
|
||||
value: s.id,
|
||||
label: s.name,
|
||||
icon: getColorStripIcon(s.source_type),
|
||||
desc: s.source_type,
|
||||
})),
|
||||
placeholder: t('palette.search'),
|
||||
});
|
||||
|
||||
// Brightness value source
|
||||
if (_brightnessVsEntitySelect) _brightnessVsEntitySelect.destroy();
|
||||
_brightnessVsEntitySelect = new EntitySelect({
|
||||
target: document.getElementById('target-editor-brightness-vs'),
|
||||
getItems: () => _cachedValueSources.map(vs => ({
|
||||
value: vs.id,
|
||||
label: vs.name,
|
||||
icon: getValueSourceIcon(vs.source_type),
|
||||
desc: vs.source_type,
|
||||
})),
|
||||
placeholder: t('palette.search'),
|
||||
allowNone: true,
|
||||
noneLabel: t('targets.brightness_vs.none'),
|
||||
});
|
||||
}
|
||||
|
||||
export async function showTargetEditor(targetId = null, cloneData = null) {
|
||||
try {
|
||||
// Load devices, CSS sources, and value sources for dropdowns
|
||||
@@ -334,6 +382,9 @@ export async function showTargetEditor(targetId = null, cloneData = null) {
|
||||
_populateBrightnessVsDropdown('');
|
||||
}
|
||||
|
||||
// Entity palette selectors
|
||||
_ensureTargetEntitySelects();
|
||||
|
||||
// Auto-name generation
|
||||
_targetNameManuallyEdited = !!(targetId || cloneData);
|
||||
document.getElementById('target-editor-name').oninput = () => { _targetNameManuallyEdited = true; };
|
||||
|
||||
Reference in New Issue
Block a user