{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "select",
  "title": "Select",
  "description": "A searchable-free listbox for choosing a single value, built on Base UI.",
  "dependencies": [
    "@base-ui/react",
    "lucide-react"
  ],
  "registryDependencies": [
    "utils",
    "scroll-area"
  ],
  "files": [
    {
      "path": "registry/base/ui/select.tsx",
      "content": "\"use client\"\n\nimport { Select as SelectPrimitive } from \"@base-ui/react/select\"\nimport { CheckIcon, ChevronDownIcon } from \"lucide-react\"\nimport * as React from \"react\"\n\nimport { ScrollArea } from \"@/components/ui/scroll-area\"\nimport { cn } from \"@/lib/utils\"\n\n/**\n * SelectContent renders through a Portal, so it doesn't inherit `dir` from a\n * nearby wrapper (only from document.documentElement). SelectTrigger\n * measures the ambient direction where it's actually rendered and pushes it\n * here so SelectContent can apply it explicitly to the portaled popup.\n */\nconst SelectDirContext = React.createContext<{\n  dir: \"ltr\" | \"rtl\"\n  setDir: (dir: \"ltr\" | \"rtl\") => void\n}>({ dir: \"ltr\", setDir: () => {} })\n\nfunction Select<Value, Multiple extends boolean | undefined = false>({\n  ...props\n}: SelectPrimitive.Root.Props<Value, Multiple>) {\n  const [dir, setDir] = React.useState<\"ltr\" | \"rtl\">(\"ltr\")\n  const contextValue = React.useMemo(() => ({ dir, setDir }), [dir])\n\n  return (\n    <SelectDirContext.Provider value={contextValue}>\n      <SelectPrimitive.Root data-slot=\"select\" {...props} />\n    </SelectDirContext.Provider>\n  )\n}\n\nfunction SelectTrigger({\n  className,\n  children,\n  ...props\n}: SelectPrimitive.Trigger.Props) {\n  const ref = React.useRef<HTMLButtonElement>(null)\n  const { setDir } = React.useContext(SelectDirContext)\n\n  React.useEffect(() => {\n    function update() {\n      if (!ref.current) return\n      setDir(getComputedStyle(ref.current).direction === \"rtl\" ? \"rtl\" : \"ltr\")\n    }\n\n    update()\n\n    const observer = new MutationObserver(update)\n    observer.observe(document.documentElement, {\n      attributes: true,\n      attributeFilter: [\"dir\"],\n      subtree: true,\n    })\n\n    return () => observer.disconnect()\n  }, [setDir])\n\n  return (\n    <SelectPrimitive.Trigger\n      ref={ref}\n      data-slot=\"select-trigger\"\n      className={cn(\n        \"flex h-8 w-full items-center justify-between gap-1.5 rounded-lg border border-border bg-background px-2.5 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-[placeholder]:text-muted-foreground data-[popup-open]:border-ring\",\n        className\n      )}\n      {...props}\n    >\n      {children}\n      <SelectPrimitive.Icon className=\"flex shrink-0 items-center justify-center text-muted-foreground\">\n        <ChevronDownIcon className=\"size-4\" />\n      </SelectPrimitive.Icon>\n    </SelectPrimitive.Trigger>\n  )\n}\n\nfunction SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {\n  return (\n    <SelectPrimitive.Value\n      data-slot=\"select-value\"\n      className={cn(\"min-w-0 truncate\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction SelectContent({\n  className,\n  sideOffset = 6,\n  children,\n  ...props\n}: SelectPrimitive.Positioner.Props & {\n  sideOffset?: number\n}) {\n  const { dir } = React.useContext(SelectDirContext)\n\n  return (\n    <SelectPrimitive.Portal>\n      <SelectPrimitive.Positioner\n        dir={dir}\n        data-slot=\"select-positioner\"\n        sideOffset={sideOffset}\n        className=\"z-50 outline-none\"\n        // Base UI's default alignItemWithTrigger={true} tries to overlay the\n        // selected item's text on top of the trigger's own text (native-\n        // <select>-like UX), computed via a custom position:fixed + manual\n        // measurement path instead of normal anchor-based floating-ui\n        // placement. That measurement path was producing a popup positioned\n        // at (0,0) with zero size in this app -- reproducible even on this\n        // component's own bare doc-page demo. Falling back to standard\n        // anchor-below-trigger placement sidesteps that measurement path\n        // entirely and is more predictable for custom-styled triggers.\n        alignItemWithTrigger={false}\n        {...props}\n      >\n        <SelectPrimitive.Popup\n          data-slot=\"select-content\"\n          className={cn(\n            \"flex max-h-80 w-[var(--anchor-width)] min-w-40 origin-[var(--transform-origin)] flex-col overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-md duration-150 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n            className\n          )}\n        >\n          <ScrollArea className=\"min-h-0 flex-1\">\n            <SelectPrimitive.List className=\"p-1\">\n              {children}\n            </SelectPrimitive.List>\n          </ScrollArea>\n        </SelectPrimitive.Popup>\n      </SelectPrimitive.Positioner>\n    </SelectPrimitive.Portal>\n  )\n}\n\nfunction SelectItem({\n  className,\n  children,\n  ...props\n}: SelectPrimitive.Item.Props) {\n  return (\n    <SelectPrimitive.Item\n      data-slot=\"select-item\"\n      className={cn(\n        \"relative flex cursor-default items-center gap-2 rounded-md py-1.5 ps-7 pe-2 text-sm text-muted-foreground outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-muted data-[highlighted]:text-foreground data-[selected]:text-foreground\",\n        className\n      )}\n      {...props}\n    >\n      <SelectPrimitive.ItemIndicator className=\"absolute start-2 inline-flex items-center justify-center\">\n        <CheckIcon className=\"size-3.5\" />\n      </SelectPrimitive.ItemIndicator>\n      <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n    </SelectPrimitive.Item>\n  )\n}\n\nfunction SelectGroup({ ...props }: SelectPrimitive.Group.Props) {\n  return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />\n}\n\nfunction SelectGroupLabel({\n  className,\n  ...props\n}: SelectPrimitive.GroupLabel.Props) {\n  return (\n    <SelectPrimitive.GroupLabel\n      data-slot=\"select-group-label\"\n      className={cn(\n        \"px-2 py-1.5 text-xs font-medium text-muted-foreground\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SelectSeparator({\n  className,\n  ...props\n}: SelectPrimitive.Separator.Props) {\n  return (\n    <SelectPrimitive.Separator\n      data-slot=\"select-separator\"\n      className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Select,\n  SelectContent,\n  SelectGroup,\n  SelectGroupLabel,\n  SelectItem,\n  SelectSeparator,\n  SelectTrigger,\n  SelectValue,\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}