{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "command-palette",
  "title": "Command Palette",
  "registryDependencies": [
    "button",
    "command",
    "kbd"
  ],
  "files": [
    {
      "path": "components/ui/command-palette.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { SearchIcon } from \"lucide-react\"\n\nimport {\n  Command,\n  CommandEmpty,\n  CommandGroup,\n  CommandInput,\n  CommandItem,\n  CommandList,\n  CommandShortcut,\n} from \"@/components/ui/command\"\nimport { CommandDialog } from \"@/components/ui/command\"\nimport { Button } from \"@/components/ui/button\"\nimport { Kbd, KbdGroup } from \"@/components/ui/kbd\"\n\nexport type CommandPaletteItem = {\n  value: string\n  label: React.ReactNode\n  group?: string\n  description?: React.ReactNode\n  keywords?: string[]\n  shortcut?: string\n  icon?: React.ReactNode\n  disabled?: boolean\n  onSelect?: () => void\n}\n\ntype CommandPaletteProps = {\n  items: CommandPaletteItem[]\n  trigger?: React.ReactElement\n  placeholder?: string\n  emptyLabel?: string\n  title?: string\n  description?: string\n  shortcut?: string\n  open?: boolean\n  defaultOpen?: boolean\n  onOpenChange?: (open: boolean) => void\n}\n\nfunction CommandPalette({\n  items,\n  trigger,\n  placeholder = \"Search commands…\",\n  emptyLabel = \"No results found.\",\n  title = \"Command palette\",\n  description = \"Search and run a command.\",\n  shortcut = \"k\",\n  open: controlledOpen,\n  defaultOpen = false,\n  onOpenChange,\n}: CommandPaletteProps) {\n  const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n  const open = controlledOpen ?? uncontrolledOpen\n  const setOpen = React.useCallback(\n    (nextOpen: boolean) => {\n      if (controlledOpen === undefined) setUncontrolledOpen(nextOpen)\n      onOpenChange?.(nextOpen)\n    },\n    [controlledOpen, onOpenChange]\n  )\n\n  React.useEffect(() => {\n    function onKeyDown(event: KeyboardEvent) {\n      if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === shortcut.toLowerCase()) {\n        event.preventDefault()\n        setOpen(!open)\n      }\n    }\n\n    document.addEventListener(\"keydown\", onKeyDown)\n    return () => document.removeEventListener(\"keydown\", onKeyDown)\n  }, [open, setOpen, shortcut])\n\n  const groups = React.useMemo(() => {\n    const grouped = new Map<string, CommandPaletteItem[]>()\n    for (const item of items) {\n      const group = item.group ?? \"Commands\"\n      grouped.set(group, [...(grouped.get(group) ?? []), item])\n    }\n    return grouped\n  }, [items])\n\n  const triggerNode = trigger ?? (\n    <Button variant=\"outline\" className=\"justify-between gap-6\">\n      <span className=\"inline-flex items-center gap-2\">\n        <SearchIcon className=\"size-4\" />\n        Search\n      </span>\n      <KbdGroup>\n        <Kbd>⌘</Kbd>\n        <Kbd>{shortcut.toUpperCase()}</Kbd>\n      </KbdGroup>\n    </Button>\n  )\n\n  const triggerWithHandler = React.isValidElement(triggerNode)\n    ? (() => {\n        const triggerElement = triggerNode as React.ReactElement<{\n          onClick?: (event: React.MouseEvent<HTMLElement>) => void\n        }>\n        return React.cloneElement(triggerElement, {\n          onClick: (event) => {\n            triggerElement.props.onClick?.(event)\n            setOpen(true)\n          },\n        })\n      })()\n    : (\n        <Button variant=\"outline\" onClick={() => setOpen(true)}>\n          {triggerNode}\n        </Button>\n      )\n\n  return (\n    <>\n      {triggerWithHandler}\n      <CommandDialog\n        open={open}\n        onOpenChange={setOpen}\n        title={title}\n        description={description}\n        showCloseButton\n      >\n        <Command>\n          <CommandInput placeholder={placeholder} />\n          <CommandList>\n            <CommandEmpty>{emptyLabel}</CommandEmpty>\n            {[...groups.entries()].map(([group, groupItems]) => (\n              <CommandGroup key={group} heading={group}>\n                {groupItems.map((item) => (\n                  <CommandItem\n                    key={item.value}\n                    value={[item.value, item.keywords?.join(\" \")].filter(Boolean).join(\" \")}\n                    disabled={item.disabled}\n                    onSelect={() => {\n                      item.onSelect?.()\n                      setOpen(false)\n                    }}\n                  >\n                    {item.icon}\n                    <span className=\"min-w-0 flex-1\">\n                      <span className=\"block truncate\">{item.label}</span>\n                      {item.description && (\n                        <span className=\"block truncate text-xs text-muted-foreground\">\n                          {item.description}\n                        </span>\n                      )}\n                    </span>\n                    {item.shortcut && <CommandShortcut>{item.shortcut}</CommandShortcut>}\n                  </CommandItem>\n                ))}\n              </CommandGroup>\n            ))}\n          </CommandList>\n        </Command>\n      </CommandDialog>\n    </>\n  )\n}\n\nexport { CommandPalette }\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}