{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "select",
  "title": "Select",
  "description": "A shadcn-style select component built with Ark UI primitives.",
  "dependencies": ["@ark-ui/react", "lucide-react", "class-variance-authority"],
  "registryDependencies": ["button", "button-group"],
  "files": [
    {
      "path": "src/components/ui/select.tsx",
      "content": "\"use client\";\n\nimport { Portal } from \"@ark-ui/react/portal\";\nimport {\n  type CollectionItem,\n  createListCollection,\n  type ListCollection,\n  Select as SelectPrimitive,\n  type SelectRootProps,\n  SelectRootProvider,\n  type UseSelectContext,\n  type UseSelectReturn,\n  useListCollection,\n  useSelect,\n  useSelectContext,\n} from \"@ark-ui/react/select\";\nimport type { VariantProps } from \"class-variance-authority\";\nimport { CheckIcon, ChevronDownIcon, XIcon } from \"lucide-react\";\nimport {\n  type ComponentProps,\n  Fragment,\n  type ReactNode,\n  useEffect,\n  useMemo,\n} from \"react\";\nimport { Button, buttonVariants } from \"@/components/ui/button\";\nimport { ButtonGroup } from \"@/components/ui/button-group\";\nimport { cn } from \"@/lib/utils\";\n\nexport type {\n  CollectionItem,\n  ListCollection,\n  UseSelectContext,\n  UseSelectReturn,\n};\nexport {\n  createListCollection,\n  SelectRootProvider,\n  useListCollection,\n  useSelect,\n  useSelectContext,\n};\n\nexport type SelectProps<T extends CollectionItem = CollectionItem> = Omit<\n  SelectRootProps<T>,\n  \"collection\" | \"children\"\n> & {\n  children: ReactNode | ((api: UseSelectContext<T>) => ReactNode);\n} & (\n    | {\n        items: readonly T[];\n        groupBy?: (item: T, index: number) => string;\n        groupSort?:\n          | string[]\n          | \"asc\"\n          | \"desc\"\n          | ((a: string, b: string) => number);\n        itemToString?: (item: T) => string;\n        itemToValue?: (item: T) => string;\n        isItemDisabled?: (item: T) => boolean;\n      }\n    | { collection: ListCollection<T> }\n  );\n\n/** Strip `useListCollection` helpers from the root spread so they are not passed to a DOM node. */\ntype SelectListCollectionKeys<T extends CollectionItem> = {\n  items?: readonly T[];\n  groupBy?: (item: T, index: number) => string;\n  groupSort?: string[] | \"asc\" | \"desc\" | ((a: string, b: string) => number);\n  itemToString?: (item: T) => string;\n  itemToValue?: (item: T) => string;\n  isItemDisabled?: (item: T) => boolean;\n  collection?: ListCollection<T>;\n};\n\nexport const Select = <T extends CollectionItem = CollectionItem>(\n  props: SelectProps<T>,\n) => {\n  const {\n    positioning,\n    children,\n    items: itemsFromProps,\n    groupBy,\n    groupSort,\n    itemToString,\n    itemToValue,\n    isItemDisabled,\n    collection: collectionProp,\n    ...rootProps\n  } = props as SelectProps<T> & SelectListCollectionKeys<T>;\n  const items = itemsFromProps !== undefined ? itemsFromProps : [];\n\n  const { collection: defaultCollection, set } = useListCollection<T>({\n    initialItems: items,\n    groupBy,\n    groupSort,\n    itemToString,\n    itemToValue,\n    isItemDisabled,\n  });\n\n  const itemsKey = useMemo(\n    () =>\n      items\n        .map((item: T) =>\n          String(\n            itemToValue?.(item) ?? (item as { value?: string }).value ?? \"\",\n          ),\n        )\n        .join(\"\\uffff\"),\n    [items, itemToValue],\n  );\n\n  useEffect(() => {\n    // Sync `items` into the internal collection only when the *contents* change.\n    // Avoids infinite render loops when callers pass `items={[...arr]}`.\n    set([...items]);\n  }, [itemsKey]);\n\n  return (\n    <SelectPrimitive.Root\n      collection={collectionProp ?? defaultCollection}\n      data-slot=\"select-root\"\n      positioning={\n        positioning ?? { placement: \"bottom-start\", sameWidth: true }\n      }\n      {...rootProps}\n    >\n      {typeof children === \"function\" ? (\n        <SelectPrimitive.Context>\n          {(api) => children(api as UseSelectContext<T>)}\n        </SelectPrimitive.Context>\n      ) : (\n        children\n      )}\n      <SelectPrimitive.HiddenSelect />\n    </SelectPrimitive.Root>\n  );\n};\n\nexport const SelectControl = ({\n  className,\n  ...props\n}: SelectPrimitive.ControlProps) => (\n  <SelectPrimitive.Control\n    className={cn(\"flex w-full min-w-0 flex-col gap-1.5\", className)}\n    {...props}\n  />\n);\n\nexport const SelectTrigger = ({ ...props }: SelectPrimitive.TriggerProps) => (\n  <SelectPrimitive.Trigger data-slot=\"select-trigger\" {...props} />\n);\n\nexport type SelectValueProps<T extends CollectionItem = CollectionItem> = {\n  children?: (api: UseSelectContext<T>) => ReactNode;\n  placeholder?: string;\n  className?: string;\n};\n\nexport const SelectValue = <T extends CollectionItem = CollectionItem>({\n  children,\n  placeholder,\n  className,\n}: SelectValueProps<T>) => (\n  <SelectPrimitive.Context>\n    {(api) => {\n      if (children) {\n        return (\n          <span\n            {...api.getValueTextProps()}\n            className={cn(\"min-w-0 flex-1 truncate text-left\", className)}\n            data-slot=\"select-value\"\n          >\n            {children(api as UseSelectContext<T>)}\n          </span>\n        );\n      }\n      const text = api.valueAsString?.trim();\n      return (\n        <SelectPrimitive.ValueText\n          placeholder={placeholder}\n          className={cn(\n            \"min-w-0 flex-1 truncate text-left\",\n            !text && \"text-muted-foreground\",\n            className,\n          )}\n          data-slot=\"select-value\"\n        />\n      );\n    }}\n  </SelectPrimitive.Context>\n);\n\nexport type SelectPopupProps = SelectPrimitive.ContentProps & {\n  disablePortal?: boolean;\n};\n\nexport const SelectPopup = ({\n  className,\n  disablePortal,\n  ...props\n}: SelectPopupProps) => {\n  const inner = (\n    <SelectPrimitive.Content\n      className={cn(\n        \"outline-none flex max-h-[min(var(--available-height,20rem),20rem)] flex-col overflow-y-auto overscroll-contain rounded-lg border border-border bg-popover p-0.5 text-popover-foreground shadow-md\",\n        !disablePortal && \"z-50\",\n        className,\n      )}\n      data-slot=\"select-content\"\n      {...props}\n    />\n  );\n  return disablePortal ? (\n    inner\n  ) : (\n    <Portal>\n      <SelectPrimitive.Positioner>{inner}</SelectPrimitive.Positioner>\n    </Portal>\n  );\n};\n\nexport type SelectItemProps = SelectPrimitive.ItemProps;\n\nexport const SelectItem = ({ className, ...props }: SelectItemProps) => (\n  <SelectPrimitive.Item\n    className={cn(\n      \"relative flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm outline-none data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-accent data-highlighted:text-accent-foreground\",\n      className,\n    )}\n    data-slot=\"select-item\"\n    {...props}\n  />\n);\n\nexport const SelectItemText = ({\n  className,\n  ...props\n}: SelectPrimitive.ItemTextProps) => (\n  <SelectPrimitive.ItemText\n    className={cn(\"min-w-0 flex-1 truncate\", className)}\n    data-slot=\"select-item-text\"\n    {...props}\n  />\n);\n\nexport const SelectItemIndicator = ({\n  className,\n  children,\n  ...props\n}: SelectPrimitive.ItemIndicatorProps) => (\n  <SelectPrimitive.ItemIndicator\n    className={cn(\"text-primary\", className)}\n    data-slot=\"select-item-indicator\"\n    {...props}\n  >\n    {children ?? <CheckIcon className=\"size-4\" />}\n  </SelectPrimitive.ItemIndicator>\n);\n\nexport const SelectItemGroup = ({\n  className,\n  ...props\n}: SelectPrimitive.ItemGroupProps) => (\n  <SelectPrimitive.ItemGroup\n    className={cn(\"flex flex-col gap-0.5\", className)}\n    data-slot=\"select-item-group\"\n    {...props}\n  />\n);\n\nexport const SelectItemGroupLabel = ({\n  className,\n  ...props\n}: SelectPrimitive.ItemGroupLabelProps) => (\n  <SelectPrimitive.ItemGroupLabel\n    className={cn(\n      \"px-2 py-1 font-medium text-muted-foreground text-xs uppercase tracking-wide\",\n      className,\n    )}\n    data-slot=\"select-item-group-label\"\n    {...props}\n  />\n);\n\nexport const SelectSeparator = ({\n  className,\n  ...props\n}: ComponentProps<\"div\">) => (\n  <div\n    role=\"separator\"\n    className={cn(\"-mx-0.5 my-1 h-px bg-border\", className)}\n    data-slot=\"select-separator\"\n    {...props}\n  />\n);\n\nexport const SelectLabel = ({\n  className,\n  ...props\n}: SelectPrimitive.LabelProps) => (\n  <SelectPrimitive.Label\n    className={cn(\n      \"mb-1 block font-medium text-foreground text-sm select-none data-disabled:opacity-50\",\n      className,\n    )}\n    data-slot=\"select-label\"\n    {...props}\n  />\n);\n\nexport const SelectIndicator = ({\n  className,\n  children,\n  ...props\n}: SelectPrimitive.IndicatorProps) => (\n  <SelectPrimitive.Indicator\n    className={cn(\"shrink-0 text-muted-foreground\", className)}\n    data-slot=\"select-indicator\"\n    {...props}\n  >\n    {children ?? <ChevronDownIcon className=\"size-4 opacity-80\" aria-hidden />}\n  </SelectPrimitive.Indicator>\n);\n\nexport type SelectClearTriggerProps = SelectPrimitive.ClearTriggerProps;\n\nexport const SelectClearTrigger = ({ ...props }: SelectClearTriggerProps) => (\n  <SelectPrimitive.ClearTrigger {...props} />\n);\n\nexport type SelectTriggerFieldProps = {\n  showClear?: boolean;\n  className?: string;\n  children?: ReactNode;\n  hideIndicator?: boolean;\n  size?: VariantProps<typeof buttonVariants>[\"size\"];\n  containerClass?: string;\n};\n\nexport const SelectTriggerField = ({\n  showClear = false,\n  className,\n  children,\n  hideIndicator,\n  size = \"default\",\n  containerClass,\n  ...props\n}: SelectTriggerFieldProps) => (\n  <SelectPrimitive.Control asChild>\n    <ButtonGroup className={cn(\"w-full min-w-0\", containerClass)}>\n      <SelectTrigger {...props} asChild>\n        <Button\n          variant={\"outline\"}\n          size={size}\n          className={cn(\"flex-1\", className)}\n        >\n          {children}\n          {showClear ? (\n            <>\n              <SelectClearTrigger asChild>\n                <span role=\"button\">\n                  <XIcon />\n                </span>\n              </SelectClearTrigger>\n            </>\n          ) : null}\n          {!hideIndicator && (\n            <SelectIndicator className=\"inline-flex items-center justify-center\" />\n          )}\n        </Button>\n      </SelectTrigger>\n    </ButtonGroup>\n  </SelectPrimitive.Control>\n);\n\nexport const SelectList = ({\n  className,\n  ...props\n}: SelectPrimitive.ListProps) => (\n  <SelectPrimitive.List\n    className={cn(\"flex flex-col gap-0.5 p-0.5 outline-none\", className)}\n    data-slot=\"select-list\"\n    {...props}\n  />\n);\n\nexport type SelectGroupedListProps<T extends CollectionItem = CollectionItem> =\n  {\n    className?: string;\n    items: readonly T[];\n    children: (group: readonly [string, T[]]) => ReactNode;\n  };\n\nexport const SelectGroupedList = <T extends CollectionItem = CollectionItem>({\n  items,\n  className,\n  children,\n}: SelectGroupedListProps<T>) => {\n  // `useSelectContext()` is not generic over `T`; collection matches `T` when used under `<Select<T>>`.\n  const { collection } = useSelectContext();\n  const typedCollection = collection as ListCollection<T>;\n  const groups = typedCollection.group();\n  return (\n    <div\n      className={cn(\"flex flex-col gap-1 p-0.5 outline-none\", className)}\n      data-slot=\"select-grouped-list\"\n    >\n      {groups.map((tuple: readonly [string, (typeof items)[number][]]) => (\n        <Fragment key={tuple[0]}>{children(tuple)}</Fragment>\n      ))}\n    </div>\n  );\n};\n\nexport const SelectEmpty = ({ className, ...props }: ComponentProps<\"div\">) => {\n  const { collection } = useSelectContext();\n  if (collection.size > 0) {\n    return null;\n  }\n  return (\n    <div\n      role=\"presentation\"\n      className={cn(\n        \"rounded-md px-2 py-3 text-center text-muted-foreground text-sm\",\n        className,\n      )}\n      data-slot=\"select-empty\"\n      {...props}\n    />\n  );\n};\n\nexport const SelectContext = SelectPrimitive.Context;\n\nexport type SelectItemContextProps = SelectPrimitive.ItemContextProps;\n\nexport const SelectItemContext = SelectPrimitive.ItemContext;\n",
      "type": "registry:ui",
      "target": "src/components/ui/select.tsx"
    }
  ],
  "type": "registry:ui"
}
