"use client"; // Befehls-Palette (Cmd/Ctrl+K): schnelles Springen zwischen Plänen und Szenarien plus // die wichtigsten Aktionen -- der Effizienz-Pfad für geübte Nutzer, ohne der Maus- // Bedienung etwas wegzunehmen. import { useEffect, useMemo, useRef, useState } from "react"; import { CornerDownLeft, Search } from "lucide-react"; import type { PlanListItem } from "@/lib/types"; export interface PaletteAction { id: string; label: string; hint?: string; run: () => void; } export function CommandPalette({ open, onClose, plans, actions, onOpenScenario, }: { open: boolean; onClose: () => void; plans: PlanListItem[]; actions: PaletteAction[]; onOpenScenario: (id: string) => void; }) { const [query, setQuery] = useState(""); const [index, setIndex] = useState(0); const inputRef = useRef(null); const items = useMemo(() => { const scenarioItems: PaletteAction[] = plans.flatMap((p) => p.scenarios.map((s) => ({ id: `s-${s.id}`, label: `${p.name} · ${s.name}`, hint: "Szenario öffnen", run: () => onOpenScenario(s.id), })) ); const all = [...actions, ...scenarioItems]; const q = query.trim().toLowerCase(); if (!q) return all; return all.filter((i) => i.label.toLowerCase().includes(q)); }, [plans, actions, query, onOpenScenario]); useEffect(() => { if (open) { // eslint-disable-next-line react-hooks/set-state-in-effect -- Reset beim Öffnen setQuery(""); setIndex(0); requestAnimationFrame(() => inputRef.current?.focus()); } }, [open]); useEffect(() => { // eslint-disable-next-line react-hooks/set-state-in-effect -- Auswahl folgt der Eingabe setIndex(0); }, [query]); if (!open) return null; function choose(item: PaletteAction | undefined) { if (!item) return; onClose(); item.run(); } return (
e.stopPropagation()} className="ui-pop w-full max-w-lg overflow-hidden rounded-2xl border border-border bg-surface shadow-2xl" >
setQuery(e.target.value)} onKeyDown={(e) => { if (e.key === "ArrowDown") { e.preventDefault(); setIndex((i) => Math.min(i + 1, items.length - 1)); } else if (e.key === "ArrowUp") { e.preventDefault(); setIndex((i) => Math.max(i - 1, 0)); } else if (e.key === "Enter") { e.preventDefault(); choose(items[index]); } else if (e.key === "Escape") { onClose(); } }} placeholder="Plan, Szenario oder Aktion suchen…" className="w-full bg-transparent text-sm text-fg outline-none placeholder:text-faint" /> ESC
{items.length === 0 &&

Nichts gefunden.

} {items.slice(0, 40).map((item, i) => ( ))}
); }