{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "select",
  "type": "registry:ui",
  "title": "Select",
  "description": "Styled native select for a one-of-n choice with more options than a segmented control can show.",
  "categories": [
    "forms"
  ],
  "registryDependencies": [
    "https://whiskeyjack.net/r/utils.json"
  ],
  "files": [
    {
      "path": "components/ui/select.tsx",
      "type": "registry:ui",
      "target": "components/ui/select.tsx",
      "content": "import * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface SelectOption {\n  value: string;\n  label: string;\n  disabled?: boolean;\n}\n\nexport interface SelectProps\n  extends Omit<\n    React.SelectHTMLAttributes<HTMLSelectElement>,\n    \"onChange\" | \"value\" | \"children\"\n  > {\n  /** Optional label shown above the select. */\n  label?: React.ReactNode;\n  value: string;\n  onChange: (value: string) => void;\n  options: SelectOption[];\n  placeholder?: string;\n}\n\n/**\n * Native `<select>` styled to match the design-system Input / Slider primitives.\n * Uses a small inline SVG caret instead of pulling in an icon library so the\n * design system stays icon-free (apps own that decision).\n */\nconst Select = React.forwardRef<HTMLSelectElement, SelectProps>(\n  ({ label, value, onChange, options, placeholder, className, id: idProp, ...props }, ref) => {\n    const autoId = React.useId();\n    const id = idProp ?? (label !== undefined ? autoId : undefined);\n\n    return (\n      <div className=\"flex flex-col gap-2\">\n        {label !== undefined && (\n          <label\n            htmlFor={id}\n            className=\"text-xs text-[var(--color-text-muted-light)] dark:text-[var(--color-text-muted-dark)]\"\n          >\n            {label}\n          </label>\n        )}\n        <div className=\"relative\">\n          <select\n            ref={ref}\n            id={id}\n            value={value}\n            onChange={e => onChange(e.target.value)}\n            className={cn(\n              // Same field shape as Input: control height, regular radius,\n              // solid border, no fill, deboss recess.\n              \"appearance-none w-full h-control-md ps-3 pe-8 rounded-lg text-sm\",\n              \"bg-transparent shadow-deboss\",\n              // The popup list needs a fill of its own. Firefox lets <option>\n              // inherit the select's background, so a transparent control there\n              // renders the open list against whatever is behind the page.\n              \"[&>option]:bg-[var(--color-surface-light)] [&>option]:text-[var(--color-text-primary-light)]\",\n              \"dark:[&>option]:bg-[var(--color-surface-dark)] dark:[&>option]:text-[var(--color-text-primary-dark)]\",\n              \"border border-[var(--color-border-light)] dark:border-[var(--color-border-dark)]\",\n              \"text-[var(--color-text-primary-light)] dark:text-[var(--color-text-primary-dark)]\",\n              \"hover:border-[var(--color-warm-300)] dark:hover:border-[var(--color-neutral-700)]\",\n              \"wj-focus-ring\",\n              \"disabled:cursor-not-allowed disabled:opacity-50\",\n              \"transition-colors\",\n              className,\n            )}\n            {...props}\n          >\n            {placeholder && (\n              <option value=\"\" disabled>\n                {placeholder}\n              </option>\n            )}\n            {options.map(opt => (\n              <option key={opt.value} value={opt.value} disabled={opt.disabled}>\n                {opt.label}\n              </option>\n            ))}\n          </select>\n          {/* Caret -- logical end so it sits opposite the text in RTL too */}\n          <svg\n            className=\"absolute end-2.5 top-1/2 -translate-y-1/2 pointer-events-none w-3 h-3 text-[var(--color-text-muted-light)] dark:text-[var(--color-text-muted-dark)]\"\n            viewBox=\"0 0 12 12\"\n            fill=\"none\"\n            stroke=\"currentColor\"\n            strokeWidth=\"1.75\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            aria-hidden\n          >\n            <path d=\"M2.5 4.5L6 8l3.5-3.5\" />\n          </svg>\n        </div>\n      </div>\n    );\n  },\n);\nSelect.displayName = \"Select\";\n\nexport { Select };\n"
    }
  ],
  "docs": "Give it a label, value, onChange, and an options array. It stays the native control underneath, so it is accessible and familiar on every platform. For a small set of choices, ToggleGroup reads better.",
  "meta": {
    "group": "forms",
    "related": [
      "toggle-group",
      "input"
    ],
    "exports": [
      "Select"
    ],
    "siteSlug": "select"
  }
}
