{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "command-palette",
  "type": "registry:ui",
  "title": "Command Palette",
  "description": "A ⌘K search palette with live filtering, arrow-key navigation and an Enter action per item.",
  "files": [
    {
      "path": "registry/ui/command-palette.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nexport interface CommandItem {\n  label: string;\n  hint?: string;\n  onSelect?: () => void;\n}\n\nexport interface CommandPaletteProps {\n  items: CommandItem[];\n  placeholder?: string;\n  className?: string;\n}\n\nexport function CommandPalette({ items, placeholder = \"Search…\", className = \"\" }: CommandPaletteProps) {\n  const [query, setQuery] = React.useState(\"\");\n  const [active, setActive] = React.useState(0);\n  const inputRef = React.useRef<HTMLInputElement>(null);\n\n  const results = items.filter((item) => item.label.toLowerCase().includes(query.toLowerCase()));\n\n  React.useEffect(() => setActive(0), [query]);\n\n  React.useEffect(() => {\n    const onKey = (e: KeyboardEvent) => {\n      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === \"k\") {\n        e.preventDefault();\n        inputRef.current?.focus();\n      }\n    };\n    window.addEventListener(\"keydown\", onKey);\n    return () => window.removeEventListener(\"keydown\", onKey);\n  }, []);\n\n  const onKeyDown = (e: React.KeyboardEvent) => {\n    if (e.key === \"ArrowDown\") {\n      e.preventDefault();\n      setActive((i) => Math.min(i + 1, results.length - 1));\n    } else if (e.key === \"ArrowUp\") {\n      e.preventDefault();\n      setActive((i) => Math.max(i - 1, 0));\n    } else if (e.key === \"Enter\") {\n      results[active]?.onSelect?.();\n    }\n  };\n\n  return (\n    <div\n      className={[\n        \"w-full max-w-[420px] overflow-hidden rounded-2xl border border-white/15 bg-zinc-950\",\n        \"shadow-[0_30px_80px_-30px_rgba(56,189,248,.25)]\",\n        className,\n      ].join(\" \")}\n    >\n      <div className=\"flex items-center gap-2.5 border-b border-white/10 px-3.5 py-3 text-zinc-500\">\n        <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n          <circle cx=\"11\" cy=\"11\" r=\"7\" />\n          <path d=\"m20 20-3.5-3.5\" />\n        </svg>\n        <input\n          ref={inputRef}\n          value={query}\n          onChange={(e) => setQuery(e.target.value)}\n          onKeyDown={onKeyDown}\n          placeholder={placeholder}\n          className=\"min-w-0 flex-1 bg-transparent text-sm text-zinc-100 outline-none placeholder:text-zinc-500\"\n        />\n        <kbd className=\"rounded-md border border-white/15 px-1.5 py-0.5 font-mono text-[11px] text-zinc-400\">⌘K</kbd>\n      </div>\n      <ul role=\"listbox\" className=\"p-1.5\">\n        {results.length === 0 && <li className=\"px-2.5 py-6 text-center text-[13px] text-zinc-500\">No results</li>}\n        {results.map((item, i) => (\n          <li\n            key={item.label}\n            role=\"option\"\n            aria-selected={i === active}\n            onMouseEnter={() => setActive(i)}\n            onClick={item.onSelect}\n            className={[\n              \"flex cursor-pointer justify-between rounded-lg px-2.5 py-2 text-[13px] transition-colors\",\n              i === active ? \"bg-sky-300/10 text-zinc-100\" : \"text-zinc-400\",\n            ].join(\" \")}\n          >\n            <span>{item.label}</span>\n            {item.hint && (\n              <span className={[\"font-mono text-[11px]\", i === active ? \"text-sky-300\" : \"text-zinc-500\"].join(\" \")}>\n                {item.hint}\n              </span>\n            )}\n          </li>\n        ))}\n      </ul>\n    </div>\n  );\n}\n"
    }
  ]
}