{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "select",
  "title": "Select",
  "description": "The list unfolds from the field, one highlight glides between options and the chosen value rises in.",
  "dependencies": [
    "@ui-sdk/core@0.1.0-beta.2",
    "@ui-sdk/react@0.1.0-beta.2"
  ],
  "registryDependencies": [
    "@keyframery/motion"
  ],
  "files": [
    {
      "path": "registry/components/keyframery/primitives/select.tsx",
      "content": "\"use client\"\n\n/* Animated drop-in for `@ui-sdk/react/select`: same parts, same props. Swap the import and keep your code.\n   This file adds motion only. Colours, radii, shadows and spacing stay yours.\n\n   - Content: Unfold from the field (scale 0.86, 6px blur, 8px toward it; spring in, quick out).\n   - Rows: Cascade in as the list opens. Glide: one highlight springs from row to row (CSS anchor\n     positioning). Its neutral surface follows the text colour; give `before:bg-…` and\n     `before:rounded-…` to restyle it.\n   - Checks: Draw themselves. Trigger: Press.\n   - Value: a newly chosen value rises into the field (Direction, up). */\n\nimport {\n  SelectContent as SelectContentPart,\n  SelectItem as SelectItemPart,\n  SelectItemIndicator as SelectItemIndicatorPart,\n  SelectSelectAll as SelectSelectAllPart,\n  SelectTrigger as SelectTriggerPart,\n  SelectValue as SelectValuePart,\n} from \"@ui-sdk/react/select\"\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport * from \"@ui-sdk/react/select\"\n\nconst keyframes = \"@keyframes kf-value-up{from{translate:0 0.75em;opacity:0;filter:blur(3px)}}\"\n\nfunction SelectTrigger({ className, ...props }: React.ComponentProps<typeof SelectTriggerPart>) {\n  return (\n    <SelectTriggerPart\n      className={cn(\n        \"transition-[scale] duration-[calc(200ms*var(--kf-speed,1))] ease-pop active:scale-[0.98] motion-reduce:transition-none!\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* The value text is wrapped in a span keyed by its label, so a new value mounts fresh and rises in.\n   A readiness gate keeps the first value still on load. Pass `render` to take over. */\nfunction SelectValue({ className, render, ...props }: React.ComponentProps<typeof SelectValuePart>) {\n  const [ready, setReady] = React.useState(false)\n  React.useEffect(() => {\n    const timer = setTimeout(() => setReady(true), 150)\n    return () => clearTimeout(timer)\n  }, [])\n  return (\n    <>\n      <style href=\"kf-select-value\" precedence=\"default\">\n        {keyframes}\n      </style>\n      <SelectValuePart\n        className={cn(\"overflow-hidden\", className)}\n        render={\n          render ??\n          ((partProps, state) => (\n            <span {...partProps}>\n              <span\n                key={state.placeholder ? \"\\u0000placeholder\" : state.label}\n                className={cn(\n                  \"block truncate\",\n                  ready && \"[animation:kf-value-up_calc(460ms*var(--kf-speed,1))_var(--ease-spring)] motion-reduce:animate-none!\",\n                )}\n              >\n                {partProps.children}\n              </span>\n            </span>\n          ))\n        }\n        {...props}\n      />\n    </>\n  )\n}\n\n/* Unfold + Cascade + Glide. Rows cascade whether they sit in the content or in a SelectList. */\nfunction SelectContent({ className, ...props }: React.ComponentProps<typeof SelectContentPart>) {\n  return (\n    <SelectContentPart\n      className={cn(\n        \"group/kf-select origin-(--transform-origin)\",\n        \"[transition:opacity_calc(380ms*var(--kf-speed,1))_var(--ease-spring),scale_calc(380ms*var(--kf-speed,1))_var(--ease-spring),translate_calc(380ms*var(--kf-speed,1))_var(--ease-spring),filter_calc(380ms*var(--kf-speed,1))_var(--ease-spring)]\",\n        \"data-[side=bottom]:[--kf-from:0_-8px] data-[side=top]:[--kf-from:0_8px] data-[side=left]:[--kf-from:8px_0] data-[side=right]:[--kf-from:-8px_0]\",\n        \"data-starting-style:[translate:var(--kf-from,0_0)] data-starting-style:scale-[0.86] data-starting-style:opacity-0 data-starting-style:blur-[6px]\",\n        \"data-ending-style:scale-[0.96] data-ending-style:opacity-0 data-ending-style:blur-[2px]\",\n        \"data-ending-style:[transition:opacity_calc(150ms*var(--kf-speed,1))_var(--ease-house),scale_calc(150ms*var(--kf-speed,1))_var(--ease-house),translate_calc(150ms*var(--kf-speed,1))_var(--ease-house),filter_calc(150ms*var(--kf-speed,1))_var(--ease-house)]\",\n        /* Cascade */\n        \"[&>*:not([data-slot=select-list])]:transition-[opacity,translate,filter] [&>*:not([data-slot=select-list])]:duration-[calc(420ms*var(--kf-speed,1))] [&>*:not([data-slot=select-list])]:ease-spring\",\n        \"[&>*:not([data-slot=select-list])]:[transition-delay:calc((min(sibling-index(),10)-1)*calc(32ms*var(--kf-speed,1)))]\",\n        \"data-starting-style:[&>*:not([data-slot=select-list])]:translate-y-2 data-starting-style:[&>*:not([data-slot=select-list])]:opacity-0 data-starting-style:[&>*:not([data-slot=select-list])]:blur-[4px]\",\n        \"[&>[data-slot=select-list]>*]:transition-[opacity,translate,filter] [&>[data-slot=select-list]>*]:duration-[calc(420ms*var(--kf-speed,1))] [&>[data-slot=select-list]>*]:ease-spring\",\n        \"[&>[data-slot=select-list]>*]:[transition-delay:calc((min(sibling-index(),10)-1)*calc(32ms*var(--kf-speed,1)))]\",\n        \"data-starting-style:[&>[data-slot=select-list]>*]:translate-y-2 data-starting-style:[&>[data-slot=select-list]>*]:opacity-0 data-starting-style:[&>[data-slot=select-list]>*]:blur-[4px]\",\n        \"data-ending-style:[&>*]:[transition-delay:0ms] data-ending-style:[&>[data-slot=select-list]>*]:[transition-delay:0ms]\",\n        \"motion-reduce:[&>*:not([data-slot=select-list])]:[translate:none]! motion-reduce:[&>*:not([data-slot=select-list])]:[filter:none]! data-starting-style:[&>*:not([data-slot=select-list])]:[transition:none] data-starting-style:[&>[data-slot=select-list]>*]:[transition:none]\",\n        /* Glide */\n        \"relative isolate [anchor-scope:--kf-hl]\",\n        \"before:pointer-events-none before:absolute before:-z-10 before:hidden before:bg-[color-mix(in_oklch,currentColor_9%,transparent)]\",\n        \"before:[position-anchor:--kf-hl] before:top-[anchor(top)] before:right-[anchor(right)] before:bottom-[anchor(bottom)] before:left-[anchor(left)]\",\n        \"before:[transition:top_calc(260ms*var(--kf-speed,1))_var(--ease-spring),right_calc(260ms*var(--kf-speed,1))_var(--ease-spring),bottom_calc(260ms*var(--kf-speed,1))_var(--ease-spring),left_calc(260ms*var(--kf-speed,1))_var(--ease-spring),opacity_calc(150ms*var(--kf-speed,1))_var(--ease-house)]\",\n        \"has-[[data-highlighted]]:before:block starting:before:opacity-0\",\n        \"motion-reduce:[transition:none]! motion-reduce:before:[transition:none]! motion-reduce:[&>*]:[transition:none] motion-reduce:[&>[data-slot=select-list]>*]:[transition:none]\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SelectItem<T = string>({ className, ...props }: React.ComponentProps<typeof SelectItemPart<T>>) {\n  return <SelectItemPart<T> className={cn(\"data-highlighted:[anchor-name:--kf-hl]\", className)} {...props} />\n}\n\nfunction SelectSelectAll({ className, ...props }: React.ComponentProps<typeof SelectSelectAllPart>) {\n  return <SelectSelectAllPart className={cn(\"data-highlighted:[anchor-name:--kf-hl]\", className)} {...props} />\n}\n\n/* Draw: the check's stroke draws in when its item is chosen, and again as the list unfolds.\n   Works with any check path up to 24 units long. */\nfunction SelectItemIndicator({ className, ...props }: React.ComponentProps<typeof SelectItemIndicatorPart>) {\n  return (\n    <SelectItemIndicatorPart\n      className={cn(\n        \"[&_:is(path,polyline)]:[stroke-dasharray:24] [&_:is(path,polyline)]:[stroke-dashoffset:24]\",\n        \"[&_:is(path,polyline)]:transition-[stroke-dashoffset] [&_:is(path,polyline)]:duration-[calc(260ms*var(--kf-speed,1))] [&_:is(path,polyline)]:ease-house\",\n        \"data-selected:[&_:is(path,polyline)]:[stroke-dashoffset:0] data-selected:[&_:is(path,polyline)]:delay-[calc(100ms*var(--kf-speed,1))]\",\n        \"data-selected:[&_:is(path,polyline)]:starting:[stroke-dashoffset:24]\",\n        \"group-data-starting-style/kf-select:[&_:is(path,polyline)]:[stroke-dashoffset:24]!\",\n        \"motion-reduce:[&_:is(path,polyline)]:transition-none\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nexport { SelectContent, SelectItem, SelectItemIndicator, SelectSelectAll, SelectTrigger, SelectValue }\n",
      "type": "registry:component",
      "target": "components/keyframery/primitives/select.tsx"
    },
    {
      "path": "registry/components/keyframery/select.tsx",
      "content": "\"use client\"\n\n/* Styled select: the animated primitive plus the Keyframery look. */\n\nimport {\n  createSelectController,\n  type ListData,\n  Select as SelectRoot,\n  SelectArrow as SelectArrowPart,\n  SelectClear as SelectClearPart,\n  SelectContent as SelectContentPart,\n  SelectEmpty as SelectEmptyPart,\n  SelectGroup as SelectGroupPart,\n  SelectGroupLabel as SelectGroupLabelPart,\n  SelectInput as SelectInputPart,\n  SelectItem as SelectItemPart,\n  SelectItemIcon as SelectItemIconPart,\n  SelectItemIndicator as SelectItemIndicatorPart,\n  SelectItemText as SelectItemTextPart,\n  SelectLabel as SelectLabelPart,\n  SelectList as SelectListPart,\n  type SelectProps,\n  SelectSelectAll as SelectSelectAllPart,\n  SelectSeparator as SelectSeparatorPart,\n  SelectStatus as SelectStatusPart,\n  SelectTrigger as SelectTriggerPart,\n  SelectValue as SelectValuePart,\n  SelectValueIcon as SelectValueIconPart,\n} from \"@/components/keyframery/primitives/select\"\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* The sheet. Its motion (unfold, cascade, the gliding highlight) comes from the primitive. */\nconst sheet = cn(\n  \"group/content m-0 flex min-w-(--anchor-width) flex-col border-0 p-0 outline-none\",\n  \"[--list-height:var(--available-height)]\",\n  /* Items placed straight in the sheet get the list's padding and scrolling. */\n  \"not-has-[[data-slot=select-list]]:max-h-[min(calc(var(--list-height,100vh)-8px),18rem)] not-has-[[data-slot=select-list]]:scroll-py-1.5 not-has-[[data-slot=select-list]]:overflow-y-auto not-has-[[data-slot=select-list]]:overscroll-contain not-has-[[data-slot=select-list]]:p-1.5\",\n  \"rounded-[14px] bg-popover text-popover-foreground\",\n  \"shadow-[0_0_0_1px_rgb(0_0_0/0.06),0_2px_6px_-2px_rgb(0_0_0/0.08),0_12px_32px_-8px_rgb(0_0_0/0.18)]\",\n  \"dark:shadow-[0_0_0_1px_rgb(255_255_255/0.08),0_12px_32px_-8px_rgb(0_0_0/0.7)]\",\n  \"before:rounded-[8px] before:bg-accent has-[[data-disabled][data-highlighted]]:before:bg-accent/50\",\n)\n\n/* One row for items and the select-all row. No background of its own: the gliding highlight sits under it. */\nconst row = cn(\n  \"group/item relative flex min-h-8 cursor-default items-center gap-2 rounded-[8px] px-2 py-1.5 text-[13px] leading-4 outline-none select-none\",\n  \"data-highlighted:text-accent-foreground\",\n  \"data-disabled:pointer-events-none data-disabled:text-muted-foreground/60\",\n  /* Rows without an icon keep the icon column when another row in the list has one. */\n  \"[[data-has-icons]_&:not([data-has-icon])]:ps-8\",\n)\n\nconst field = cn(\n  \"flex h-9 w-full min-w-0 items-center gap-2 rounded-[10px] bg-background px-3 text-[13px] text-foreground outline-none\",\n  \"shadow-[0_0_0_1px_rgb(0_0_0/0.09),0_1px_2px_rgb(0_0_0/0.05)] dark:shadow-[0_0_0_1px_rgb(255_255_255/0.1)]\",\n  \"[transition:box-shadow_calc(150ms*var(--kf-speed,1)),background-color_calc(150ms*var(--kf-speed,1)),scale_calc(200ms*var(--kf-speed,1))_var(--ease-pop)] motion-reduce:transition-none!\",\n)\n\nfunction ChevronIcon() {\n  return (\n    <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n      <path d=\"m5 6.5 3-3 3 3M5 9.5l3 3 3-3\" />\n    </svg>\n  )\n}\n\nfunction XIcon() {\n  return (\n    <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n      <path d=\"m4.5 4.5 7 7m0-7-7 7\" />\n    </svg>\n  )\n}\n\nfunction CheckIcon() {\n  return (\n    <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n      <path d=\"m3.5 8.5 3 3 6-7\" />\n    </svg>\n  )\n}\n\nfunction SearchIcon() {\n  return (\n    <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n      <circle cx=\"7\" cy=\"7\" r=\"4.25\" />\n      <path d=\"m10.25 10.25 3.25 3.25\" />\n    </svg>\n  )\n}\n\nfunction Select<T = string, Multiple extends boolean | undefined = false>(\n  props: SelectProps<T, Multiple>,\n) {\n  return <SelectRoot<T, Multiple> {...props} />\n}\n\nfunction SelectLabel({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectLabelPart>) {\n  return (\n    <SelectLabelPart\n      className={cn(\n        \"mb-2 block text-[13px] leading-none font-medium text-foreground data-disabled:opacity-50\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* The field. Its chevron sits at the end; pass a SelectValue (and a SelectValueIcon) inside. */\nfunction SelectTrigger({\n  className,\n  children,\n  ...props\n}: Omit<React.ComponentProps<typeof SelectTriggerPart>, \"children\"> & {\n  children?: React.ReactNode\n}) {\n  return (\n    <SelectTriggerPart\n      className={cn(\n        field,\n        \"cursor-pointer text-start select-none\",\n        \"hover:shadow-[0_0_0_1px_rgb(0_0_0/0.16),0_1px_2px_rgb(0_0_0/0.05)] dark:hover:shadow-[0_0_0_1px_rgb(255_255_255/0.16)]\",\n        \"data-open:shadow-[0_0_0_1px_rgb(0_0_0/0.16),0_1px_2px_rgb(0_0_0/0.05)] dark:data-open:shadow-[0_0_0_1px_rgb(255_255_255/0.16)]\",\n        \"focus-visible:shadow-[0_0_0_1px_var(--ring)] focus-visible:ring-[3px] focus-visible:ring-ring/25 dark:focus-visible:shadow-[0_0_0_1px_var(--ring)]\",\n        \"aria-invalid:shadow-[0_0_0_1px_var(--destructive)] aria-invalid:focus-visible:ring-destructive/25 dark:aria-invalid:shadow-[0_0_0_1px_var(--destructive)]\",\n        \"data-invalid:shadow-[0_0_0_1px_var(--destructive)] dark:data-invalid:shadow-[0_0_0_1px_var(--destructive)]\",\n        \"active:bg-[color-mix(in_oklab,var(--background),var(--foreground)_2%)]\",\n        \"data-disabled:cursor-not-allowed data-disabled:opacity-50 data-readonly:cursor-default data-readonly:bg-muted/40\",\n        \"[&>svg:last-child]:ms-auto [&>svg:last-child]:size-4 [&>svg:last-child]:shrink-0 [&>svg:last-child]:text-muted-foreground\",\n        className,\n      )}\n      {...props}\n    >\n      {children}\n      <ChevronIcon />\n    </SelectTriggerPart>\n  )\n}\n\nfunction SelectValue({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectValuePart>) {\n  return (\n    <SelectValuePart\n      className={cn(\"min-w-0 flex-1 truncate data-placeholder:text-muted-foreground\", className)}\n      {...props}\n    />\n  )\n}\n\n/* Shows the chosen item's icon inside the field. */\nfunction SelectValueIcon({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectValueIconPart>) {\n  return (\n    <SelectValueIconPart\n      className={cn(\n        \"-ms-0.5 grid size-4 shrink-0 place-items-center text-muted-foreground [&_svg]:size-4\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SelectClear({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof SelectClearPart>) {\n  return (\n    <SelectClearPart\n      className={cn(\n        \"grid size-6 shrink-0 cursor-pointer place-items-center rounded-[6px] text-muted-foreground outline-none [&_svg]:size-3.5\",\n        \"transition-[color,background-color,scale] duration-[calc(150ms*var(--kf-speed,1))] hover:bg-foreground/[0.06] hover:text-foreground active:scale-[0.94]\",\n        \"focus-visible:ring-2 focus-visible:ring-ring data-disabled:pointer-events-none data-disabled:opacity-40 motion-reduce:transition-none!\",\n        className,\n      )}\n      {...props}\n    >\n      {children ?? <XIcon />}\n    </SelectClearPart>\n  )\n}\n\nfunction SelectContent({\n  className,\n  children,\n  sideOffset = 6,\n  ...props\n}: React.ComponentProps<typeof SelectContentPart>) {\n  return (\n    <SelectContentPart\n      sideOffset={sideOffset}\n      className={cn(sheet, className)}\n      {...props}\n    >\n      {children ?? <SelectList />}\n    </SelectContentPart>\n  )\n}\n\nfunction SelectList({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof SelectListPart>) {\n  return (\n    <SelectListPart\n      className={cn(\n        \"max-h-[min(calc(var(--list-height,100vh)-8px),18rem)] scroll-py-1.5 overflow-y-auto overscroll-contain p-1.5 outline-none\",\n        \"aria-busy:opacity-60\",\n        \"group-has-[[data-slot=select-empty][data-empty]]/content:hidden\",\n        className,\n      )}\n      {...props}\n    >\n      {children ?? ((state) => <SelectItems items={state.items} />)}\n    </SelectListPart>\n  )\n}\n\n/* A search field at the top of the sheet. */\nfunction SelectInput({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectInputPart>) {\n  return (\n    <div data-slot=\"select-input-row\" className=\"relative flex items-center border-b border-border\">\n      <span className=\"pointer-events-none absolute start-3 grid size-4 place-items-center text-muted-foreground [&_svg]:size-4\">\n        <SearchIcon />\n      </span>\n      <SelectInputPart\n        className={cn(\n          \"h-10 w-full min-w-0 bg-transparent ps-9 pe-3 text-[13px] text-foreground outline-none placeholder:text-muted-foreground\",\n          className,\n        )}\n        {...props}\n      />\n    </div>\n  )\n}\n\nfunction SelectItem<T = string>({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectItemPart<T>>) {\n  return <SelectItemPart<T> className={cn(row, className)} {...props} />\n}\n\n/* The label of an item. It takes the free space, so hints and the check line up at the end.\n   While searching, the matched part reads stronger. */\nfunction SelectItemText({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectItemTextPart>) {\n  return (\n    <SelectItemTextPart\n      className={cn(\n        \"min-w-0 flex-1 truncate data-matched:text-muted-foreground [&_mark]:bg-transparent [&_mark]:font-medium [&_mark]:text-foreground\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* The check. It stays mounted, so the primitive can draw it in when its item is chosen and\n   when the sheet opens on the chosen item. */\nfunction SelectItemIndicator({\n  className,\n  children,\n  keepMounted = true,\n  ...props\n}: React.ComponentProps<typeof SelectItemIndicatorPart>) {\n  return (\n    <SelectItemIndicatorPart\n      keepMounted={keepMounted}\n      className={cn(\n        \"ms-auto grid size-4 shrink-0 place-items-center text-foreground [&_svg]:size-4\",\n        className,\n      )}\n      {...props}\n    >\n      {children ?? <CheckIcon />}\n    </SelectItemIndicatorPart>\n  )\n}\n\nfunction SelectItemIcon({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectItemIconPart>) {\n  return (\n    <SelectItemIconPart\n      className={cn(\n        \"grid size-4 shrink-0 place-items-center text-muted-foreground [&_svg]:size-4\",\n        \"group-data-highlighted/item:text-current\",\n        \"rtl:data-mirror:-scale-x-100\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SelectGroup({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectGroupPart>) {\n  return <SelectGroupPart className={cn(\"flex flex-col\", className)} {...props} />\n}\n\nfunction SelectGroupLabel({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectGroupLabelPart>) {\n  return (\n    <SelectGroupLabelPart\n      className={cn(\n        \"px-2 pt-1.5 pb-1 text-[11px] leading-4 font-medium text-muted-foreground select-none\",\n        \"[[data-has-icons]_&]:ps-8\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SelectSeparator({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectSeparatorPart>) {\n  return (\n    <SelectSeparatorPart\n      className={cn(\"-mx-1.5 my-1.5 h-px bg-border\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction SelectEmpty({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectEmptyPart>) {\n  return (\n    <SelectEmptyPart\n      className={cn(\n        \"hidden px-3 py-6 text-center text-[13px] text-muted-foreground data-empty:block data-loading:block\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SelectStatus({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectStatusPart>) {\n  return (\n    <SelectStatusPart\n      className={cn(\"px-3.5 pt-2.5 pb-0.5 text-[12px] text-muted-foreground empty:hidden\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction SelectSelectAll({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectSelectAllPart>) {\n  return (\n    <SelectSelectAllPart\n      className={cn(row, \"font-medium data-unchecked:font-normal\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction SelectArrow({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectArrowPart>) {\n  return (\n    <SelectArrowPart\n      className={cn(\"size-2.5 rotate-45 rounded-[2px] bg-popover\", className)}\n      {...props}\n    />\n  )\n}\n\n/* Renders items passed as data with the styled parts above. */\nfunction SelectItems({ items }: { items?: ListData<unknown> }) {\n  return (items ?? []).map((entry, index) => {\n    if (typeof entry === \"string\") {\n      return (\n        <SelectItem key={entry} value={entry}>\n          <SelectItemText>{entry}</SelectItemText>\n          <SelectItemIndicator />\n        </SelectItem>\n      )\n    }\n    if (\"type\" in entry && entry.type === \"separator\") {\n      return <SelectSeparator key={`separator-${index}`} />\n    }\n    if (\"type\" in entry && entry.type === \"group\") {\n      return (\n        <SelectGroup key={`group-${entry.label ?? index}`}>\n          {entry.label && <SelectGroupLabel>{entry.label}</SelectGroupLabel>}\n          <SelectItems items={entry.items} />\n        </SelectGroup>\n      )\n    }\n    const { value, label, disabled } = entry\n    return (\n      <SelectItem<unknown>\n        key={typeof value === \"string\" ? value : index}\n        value={value}\n        label={label}\n        disabled={disabled}\n      >\n        <SelectItemText>{label}</SelectItemText>\n        <SelectItemIndicator />\n      </SelectItem>\n    )\n  })\n}\n\nexport type { ListData } from \"@/components/keyframery/primitives/select\"\nexport {\n  createSelectController,\n  Select,\n  SelectArrow,\n  SelectClear,\n  SelectContent,\n  SelectEmpty,\n  SelectGroup,\n  SelectGroupLabel,\n  SelectInput,\n  SelectItem,\n  SelectItemIcon,\n  SelectItemIndicator,\n  SelectItems,\n  SelectItemText,\n  SelectLabel,\n  SelectList,\n  SelectSelectAll,\n  SelectSeparator,\n  SelectStatus,\n  SelectTrigger,\n  SelectValue,\n  SelectValueIcon,\n}\n",
      "type": "registry:component",
      "target": "components/keyframery/select.tsx"
    }
  ],
  "type": "registry:component"
}