{
  "name": "select",
  "type": "registry:ui",
  "title": "Select",
  "description": "A small known set of options for single or multiple selection without text search.",
  "registryDependencies": [
    "@siteplane/base"
  ],
  "dependencies": [
    "@base-ui/react@1.5.0",
    "class-variance-authority@0.7.1",
    "lucide-react@1.18.0"
  ],
  "files": [
    {
      "path": "src/components/ui/icons.tsx",
      "type": "registry:ui",
      "content": "import type React from \"react\";\n\n// Siteplane-UI-Haken-Glyphe (bewusst andere Geometrie als lucide `Check`).\n// Einzige Quelle fuer den statischen Selected-Marker in Select, Combobox, Menu,\n// ContextMenu und Drawer. (Die Checkbox nutzt eine eigene, ueber\n// `siteplane-checkbox-check` animierte Variante und bleibt davon unberuehrt.)\nexport function CheckIcon(props: React.ComponentProps<\"svg\">): React.ReactElement {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      fill=\"none\"\n      height=\"24\"\n      stroke=\"currentColor\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      strokeWidth=\"2\"\n      viewBox=\"0 0 24 24\"\n      width=\"24\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...props}\n    >\n      <path d=\"M5.252 12.7 10.2 18.63 18.748 5.37\" />\n    </svg>\n  );\n}\n"
    },
    {
      "path": "src/components/ui/select.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { Select as SelectPrimitive } from \"@base-ui/react/select\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport {\n  ChevronDownIcon,\n  ChevronsUpDownIcon,\n  ChevronUpIcon,\n} from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  SiteplaneUIPortalScope,\n  useResolvedControlSize,\n} from \"@/components/ui/siteplane-provider\";\nimport { CheckIcon } from \"@/components/ui/icons\";\nimport { surfaceClassNames } from \"@/components/ui/surface\";\n\nexport function Select<Value, Multiple extends boolean | undefined = false>(\n  props: SelectPrimitive.Root.Props<Value, Multiple>,\n): React.ReactElement {\n  return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nexport const selectTriggerVariants = cva(\n  cn(\n    surfaceClassNames.formControlTrigger,\n    \"min-h-9 min-w-36 items-center justify-between gap-2 px-[calc(--spacing(3)-1px)] sm:min-h-8 [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n  ),\n  {\n    defaultVariants: {\n      size: \"default\",\n    },\n    variants: {\n      size: {\n        default: \"\",\n        lg: \"min-h-10 sm:min-h-9\",\n        sm: \"min-h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:min-h-7\",\n        xl: \"min-h-14 px-[calc(--spacing(4)-1px)] text-base sm:min-h-14 sm:text-base\",\n      },\n    },\n  },\n);\n\nexport const selectTriggerIconClassName = \"-me-1 size-4.5 opacity-80 sm:size-4\";\n\nexport interface SelectButtonProps extends useRender.ComponentProps<\"button\"> {\n  size?: VariantProps<typeof selectTriggerVariants>[\"size\"];\n}\n\nexport function SelectButton({\n  className,\n  size,\n  render,\n  children,\n  ...props\n}: SelectButtonProps): React.ReactElement {\n  const typeValue: React.ButtonHTMLAttributes<HTMLButtonElement>[\"type\"] =\n    render ? undefined : \"button\";\n  const resolvedSize = useResolvedControlSize(size);\n\n  const defaultProps = {\n    children: (\n      <>\n        <span className=\"flex-1 truncate in-data-placeholder:text-muted-foreground/72\">\n          {children}\n        </span>\n        <ChevronsUpDownIcon className={selectTriggerIconClassName} />\n      </>\n    ),\n    className: cn(\n      selectTriggerVariants({ size: resolvedSize }),\n      \"min-w-0\",\n      className,\n    ),\n    \"data-slot\": \"select-button\",\n    type: typeValue,\n  };\n\n  return useRender({\n    defaultTagName: \"button\",\n    props: mergeProps<\"button\">(defaultProps, props),\n    render,\n  });\n}\n\nexport function SelectTrigger({\n  className,\n  size,\n  children,\n  ...props\n}: SelectPrimitive.Trigger.Props &\n  VariantProps<typeof selectTriggerVariants>): React.ReactElement {\n  const resolvedSize = useResolvedControlSize(size);\n\n  return (\n    <SelectPrimitive.Trigger\n      className={cn(selectTriggerVariants({ size: resolvedSize }), className)}\n      data-slot=\"select-trigger\"\n      {...props}\n    >\n      {children}\n      <SelectPrimitive.Icon data-slot=\"select-icon\">\n        <ChevronsUpDownIcon className={selectTriggerIconClassName} />\n      </SelectPrimitive.Icon>\n    </SelectPrimitive.Trigger>\n  );\n}\n\nexport function SelectValue({\n  className,\n  ...props\n}: SelectPrimitive.Value.Props): React.ReactElement {\n  return (\n    <SelectPrimitive.Value\n      className={cn(\n        \"flex-1 truncate data-placeholder:text-muted-foreground\",\n        className,\n      )}\n      data-slot=\"select-value\"\n      {...props}\n    />\n  );\n}\n\nexport function SelectPopup({\n  className,\n  children,\n  side = \"bottom\",\n  sideOffset = 4,\n  align = \"start\",\n  alignOffset = 0,\n  alignItemWithTrigger = true,\n  anchor,\n  portalProps,\n  ...props\n}: SelectPrimitive.Popup.Props & {\n  portalProps?: SelectPrimitive.Portal.Props;\n  side?: SelectPrimitive.Positioner.Props[\"side\"];\n  sideOffset?: SelectPrimitive.Positioner.Props[\"sideOffset\"];\n  align?: SelectPrimitive.Positioner.Props[\"align\"];\n  alignOffset?: SelectPrimitive.Positioner.Props[\"alignOffset\"];\n  alignItemWithTrigger?: SelectPrimitive.Positioner.Props[\"alignItemWithTrigger\"];\n  anchor?: SelectPrimitive.Positioner.Props[\"anchor\"];\n}): React.ReactElement {\n  return (\n    <SelectPrimitive.Portal {...portalProps}>\n      <SiteplaneUIPortalScope>\n        <SelectPrimitive.Positioner\n          align={align}\n          alignItemWithTrigger={alignItemWithTrigger}\n          alignOffset={alignOffset}\n          anchor={anchor}\n          className=\"z-50 select-none\"\n          data-slot=\"select-positioner\"\n          side={side}\n          sideOffset={sideOffset}\n        >\n          <SelectPrimitive.Popup\n            className=\"siteplane-floating-panel origin-(--transform-origin) text-foreground outline-none\"\n            data-slot=\"select-popup\"\n            {...props}\n          >\n            <SelectPrimitive.ScrollUpArrow\n              className=\"top-0 z-50 flex h-6 w-full cursor-pointer items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:top-px before:h-[200%] before:rounded-t-[inherit] before:bg-linear-to-b before:from-50% before:from-popover\"\n              data-slot=\"select-scroll-up-arrow\"\n            >\n              <ChevronUpIcon className=\"relative size-4.5 sm:size-4\" />\n            </SelectPrimitive.ScrollUpArrow>\n            <div\n              className={cn(\n                surfaceClassNames.overlay,\n                \"h-full min-w-(--anchor-width) w-max max-w-(--available-width) rounded-lg before:rounded-[inherit]\",\n              )}\n            >\n              <SelectPrimitive.List\n                className={cn(\n                  \"max-h-(--available-height) overflow-y-auto p-1\",\n                  className,\n                )}\n                data-slot=\"select-list\"\n              >\n                {children}\n              </SelectPrimitive.List>\n            </div>\n            <SelectPrimitive.ScrollDownArrow\n              className=\"bottom-0 z-50 flex h-6 w-full cursor-pointer items-center justify-center before:pointer-events-none before:absolute before:inset-x-px before:bottom-px before:h-[200%] before:rounded-b-[inherit] before:bg-linear-to-t before:from-50% before:from-popover\"\n              data-slot=\"select-scroll-down-arrow\"\n            >\n              <ChevronDownIcon className=\"relative size-4.5 sm:size-4\" />\n            </SelectPrimitive.ScrollDownArrow>\n          </SelectPrimitive.Popup>\n        </SelectPrimitive.Positioner>\n      </SiteplaneUIPortalScope>\n    </SelectPrimitive.Portal>\n  );\n}\n\nexport function SelectItem({\n  className,\n  children,\n  ...props\n}: SelectPrimitive.Item.Props): React.ReactElement {\n  return (\n    <SelectPrimitive.Item\n      className={cn(\n        \"grid min-h-8 cursor-pointer grid-cols-[minmax(0,1fr)_1rem] items-center gap-2 rounded-sm py-1 ps-2 pe-2 text-base outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n        className,\n      )}\n      data-slot=\"select-item\"\n      {...props}\n    >\n      <SelectPrimitive.ItemText\n        className=\"col-start-1 row-start-1 min-w-0 truncate\"\n        data-slot=\"select-item-text\"\n      >\n        {children}\n      </SelectPrimitive.ItemText>\n      <SelectPrimitive.ItemIndicator\n        className=\"col-start-2 row-start-1 justify-self-end\"\n        data-slot=\"select-item-indicator\"\n      >\n        <CheckIcon />\n      </SelectPrimitive.ItemIndicator>\n    </SelectPrimitive.Item>\n  );\n}\n\nexport function SelectSeparator({\n  className,\n  ...props\n}: SelectPrimitive.Separator.Props): React.ReactElement {\n  return (\n    <SelectPrimitive.Separator\n      className={cn(\"mx-2 my-1 h-px bg-border\", className)}\n      data-slot=\"select-separator\"\n      {...props}\n    />\n  );\n}\n\nexport function SelectGroup(\n  props: SelectPrimitive.Group.Props,\n): React.ReactElement {\n  return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />;\n}\n\nexport function SelectLabel({\n  className,\n  ...props\n}: SelectPrimitive.Label.Props): React.ReactElement {\n  return (\n    <SelectPrimitive.Label\n      className={cn(\n        \"not-in-data-[slot=field]:mb-2 inline-flex cursor-default items-center gap-2 font-medium text-base/4.5 text-foreground sm:text-sm/4\",\n        className,\n      )}\n      data-slot=\"select-label\"\n      {...props}\n    />\n  );\n}\n\nexport function SelectGroupLabel(\n  props: SelectPrimitive.GroupLabel.Props,\n): React.ReactElement {\n  return (\n    <SelectPrimitive.GroupLabel\n      className=\"px-2 py-1.5 font-medium text-muted-foreground text-xs\"\n      data-slot=\"select-group-label\"\n      {...props}\n    />\n  );\n}\n\nexport { SelectPrimitive, SelectPopup as SelectContent };\n"
    }
  ],
  "categories": [
    "form-controls"
  ],
  "docs": "# Select\n\n> Siteplane UI release `0.1.1`.\n\n## Public Purpose\n\nUse Select for a bounded, known set of choices such as status, category, framework or filter values.\n\n## Import\n\n```tsx\nimport {\n  Select,\n  SelectButton,\n  SelectGroup,\n  SelectGroupLabel,\n  SelectItem,\n  SelectLabel,\n  SelectPopup,\n  SelectSeparator,\n  SelectTrigger,\n  SelectValue,\n} from \"@/components/ui/select\";\n```\n\n## Public API\n\n- `Select` supports single or multiple controlled and uncontrolled values through the Base UI root contract.\n- `SelectTrigger size=\"xl\"` uses the 56px customer-facing field height and 16px\n  field text. Pair it with a surrounding `SiteplaneUIProvider radius=\"sm\"`\n  for the global 8px main corner. Popup item density and radius stay independent\n  from the trigger size.\n- Compose `SelectTrigger`, `SelectValue`, `SelectPopup`, `SelectItem`, `SelectGroup`, `SelectGroupLabel`, `SelectLabel` and `SelectSeparator`; `SelectButton` is the standalone trigger-style button.\n- `SelectPopup` accepts `side`, `align`, `sideOffset`, `alignOffset`, `anchor`, `alignItemWithTrigger`, `portalProps` and popup props.\n- `SelectItem` accepts `disabled`. Long lists automatically expose the built-in scroll-up and scroll-down controls when the popup overflows.\n\n## Public Motion\n\n- Select uses the shared floating-panel transition. Item-aligned popups keep the selected item stable while using the shared fade and scale behavior.\n- Placement, collision handling and reduced motion remain inside the native primitive.\n\n## Public Accessibility\n\n- Give the trigger a visible label or accessible name and keep disabled or invalid state paired with clear text.\n- Preserve keyboard navigation, typeahead, focus return and the built-in long-list scroll controls.\n- A disabled option must remain understandable without being the only available choice.\n\n## Public Agent Guidance\n\n- Use Combobox for large searchable sets and Autocomplete for suggestions while typing.\n- Configure placement on `SelectPopup`, not with local positioning wrappers.\n- Do not replace the built-in overflow behavior with a second nested scroll container.\n\n## Public Links\n\n- [Documentation and preview](https://ui.siteplane.io/docs/components/form-controls/select)\n\n- [Registry source](https://ui.siteplane.io/r/select.json)\n",
  "meta": {
    "siteplane:agentContractVersion": 1,
    "siteplane:docs": "https://ui.siteplane.io/docs/components/form-controls/select",
    "siteplane:releaseVersion": "0.1.1",
    "siteplane:sourceOwned": true
  },
  "devDependencies": []
}
