{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "color-picker",
  "title": "Color Picker",
  "description": "Popover color picker with swatches, a hue slider, and a hex input.",
  "dependencies": [
    "@vllnt/ui@^0.2.1"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/color-picker/color-picker.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@vllnt/ui\";\nimport { Button } from \"@vllnt/ui\";\nimport { Input } from \"@vllnt/ui\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@vllnt/ui\";\n\nconst presetSwatches: string[] = [\n  \"#ef4444\",\n  \"#f97316\",\n  \"#f59e0b\",\n  \"#84cc16\",\n  \"#22c55e\",\n  \"#14b8a6\",\n  \"#3b82f6\",\n  \"#6366f1\",\n  \"#a855f7\",\n  \"#ec4899\",\n  \"#64748b\",\n  \"#0f172a\",\n];\n\nfunction hexPart(value: number): string {\n  return value.toString(16).padStart(2, \"0\");\n}\n\nfunction toHex(red: number, green: number, blue: number): string {\n  return `#${hexPart(red)}${hexPart(green)}${hexPart(blue)}`;\n}\n\nfunction hueChannel(hue: number, offset: number): number {\n  const k = (offset + hue / 30) % 12;\n  const amount = 0.45;\n  const value = 0.5 - amount * Math.max(-1, Math.min(k - 3, 9 - k, 1));\n  return Math.round(value * 255);\n}\n\nfunction hueToHex(hue: number): string {\n  return toHex(hueChannel(hue, 0), hueChannel(hue, 8), hueChannel(hue, 4));\n}\n\ntype SwatchGridProps = {\n  onSelect: (value: string) => void;\n  selected: string;\n  swatches: string[];\n};\n\nfunction SwatchGrid({ onSelect, selected, swatches }: SwatchGridProps) {\n  return (\n    <div className=\"grid grid-cols-6 gap-2\" role=\"group\">\n      {swatches.map((swatch) => (\n        <button\n          aria-label={swatch}\n          aria-pressed={swatch.toLowerCase() === selected.toLowerCase()}\n          className={cn(\n            \"size-7 rounded-md border outline-none ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n            swatch.toLowerCase() === selected.toLowerCase() &&\n              \"ring-2 ring-ring\",\n          )}\n          key={swatch}\n          onClick={() => {\n            onSelect(swatch);\n          }}\n          style={{ backgroundColor: swatch }}\n          type=\"button\"\n        />\n      ))}\n    </div>\n  );\n}\n\n/** Popover colour picker with swatches, a hue slider, and a hex input. */\nexport type ColorPickerProps = {\n  className?: string;\n  defaultValue?: string;\n  onValueChange?: (value: string) => void;\n  swatches?: string[];\n  value?: string;\n};\n\nconst ColorPicker = ({\n  className,\n  defaultValue = \"#3b82f6\",\n  onValueChange,\n  ref,\n  swatches = presetSwatches,\n  value,\n}: ColorPickerProps & { ref?: React.Ref<HTMLButtonElement> }) => {\n  const [internalValue, setInternalValue] = React.useState(defaultValue);\n  const currentValue = value ?? internalValue;\n\n  const update = (next: string) => {\n    if (value === undefined) {\n      setInternalValue(next);\n    }\n\n    onValueChange?.(next);\n  };\n\n  return (\n    <Popover>\n      <PopoverTrigger asChild>\n        <Button\n          className={cn(\"w-full justify-start gap-2 font-normal\", className)}\n          ref={ref}\n          variant=\"outline\"\n        >\n          <span\n            aria-hidden\n            className=\"size-4 rounded-sm border\"\n            style={{ backgroundColor: currentValue }}\n          />\n          <span className=\"uppercase tabular-nums\">{currentValue}</span>\n        </Button>\n      </PopoverTrigger>\n      <PopoverContent align=\"start\" className=\"w-56 space-y-3\">\n        <SwatchGrid\n          onSelect={update}\n          selected={currentValue}\n          swatches={swatches}\n        />\n        <input\n          aria-label=\"Hue\"\n          className=\"h-3 w-full cursor-pointer appearance-none rounded-full\"\n          max={360}\n          min={0}\n          onChange={(event) => {\n            update(hueToHex(Number(event.target.value)));\n          }}\n          style={{\n            background:\n              \"linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%)\",\n          }}\n          type=\"range\"\n        />\n        <Input\n          aria-label=\"Hex value\"\n          onChange={(event) => {\n            update(event.target.value);\n          }}\n          value={currentValue}\n        />\n      </PopoverContent>\n    </Popover>\n  );\n};\nColorPicker.displayName = \"ColorPicker\";\n\nexport { ColorPicker };\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component",
  "version": "0.2.1",
  "stability": "stable"
}
