import { useEffect, useMemo, useState } from 'react' import { createPortal } from 'react-dom' import { ArrowRight, FileText, Home, Image, Library, Search, Settings, UploadCloud, X } from 'lucide-react' import { useNavigate } from 'react-router-dom' import { preloadRoute } from '../lib/routePreload' import { useFocusTrap } from '../hooks/useFocusTrap' interface Command { label: string path: string group: string keywords: string icon: typeof Home } const COMMANDS: Command[] = [ { label: 'Home', path: '/', group: 'Navigate', keywords: 'dashboard status recent', icon: Home }, { label: 'New run', path: '/workspace', group: 'Create', keywords: 'workspace tools start', icon: FileText }, { label: 'Text to Video', path: '/workspace/text', group: 'Create', keywords: 'text ai lesson video', icon: FileText }, { label: 'HTML to Video', path: '/workspace/html', group: 'Create', keywords: 'html render playwright', icon: FileText }, { label: 'Image/PDF to Screenshots', path: '/workspace/image', group: 'Create', keywords: 'image pdf ocr screenshot', icon: Image }, { label: 'Screenshots to Video', path: '/workspace/screenshots', group: 'Create', keywords: 'screenshots export pptx mp4', icon: Image }, { label: 'YouTube to Video', path: '/workspace/youtube', group: 'Create', keywords: 'youtube timestamps video', icon: UploadCloud }, { label: 'YouTube to Screenshots', path: '/workspace/youtube-screenshots', group: 'Utility', keywords: 'youtube screenshots capture folder', icon: Image }, { label: 'Library', path: '/library', group: 'Manage', keywords: 'files outputs assets bundles', icon: Library }, { label: 'Publish', path: '/publish', group: 'Manage', keywords: 'youtube metadata upload checklist', icon: UploadCloud }, { label: 'Processes', path: '/processes', group: 'Monitor', keywords: 'runs logs queue progress', icon: FileText }, { label: 'Settings', path: '/settings', group: 'System', keywords: 'backend theme defaults diagnostics', icon: Settings }, ] export default function CommandPalette({ open, onClose, }: { open: boolean onClose: () => void }) { const nav = useNavigate() const dialogRef = useFocusTrap(open) const [query, setQuery] = useState('') useEffect(() => { if (!open) return const resetId = window.setTimeout(() => setQuery(''), 0) const onKey = (event: KeyboardEvent) => { if (event.key === 'Escape') onClose() } window.addEventListener('keydown', onKey) return () => { window.clearTimeout(resetId) window.removeEventListener('keydown', onKey) } }, [onClose, open]) const matches = useMemo(() => { const q = query.trim().toLowerCase() if (!q) return COMMANDS return COMMANDS.filter((command) => `${command.label} ${command.group} ${command.keywords}`.toLowerCase().includes(q), ) }, [query]) const run = (command: Command) => { preloadRoute(command.path) nav(command.path) onClose() } if (!open) return null return createPortal(
, document.body, ) }