feat: add IconGrid, EntityPicker controls and enhance search panel
CI / lint-and-check (push) Failing after 4m56s
CI / test (push) Has been skipped
CI / docker-build (push) Has been skipped

Port icon grid and entity picker patterns from wled-screen-controller.
IconGrid replaces plain <select> elements with visual icon grids for
known item sets (widget type, icon type, healthcheck method, permission
level). EntityPicker replaces search dropdowns with a command-palette
style overlay with keyboard navigation and filtering.

Enhance SearchDialog with keyboard navigation (arrow keys, Enter,
Escape), grouped results with section headers, active highlight,
and a footer with shortcut hints.
This commit is contained in:
2026-03-25 11:58:21 +03:00
parent 54a30ca4ca
commit 8d7847889e
11 changed files with 744 additions and 195 deletions
+19 -13
View File
@@ -1,5 +1,7 @@
<script lang="ts">
import { t } from 'svelte-i18n';
import IconGrid from '$lib/components/ui/IconGrid.svelte';
import type { IconGridItem } from '$lib/components/ui/IconGrid.svelte';
interface Props {
iconType: string;
@@ -9,9 +11,15 @@
let { iconType = $bindable('lucide'), iconValue = $bindable(''), onchange }: Props = $props();
function handleTypeChange(e: Event) {
const target = e.target as HTMLSelectElement;
iconType = target.value;
const iconTypeItems: IconGridItem[] = [
{ value: 'lucide', icon: '◇', label: $t('app.icon_lucide') ?? 'Lucide' },
{ value: 'simple', icon: '◆', label: $t('app.icon_simple') ?? 'Simple Icons' },
{ value: 'url', icon: '🔗', label: $t('app.icon_url') ?? 'Image URL' },
{ value: 'emoji', icon: '😀', label: $t('app.icon_emoji') ?? 'Emoji' }
];
function handleTypeChange(value: string) {
iconType = value;
iconValue = '';
onchange?.(iconType, iconValue);
}
@@ -27,16 +35,14 @@
<label class="block text-sm font-medium text-card-foreground">{$t('app.icon')}</label>
<div class="flex gap-2">
<select
value={iconType}
onchange={handleTypeChange}
class="rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-ring"
>
<option value="lucide">{$t('app.icon_lucide')}</option>
<option value="simple">{$t('app.icon_simple')}</option>
<option value="url">{$t('app.icon_url')}</option>
<option value="emoji">{$t('app.icon_emoji')}</option>
</select>
<div class="w-44 shrink-0">
<IconGrid
items={iconTypeItems}
value={iconType}
onchange={handleTypeChange}
columns={2}
/>
</div>
<input
type="text"