{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "gradient-picker-radix",
  "type": "registry:ui",
  "title": "Amplo Gradient Picker (Radix)",
  "description": "Radix/shadcn-classic shells for the Amplo gradient picker — TypeSwitcher, InterpSwitcher and RadialSizeSelect on shadcn's Select, plus the popover stop editor. Gradient parsing, contexts and the pointer-driven parts (Bar, Overlay, Area, StopList, angle/position pads, Presets) come from the shared gradient engine, pulled in as a registry dependency.",
  "version": "2.0.0",
  "categories": [
    "color",
    "input",
    "design",
    "accessibility"
  ],
  "dependencies": [
    "culori",
    "@types/culori",
    "lucide-react",
    "@base-ui/react"
  ],
  "registryDependencies": [
    "utils",
    "select",
    "https://amplo.ale.design/r/color-picker-radix.json",
    "https://amplo.ale.design/r/gradient-picker-engine.json"
  ],
  "files": [
    {
      "path": "registry/new-york/ui/fill-picker/parts/gradient/type-switcher.tsx",
      "type": "registry:ui",
      "target": "@ui/fill-picker/parts/gradient/type-switcher.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { SelectItem } from \"@/components/ui/select\";\nimport { useGradientPickerContext } from \"../../contexts/gradient\";\nimport type { GradientType } from \"../../lib/gradient\";\nimport { FieldSelect } from \"../field-select\";\nimport { GRADIENT_TYPE_OPTIONS } from \"../../lib/gradient-options\";\n\nconst TYPES = GRADIENT_TYPE_OPTIONS;\n\n/**\n * Bound to `gradient.type`. Built on `<FieldSelect>` (shadcn `<Select>`\n * under the hood) so it shares its border, focus ring, font, and chevron\n * with every other dropdown in the picker.\n *\n * Width is intrinsic (not `w-full`) so it can sit next to icon buttons\n * like `<GradientPicker.ReverseStops>` without stretching the row.\n */\nexport const TypeSwitcher = React.forwardRef<\n  HTMLButtonElement,\n  { className?: string }\n>(function TypeSwitcher({ className }, ref) {\n  const ctx = useGradientPickerContext();\n  return (\n    <FieldSelect\n      ref={ref}\n      aria-label=\"Gradient type\"\n      value={ctx.gradient.type}\n      onValueChange={(v) => ctx.setType(v as GradientType)}\n      wrapperProps={{\n        \"data-slot\": \"gradient-type-switcher\",\n        className,\n      }}\n    >\n      {TYPES.map((t) => (\n        <SelectItem key={t.value} value={t.value}>\n          {t.label}\n        </SelectItem>\n      ))}\n    </FieldSelect>\n  );\n});\n"
    },
    {
      "path": "registry/new-york/ui/fill-picker/parts/gradient/interp-switcher.tsx",
      "type": "registry:ui",
      "target": "@ui/fill-picker/parts/gradient/interp-switcher.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"@/components/ui/select\";\nimport { useGradientPickerContext } from \"../../contexts/gradient\";\nimport type { GradientInterp } from \"../../lib/gradient\";\nimport { GRADIENT_INTERP_OPTIONS } from \"../../lib/gradient-options\";\n\nconst OPTIONS = GRADIENT_INTERP_OPTIONS;\n\nexport interface InterpSwitcherProps {\n  className?: string;\n  /** Applied to the SelectTrigger. */\n  triggerClassName?: string;\n}\n\n/**\n * Bound to the active gradient's `interp` property. Switching only\n * changes the blending math between stops — stop positions and colors\n * stay identical.\n *\n * Must render inside `<GradientPicker.Root>` — throws otherwise.\n */\nexport const InterpSwitcher = React.forwardRef<\n  HTMLButtonElement,\n  InterpSwitcherProps\n>(function InterpSwitcher({ className, triggerClassName }, ref) {\n  const ctx = useGradientPickerContext();\n  return (\n    <Select\n      value={ctx.gradient.interp}\n      onValueChange={(v) => ctx.setInterp(v as GradientInterp)}\n    >\n      <SelectTrigger\n        ref={ref}\n        data-slot=\"gradient-interp-switcher\"\n        aria-label=\"Interpolation space\"\n        size=\"sm\"\n        className={cn(\n          \"w-full font-mono text-xs tracking-wide\",\n          triggerClassName,\n          className,\n        )}\n      >\n        <SelectValue />\n      </SelectTrigger>\n      <SelectContent className=\"font-mono text-xs tracking-wide\">\n        {/* Bare-string children so both Select dialects derive the trigger label\n            (Radix mirrors ItemText; the Base wrapper walks children). Descriptions\n            ride on title= — an in-item tooltip subtree would pollute both. */}\n        {OPTIONS.map((opt) => (\n          <SelectItem key={opt.value} value={opt.value} title={opt.description}>\n            {opt.label}\n          </SelectItem>\n        ))}\n      </SelectContent>\n    </Select>\n  );\n});\n"
    },
    {
      "path": "registry/new-york/ui/fill-picker/parts/gradient/radial-size-select.tsx",
      "type": "registry:ui",
      "target": "@ui/fill-picker/parts/gradient/radial-size-select.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from \"@/components/ui/select\";\nimport { useGradientPickerContext } from \"../../contexts/gradient\";\nimport type { RadialSizeKeyword } from \"../../lib/gradient\";\nimport { RADIAL_SIZE_OPTIONS } from \"../../lib/gradient-options\";\n\nconst SIZE_OPTIONS = RADIAL_SIZE_OPTIONS;\n\nexport interface RadialSizeSelectProps {\n  className?: string;\n  /** Applied to the SelectTrigger. */\n  triggerClassName?: string;\n}\n\nexport const RadialSizeSelect = React.forwardRef<\n  HTMLButtonElement,\n  RadialSizeSelectProps\n>(function RadialSizeSelect({ className, triggerClassName }, ref) {\n  const ctx = useGradientPickerContext();\n  if (ctx.gradient.type !== \"radial\") return null;\n  return (\n    <Select\n      value={ctx.gradient.size}\n      onValueChange={(v) => ctx.setRadialSize(v as RadialSizeKeyword)}\n    >\n      <SelectTrigger\n        ref={ref}\n        data-slot=\"gradient-radial-size-select\"\n        aria-label=\"Radial size\"\n        size=\"sm\"\n        className={cn(\n          \"w-full font-mono text-xs tracking-wide\",\n          triggerClassName,\n          className,\n        )}\n      >\n        <SelectValue />\n      </SelectTrigger>\n      <SelectContent className=\"font-mono text-xs tracking-wide\">\n        {/* Bare-string children so both Select dialects derive the trigger label\n            (Radix mirrors ItemText; the Base wrapper walks children). Descriptions\n            ride on title= — an in-item tooltip subtree would pollute both. */}\n        {SIZE_OPTIONS.map((opt) => (\n          <SelectItem key={opt.value} value={opt.value} title={opt.description}>\n            {opt.value}\n          </SelectItem>\n        ))}\n      </SelectContent>\n    </Select>\n  );\n});\n"
    },
    {
      "path": "registry/new-york/ui/fill-picker/parts/gradient/stop-editor-popover.tsx",
      "type": "registry:ui",
      "target": "@ui/fill-picker/parts/gradient/stop-editor-popover.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { StopPopover } from \"./stop-popover\";\nimport { ColorPickerContext } from \"../../context\";\nimport type { GradientStopEditorRenderer } from \"../../contexts/gradient\";\nimport { useStopColorPickerState } from \"./stop-editor-shared\";\nimport { Area as ColorArea } from \"../area\";\nimport { Hue } from \"../hue\";\nimport { Alpha } from \"../alpha\";\nimport { ChannelInput } from \"../channel-input\";\nimport { FormatSwitcher } from \"../format-switcher\";\nimport { EyeDropper } from \"../eye-dropper\";\n\nexport interface StopEditorPopoverProps {\n  /** Stop the popover edits — color + per-stop format are read/written via gradient context. */\n  stopId: string;\n  /**\n   * Controlled open state. Required — open is always external because\n   * the anchor element typically has its own pointer handling (drag on\n   * Bar handles, click on StopList swatches) that would conflict with\n   * a trigger-managed open state.\n   */\n  open: boolean;\n  onOpenChange: (open: boolean) => void;\n  /** Anchor element. Positioned against; provides positioning only. */\n  children: React.ReactElement;\n}\n\n/**\n * Shared color-editor popover used by `<GradientPicker.StopList>` rows and\n * by `<GradientPicker.Bar editOnClick>`. Mounts a `useColorPicker` bound\n * to the named stop and provides it via `ColorPickerContext` so the\n * standard `<ColorPicker.*>` parts work inside.\n */\nexport function StopEditorPopover({\n  stopId,\n  open,\n  onOpenChange,\n  children,\n}: StopEditorPopoverProps) {\n  const state = useStopColorPickerState(stopId);\n  return (\n    <StopPopover\n      open={open}\n      onOpenChange={onOpenChange}\n      anchor={children}\n      className=\"flex w-72 flex-col gap-3\"\n      onContentClick={(e) => e.stopPropagation()}\n    >\n      <ColorPickerContext.Provider value={state}>\n        <ColorArea mode=\"oklch-cl\" />\n        <div className=\"flex flex-col gap-1.5\">\n          <Hue />\n          <Alpha />\n        </div>\n        <div className=\"flex items-center gap-2\">\n          <FormatSwitcher className=\"flex-1\" />\n          <EyeDropper className=\"h-8 w-full flex-1\" />\n        </div>\n        <ChannelInput showFormat={false} />\n      </ColorPickerContext.Provider>\n    </StopPopover>\n  );\n}\n\n/**\n * `<GradientPicker.Bar editOnClick>`'s stop-editor slot, filled with the\n * popover above. Injected as the default by the Radix/shadcn barrel\n * (`gradient-picker.tsx`, `fill-picker.tsx`); the Base UI variant injects its\n * own from `fill-picker-base/parts/gradient/stop-editor.tsx`.\n */\nexport const stopEditorSlot: GradientStopEditorRenderer = ({\n  children,\n  ...props\n}) => (\n  // The Bar always passes a single element (the stop handle) as `children`;\n  // the slot type is widened to ReactNode only because it is React's own\n  // children convention.\n  <StopEditorPopover {...props}>\n    {children as React.ReactElement}\n  </StopEditorPopover>\n);\n"
    },
    {
      "path": "registry/new-york/ui/fill-picker/gradient-picker.tsx",
      "type": "registry:ui",
      "target": "@ui/fill-picker/gradient-picker.tsx",
      "content": "\"use client\";\n\n// Re-export the color-picker public surface so consumers who install\n// gradient-picker get the underlying color types/hooks/parts they need\n// to compose stop editors and previews.\nexport * from \"./color-picker\";\nexport { ColorPicker } from \"./color-picker\";\n\nimport * as React from \"react\";\nimport { Root as EngineGradientRoot, type RootProps as GradientRootProps } from \"./parts/gradient/root\";\nimport { stopEditorSlot } from \"./parts/gradient/stop-editor-popover\";\nimport { Bar } from \"./parts/gradient/bar\";\nimport { Area as GradientArea } from \"./parts/gradient/area\";\nimport { Overlay as GradientOverlay } from \"./parts/gradient/overlay\";\nimport { TypeSwitcher } from \"./parts/gradient/type-switcher\";\nimport { ReverseStops } from \"./parts/gradient/reverse-stops\";\nimport { RepeatingToggle } from \"./parts/gradient/repeating-toggle\";\nimport { AnglePad } from \"./parts/gradient/angle-pad\";\nimport { AngleInput } from \"./parts/gradient/angle-input\";\nimport { PositionPad } from \"./parts/gradient/position-pad\";\nimport { PositionInput } from \"./parts/gradient/position-input\";\nimport { ShapeSwitcher } from \"./parts/gradient/shape-switcher\";\nimport { RadiusInput } from \"./parts/gradient/radius-input\";\nimport { EllipseRadiiInput } from \"./parts/gradient/ellipse-radii-input\";\nimport { RadialSizeSelect } from \"./parts/gradient/radial-size-select\";\nimport { StopList } from \"./parts/gradient/stop-list\";\nimport { StopColor } from \"./parts/gradient/stop-color\";\nimport { InterpSwitcher } from \"./parts/gradient/interp-switcher\";\nimport { Presets, BUILTIN_GRADIENT_PRESETS } from \"./parts/gradient/presets\";\nimport { CssInput as GradientCssInput } from \"./parts/gradient/css-input\";\nimport { PositionGroup } from \"./parts/gradient/position-group\";\nimport { AngleGroup } from \"./parts/gradient/angle-group\";\n\nexport type {\n  Gradient,\n  GradientType,\n  GradientInterp,\n  GradientStop,\n  LinearGradient,\n  RadialGradient,\n  RadialSizeKeyword,\n  ConicGradient,\n} from \"./lib/gradient\";\nexport {\n  formatGradient,\n  parseGradient,\n  DEFAULT_LINEAR,\n  DEFAULT_RADIAL,\n  DEFAULT_CONIC,\n} from \"./lib/gradient\";\nexport { BUILTIN_GRADIENT_PRESETS };\nexport { useGradientPicker } from \"./hooks/use-gradient-picker\";\nexport type {\n  UseGradientPickerProps,\n  GradientPickerState,\n} from \"./hooks/use-gradient-picker\";\n\n/**\n * The engine `Root` plus this variant's stop editor. `<Bar editOnClick>`\n * renders whatever editor was injected here (the Bar itself imports none, so\n * it can ship in a dialect-free item); the public API is unchanged — the\n * `stopEditor` prop merely gains a default.\n */\nconst GradientRoot = React.forwardRef<HTMLDivElement, GradientRootProps>(\n  function Root({ stopEditor = stopEditorSlot, ...props }, ref) {\n    return <EngineGradientRoot ref={ref} stopEditor={stopEditor} {...props} />;\n  },\n);\n\nexport const GradientPicker = {\n  Root: GradientRoot,\n  Bar,\n  Area: GradientArea,\n  Overlay: GradientOverlay,\n  TypeSwitcher,\n  ReverseStops,\n  RepeatingToggle,\n  AnglePad,\n  AngleInput,\n  PositionPad,\n  PositionInput,\n  ShapeSwitcher,\n  RadiusInput,\n  EllipseRadiiInput,\n  RadialSizeSelect,\n  StopList,\n  StopColor,\n  InterpSwitcher,\n  Presets,\n  CssInput: GradientCssInput,\n  PositionGroup,\n  AngleGroup,\n};\n"
    }
  ]
}
