{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "combobox",
  "title": "Combobox",
  "description": "A searchable controlled option picker built from Command and Popover.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "@rivelle/utils",
    "@rivelle/button",
    "@rivelle/command",
    "@rivelle/popover"
  ],
  "files": [
    {
      "path": "registry/nova/ui/combobox.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Check, ChevronsUpDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Command,\n  CommandEmpty,\n  CommandGroup,\n  CommandInput,\n  CommandItem,\n  CommandList,\n} from \"@/components/ui/command\";\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from \"@/components/ui/popover\";\n\nexport type ComboboxOption = {\n  value: string;\n  label: string;\n  disabled?: boolean;\n};\n\nfunction Combobox({\n  options,\n  value,\n  defaultValue,\n  onValueChange,\n  placeholder = \"Select an option\",\n  searchPlaceholder = \"Search...\",\n  emptyText = \"No results found.\",\n  disabled,\n  className,\n}: {\n  options: ComboboxOption[];\n  value?: string;\n  defaultValue?: string;\n  onValueChange?: (value: string) => void;\n  placeholder?: string;\n  searchPlaceholder?: string;\n  emptyText?: string;\n  disabled?: boolean;\n  className?: string;\n}) {\n  const [open, setOpen] = React.useState(false);\n  const [internalValue, setInternalValue] = React.useState(defaultValue ?? \"\");\n  const selectedValue = value ?? internalValue;\n  const selected = options.find((option) => option.value === selectedValue);\n\n  function select(nextValue: string) {\n    if (value === undefined) setInternalValue(nextValue);\n    onValueChange?.(nextValue);\n    setOpen(false);\n  }\n\n  return (\n    <Popover open={open} onOpenChange={setOpen}>\n      <PopoverTrigger asChild>\n        <Button\n          role=\"combobox\"\n          aria-expanded={open}\n          disabled={disabled}\n          variant=\"outline\"\n          className={cn(\n            \"h-11.5 w-full justify-between px-4 font-medium hover:-translate-y-0\",\n            !selected && \"text-muted-foreground\",\n            className,\n          )}\n        >\n          <span className=\"truncate\">{selected?.label ?? placeholder}</span>\n          <ChevronsUpDown className=\"ml-2 size-4 shrink-0 text-muted-foreground\" />\n        </Button>\n      </PopoverTrigger>\n      <PopoverContent\n        align=\"start\"\n        className=\"w-[var(--radix-popover-trigger-width)] p-0\"\n      >\n        <Command>\n          <CommandInput placeholder={searchPlaceholder} />\n          <CommandList>\n            <CommandEmpty>{emptyText}</CommandEmpty>\n            <CommandGroup>\n              {options.map((option) => (\n                <CommandItem\n                  disabled={option.disabled}\n                  key={option.value}\n                  value={option.label}\n                  onSelect={() => select(option.value)}\n                >\n                  <Check\n                    className={cn(\n                      \"size-4\",\n                      selectedValue === option.value\n                        ? \"opacity-100\"\n                        : \"opacity-0\",\n                    )}\n                  />\n                  {option.label}\n                </CommandItem>\n              ))}\n            </CommandGroup>\n          </CommandList>\n        </Command>\n      </PopoverContent>\n    </Popover>\n  );\n}\n\nexport { Combobox };\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}