{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "combobox",
  "type": "registry:ui",
  "title": "Combobox",
  "description": "Shadcn style combobox: a popover select with a filter input, check mark on the chosen item and an empty message. Built on Base UI popover for React.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "https://ui.minidev.pro/r/button.json",
    "https://ui.minidev.pro/r/popover.json",
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/combobox.tsx",
      "type": "registry:ui",
      "target": "components/ui/combobox.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { ChevronsUpDownIcon, CheckIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\"\n\ntype Item = { value: string; label: string }\n\n/** A button that opens a filterable list of options in a popover; uncontrolled unless a value is passed. */\ntype ComboboxProps = {\n  items?: Item[]\n  /** Controlled selection. Leave undefined for an uncontrolled combobox. */\n  value?: string\n  /** Initial selection for the uncontrolled combobox. */\n  defaultValue?: string\n  onChange?: (value: string) => void\n  placeholder?: string\n  disabled?: boolean\n  className?: string\n  emptyText?: string\n}\n\nconst SAMPLE_ITEMS: Item[] = [\n  { value: \"northwind\", label: \"Northwind Traders\" },\n  { value: \"acme\", label: \"Acme Industries\" },\n  { value: \"blue-harbor\", label: \"Blue Harbor Co.\" },\n  { value: \"cobalt\", label: \"Cobalt Systems\" },\n  { value: \"helix\", label: \"Helix Biotech\" },\n  { value: \"juniper\", label: \"Juniper Studio\" },\n  { value: \"meridian\", label: \"Meridian Freight\" },\n]\n\nfunction Combobox({ items = SAMPLE_ITEMS, value, defaultValue, onChange, placeholder = \"Select…\", disabled, className, emptyText = \"No results\" }: ComboboxProps) {\n  const [open, setOpen] = React.useState(false)\n  const [query, setQuery] = React.useState(\"\")\n  const [inner, setInner] = React.useState(defaultValue)\n  const current = value ?? inner\n  const selected = items.find((i) => i.value === current)\n  const filtered = items.filter((i) => i.label.toLowerCase().includes(query.toLowerCase()))\n  return (\n    <div data-slot=\"combobox\">\n      <Popover open={open} onOpenChange={setOpen}>\n      <PopoverTrigger\n        disabled={disabled}\n        aria-label={selected?.label ?? placeholder}\n        className={cn(\n          \"inline-flex h-9 w-64 items-center justify-between gap-2 rounded-lg border border-border bg-surface px-3 text-sm text-fg\",\n          \"shadow-highlight outline-none\",\n          \"hover:border-fg-subtle focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-bg\",\n          \"disabled:opacity-50\",\n          className\n        )}\n      >\n        <span className={cn(!selected && \"text-fg-subtle\")}>{selected?.label ?? placeholder}</span>\n        <ChevronsUpDownIcon className=\"size-4 text-fg-muted\" />\n      </PopoverTrigger>\n      <PopoverContent align=\"start\" className=\"w-64 p-1\">\n        <input\n          aria-label=\"Filter\"\n          value={query}\n          onChange={(e) => setQuery(e.target.value)}\n          placeholder=\"Filter…\"\n          className=\"mb-1 h-8 w-full rounded-md border border-border bg-surface px-2 text-sm outline-none focus-visible:border-accent\"\n        />\n        <div className=\"max-h-56 overflow-auto\">\n          {filtered.length === 0 ? (\n            <p className=\"px-2 py-2 text-xs text-fg-muted\">{emptyText}</p>\n          ) : (\n            filtered.map((item) => (\n              <button\n                key={item.value}\n                type=\"button\"\n                className={cn(\n                  \"flex w-full items-center gap-2 rounded-lg px-2.5 py-1.5 text-left text-sm\",\n                  \"transition-[background-color] duration-[70ms] hover:bg-sunken\",\n                  item.value === current && \"bg-sunken\"\n                )}\n                onClick={() => {\n                  if (value === undefined) setInner(item.value)\n                  onChange?.(item.value)\n                  setOpen(false)\n                  setQuery(\"\")\n                }}\n              >\n                <CheckIcon className={cn(\"size-4\", item.value === current ? \"opacity-100 text-accent\" : \"opacity-0\")} />\n                {item.label}\n              </button>\n            ))\n          )}\n        </div>\n      </PopoverContent>\n    </Popover>\n    </div>\n  )\n}\nexport { Combobox }\nexport type { ComboboxProps, Item as ComboboxItem }\n"
    }
  ]
}
