// Command palette — ⌘K const CommandPalette = ({ open, onClose }) => { const D = PORTFOLIO_DATA; const [q, setQ] = React.useState(""); const [active, setActive] = React.useState(0); const inputRef = React.useRef(null); React.useEffect(() => { if (open) { setQ(""); setActive(0); setTimeout(() => inputRef.current?.focus(), 50); } }, [open]); const items = React.useMemo(() => { const base = [ { group: "Navigate", label: "Go to Work", icon: Icons.Cube, action: () => location.hash = "#work" }, { group: "Navigate", label: "Go to Stack", icon: Icons.Code, action: () => location.hash = "#stack" }, { group: "Navigate", label: "Go to Agent showcase", icon: Icons.Sparkles, action: () => location.hash = "#agents" }, { group: "Navigate", label: "Go to Timeline", icon: Icons.Bolt, action: () => location.hash = "#timeline" }, { group: "Navigate", label: "Go to Contact", icon: Icons.Mail, action: () => location.hash = "#contact" }, ...D.projects.map(p => ({ group: "Projects", label: p.name, sub: p.kind, icon: Icons.Cube, action: () => location.hash = "#work", })), { group: "Action", label: "Email me directly", icon: Icons.Mail, action: () => window.location.href = `mailto:${D.brand.email}` }, { group: "Action", label: "Open GitHub", icon: Icons.Github, action: () => window.open(D.brand.socials.github) }, { group: "Action", label: "Open LinkedIn", icon: Icons.LinkedIn, action: () => window.open(D.brand.socials.linkedin) }, { group: "Action", label: "Toggle theme", icon: Icons.Sun, action: () => window.dispatchEvent(new CustomEvent("aura:toggle-theme")) }, ]; if (!q) return base; const Q = q.toLowerCase(); return base.filter(i => i.label.toLowerCase().includes(Q) || (i.sub && i.sub.toLowerCase().includes(Q))); }, [q]); React.useEffect(() => { setActive(0); }, [q]); const onKey = (e) => { if (e.key === "ArrowDown") { e.preventDefault(); setActive(a => Math.min(a + 1, items.length - 1)); } else if (e.key === "ArrowUp") { e.preventDefault(); setActive(a => Math.max(a - 1, 0)); } else if (e.key === "Enter") { e.preventDefault(); if (items[active]) { items[active].action(); onClose(); } } else if (e.key === "Escape") { onClose(); } }; if (!open) return null; // group items const groups = items.reduce((acc, it, idx) => { (acc[it.group] = acc[it.group] || []).push({ ...it, idx }); return acc; }, {}); return (