{
  "example": "import { useState } from \"react\";\nimport { ColorPicker, Form, FormField } from \"@godxjp/ui/data-entry\";\n\nexport function BrandColorField() {\n  const [color, setColor] = useState(\"#2563eb\");\n\n  return (\n    <Form>\n      <FormField id=\"brand-color\" label=\"Brand color\">\n        <ColorPicker id=\"brand-color\" value={color} onValueChange={setColor} />\n      </FormField>\n    </Form>\n  );\n}\n\n// Compact swatch-only variant (no hex input)\nexport function SwatchOnly() {\n  const [color, setColor] = useState(\"#16a34a\");\n  return <ColorPicker value={color} onValueChange={setColor} showHexInput={false} />;\n}\n\n// Fixed palette only (gh#1055): tags pick from presets, never free hex\nexport function TagColorField() {\n  const [color, setColor] = useState(\"#2563eb\");\n  return (\n    <Form>\n      <FormField id=\"tag-color\" label=\"Tag colour\">\n        <ColorPicker\n          id=\"tag-color\"\n          value={color}\n          onValueChange={setColor}\n          presets={[{ label: \"Palette\", colors: [\"#dc2626\", \"#16a34a\", \"#2563eb\", \"#9333ea\"] }]}\n          panelRender={(_, { components: { Presets } }) => <Presets />}\n        />\n      </FormField>\n    </Form>\n  );\n}\n\n// Disabled state\nexport function DisabledColor() {\n  return <ColorPicker value=\"#6b7280\" disabled />;\n}",
  "group": "data-entry",
  "importPath": "@godxjp/ui/data-entry",
  "name": "ColorPicker",
  "props": [
    {
      "description": "Initial uncontrolled color.",
      "name": "defaultValue",
      "type": "string"
    },
    {
      "description": "Native form field name.",
      "name": "name",
      "type": "string"
    },
    {
      "defaultValue": "\"#2563eb\"",
      "description": "The current hex color string (3- or 6-digit, with leading #). Component auto-prepends # if missing. Invalid hex values are discarded and the previous valid value is kept.",
      "name": "value",
      "type": "string"
    },
    {
      "defaultValue": "undefined",
      "description": "Called with the normalized, validated hex string whenever the user commits a new color — via the native swatch picker or by pressing Enter / blurring the hex input. Not called for invalid hex drafts.",
      "name": "onValueChange",
      "type": "(hex: string) => void"
    },
    {
      "defaultValue": "undefined",
      "description": "Disables both the swatch input and the hex text input, preventing all user interaction.",
      "name": "disabled",
      "type": "boolean"
    },
    {
      "defaultValue": "true",
      "description": "When true (default), renders an editable godx-ui Input alongside the swatch that shows the current hex value and lets the user type a hex string. Set to false for a compact swatch-only control.",
      "name": "showHexInput",
      "type": "boolean"
    },
    {
      "defaultValue": "undefined",
      "description": "Extra CSS class(es) applied to the root wrapper div. Use for layout sizing; avoid overriding design-token colours.",
      "name": "className",
      "type": "string"
    },
    {
      "defaultValue": "undefined",
      "description": "DOM id applied to the hidden native <input type='color'>. Pass the FormField id here so the label's htmlFor targets this control correctly.",
      "name": "id",
      "type": "string"
    },
    {
      "defaultValue": "undefined",
      "description": "antd `presets` (gh#1055) — named groups of fixed hex swatches under the picker. Each group is collapsible (`defaultOpen`, default true) and is an APG radio group: one tab stop, arrow keys move and select, each swatch is named by its hex and the one equal to `value` is checked. An empty `colors` shows the localized 'Empty' line. Hex only (#rgb/#rrggbb) — antd also accepts colour objects and gradients, which this picker has no model for.",
      "name": "presets",
      "type": "{ label: ReactNode; colors: string[]; defaultOpen?: boolean; key?: Key }[]"
    },
    {
      "defaultValue": "undefined",
      "description": "antd `panelRender` — replaces the picker body. `panel` is the default (swatch + hex row, then presets). PRESETS-ONLY mode (a fixed palette, no free hex): `panelRender={(_, { components: { Presets } }) => <Presets />}`. The hidden `name` input always renders outside the panel.",
      "name": "panelRender",
      "type": "(panel: ReactNode, extra: { components: { Picker: FC; Presets: FC } }) => ReactNode"
    }
  ],
  "related": [
    "Input — use for plain text/number entry; use ColorPicker when the value is specifically a color hex code and you want a visual swatch.",
    "Select / SearchSelect — use for choosing from a list of colour NAMES (e.g. 'Red', 'Blue'); for a fixed palette of visible swatches use ColorPicker `presets` (presets-only via `panelRender`)."
  ],
  "rules": [
    2,
    3,
    6,
    13
  ],
  "storyPath": "data-entry/color-picker.tsx",
  "tagline": "Native color-swatch picker with an optional editable hex input — always pass a valid 3- or 6-digit hex `value`; invalid hex is silently ignored and the previous value is restored.",
  "usage": [
    "DO wrap in FormField when a label or validation message is needed — pass the same id to both FormField and ColorPicker so htmlFor wires up correctly: `<FormField id='brand' label='Brand color'><ColorPicker id='brand' value={v} onValueChange={setV} /></FormField>`.",
    "Use it controlled (value + onValueChange) or uncontrolled (defaultValue + onValueChange); both paths commit only validated hex.",
    "DON'T pass an invalid or empty string to value — the component will flash the invalid color on the preview swatch. Always initialize state to a valid 3- or 6-digit hex (e.g. '#2563eb').",
    "The hex Input is a live draft field — onValueChange is NOT called until the user presses Enter or blurs; only then is the value validated and the parent notified. Do not rely on onValueChange firing on every keystroke.",
    "Set showHexInput={false} only for compact/inline contexts (icon pickers, table cells) where space is tight and keyboard hex entry is not needed.",
    "DO use `presets` when the value must come from a fixed palette (tag / label colours) — add `panelRender={(_, { components: { Presets } }) => <Presets />}` to remove free hex entry entirely. NEVER rebuild a palette from a ToggleGroup of swatches.",
    "NEVER hand-roll a color picker with raw <input type='color'> — always use this component; it normalizes hex, debounces draft state, and respects the design-token control styles."
  ],
  "useCases": [
    "Brand / campaign color selection in settings or campaign creation forms where users need to pick or type an exact hex value.",
    "Invoice or document theme customization — letting users pick accent colors that are stored and applied to PDF output.",
    "Accounting dashboard category tagging — assigning a color code to GL account categories or chart-of-accounts nodes for visual grouping.",
    "Product or inventory label colors in admin panels where a compact swatch (showHexInput={false}) fits inside a table cell or sidebar.",
    "Design-token or CSS variable editor pages where the user needs precise hex entry alongside a visual swatch preview.",
    "User-profile or team avatar color personalization forms."
  ]
}
