{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "select",
  "title": "Ninaero select",
  "dependencies": [
    "@base-ui/react@^1.9.0",
    "cn@^0.4.0"
  ],
  "registryDependencies": [
    "https://ninaero.pages.dev/r/theme.json",
    "https://ninaero.pages.dev/r/icons.json",
    "https://ninaero.pages.dev/r/sound-provider.json"
  ],
  "files": [
    {
      "path": "registry/ninaero/ui/select.tsx",
      "content": "\"use client\";\n\nimport { Select as SelectPrimitive } from \"@base-ui/react/select\";\nimport { cn } from \"cn\";\nimport type * as React from \"react\";\n\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"@/lib/icons\";\n\nimport { HighlightSound, SoundGroup, useControlSound, HoverSound } from \"./sound-feedback\";\n\nfunction Select<Value, Multiple extends boolean | undefined = false>({\n  sound = true,\n  onValueChange,\n  ...props\n}: SelectPrimitive.Root.Props<Value, Multiple> & { sound?: boolean }) {\n  const { play } = useControlSound(sound);\n  return (\n    <SoundGroup sound={sound}>\n      <SelectPrimitive.Root\n        {...props}\n        onValueChange={(value, details) => {\n          onValueChange?.(value, details);\n          if (\n            !details.isCanceled &&\n            (details.reason === \"item-press\" || details.reason === \"list-navigation\")\n          ) {\n            play(\"tap\");\n          }\n        }}\n      />\n    </SoundGroup>\n  );\n}\n\nfunction SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {\n  return (\n    <SelectPrimitive.Group\n      data-slot=\"select-group\"\n      className={cn(\"scroll-my-1\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {\n  return (\n    <SelectPrimitive.Value\n      data-slot=\"select-value\"\n      className={cn(\"flex flex-1 text-left\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction SelectTrigger({\n  className,\n  size = \"default\",\n  children,\n  sound = true,\n  ...props\n}: SelectPrimitive.Trigger.Props & {\n  size?: \"sm\" | \"default\";\n} & { sound?: boolean }) {\n  return (\n    <HoverSound sound={sound}>\n      <SelectPrimitive.Trigger\n        data-slot=\"select-trigger\"\n        data-size={size}\n        className={cn(\n          \"ninaero-select-trigger flex w-fit items-center justify-between gap-2 px-(--field-padding-inline) py-1 text-sm type-body leading-5 whitespace-nowrap select-none disabled:cursor-not-allowed data-disabled:cursor-not-allowed data-[size=default]:h-(--field-height) data-[size=sm]:h-7 data-[size=sm]:gap-1 data-[size=sm]:px-2 data-[size=sm]:text-[0.8rem] data-[size=sm]:leading-4 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 data-[size=sm]:*:data-[slot=select-value]:gap-1 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n          className,\n        )}\n        {...props}\n      >\n        {children}\n        <SelectPrimitive.Icon\n          render={<ChevronDownIcon className=\"ninaero-select-icon pointer-events-none size-4\" />}\n        />\n      </SelectPrimitive.Trigger>\n    </HoverSound>\n  );\n}\n\nfunction SelectContent({\n  className,\n  children,\n  side = \"bottom\",\n  sideOffset = 4,\n  align = \"center\",\n  alignOffset = 0,\n  alignItemWithTrigger = true,\n  ...props\n}: SelectPrimitive.Popup.Props &\n  Pick<\n    SelectPrimitive.Positioner.Props,\n    \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\" | \"alignItemWithTrigger\"\n  >) {\n  return (\n    <SelectPrimitive.Portal>\n      <SelectPrimitive.Positioner\n        side={side}\n        sideOffset={sideOffset}\n        align={align}\n        alignOffset={alignOffset}\n        alignItemWithTrigger={alignItemWithTrigger}\n        className=\"isolate z-50\"\n      >\n        <SelectPrimitive.Popup\n          data-slot=\"select-content\"\n          data-align-trigger={alignItemWithTrigger}\n          className={cn(\n            \"ninaero-popover ninaero-select-content relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-36 overflow-x-hidden overflow-y-auto p-2\",\n            className,\n          )}\n          {...props}\n        >\n          <SelectScrollUpButton />\n          <SelectPrimitive.List>{children}</SelectPrimitive.List>\n          <SelectScrollDownButton />\n        </SelectPrimitive.Popup>\n      </SelectPrimitive.Positioner>\n    </SelectPrimitive.Portal>\n  );\n}\n\nfunction SelectLabel({ className, ...props }: SelectPrimitive.GroupLabel.Props) {\n  return (\n    <SelectPrimitive.GroupLabel\n      data-slot=\"select-label\"\n      className={cn(\"px-3 py-1 text-xs text-muted-foreground\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction SelectItem({ className, children, render, ...props }: SelectPrimitive.Item.Props) {\n  return (\n    <SelectPrimitive.Item\n      data-slot=\"select-item\"\n      className={cn(\n        \"ninaero-select-item relative flex min-h-8 w-full cursor-default items-center gap-2 py-1 pr-8 pl-3 text-sm type-body leading-5 select-none data-disabled:cursor-not-allowed [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2\",\n        className,\n      )}\n      {...props}\n      render={(elementProps, state) => (\n        <HighlightSound elementProps={elementProps} state={state} render={render} />\n      )}\n    >\n      <SelectPrimitive.ItemText className=\"flex flex-1 shrink-0 gap-2 whitespace-nowrap\">\n        {children}\n      </SelectPrimitive.ItemText>\n      <SelectPrimitive.ItemIndicator\n        render={\n          <span className=\"pointer-events-none absolute right-2 flex size-4 items-center justify-center\" />\n        }\n      >\n        <CheckIcon className=\"pointer-events-none\" />\n      </SelectPrimitive.ItemIndicator>\n    </SelectPrimitive.Item>\n  );\n}\n\nfunction SelectSeparator({ className, ...props }: SelectPrimitive.Separator.Props) {\n  return (\n    <SelectPrimitive.Separator\n      data-slot=\"select-separator\"\n      className={cn(\"pointer-events-none my-1 h-px bg-border\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction SelectScrollUpButton({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>) {\n  return (\n    <SelectPrimitive.ScrollUpArrow\n      data-slot=\"select-scroll-up-button\"\n      className={cn(\n        \"top-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4\",\n        className,\n      )}\n      {...props}\n    >\n      <ChevronUpIcon />\n    </SelectPrimitive.ScrollUpArrow>\n  );\n}\n\nfunction SelectScrollDownButton({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>) {\n  return (\n    <SelectPrimitive.ScrollDownArrow\n      data-slot=\"select-scroll-down-button\"\n      className={cn(\n        \"bottom-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4\",\n        className,\n      )}\n      {...props}\n    >\n      <ChevronDownIcon />\n    </SelectPrimitive.ScrollDownArrow>\n  );\n}\n\nexport {\n  Select,\n  SelectContent,\n  SelectGroup,\n  SelectItem,\n  SelectLabel,\n  SelectScrollDownButton,\n  SelectScrollUpButton,\n  SelectSeparator,\n  SelectTrigger,\n  SelectValue,\n};\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}