{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"checkbox","type":"registry:ui","title":"Checkbox","description":"A control that toggles between checked and unchecked.","dependencies":["lucide-react","radix-ui"],"registryDependencies":["https://dashral.com/r/utils.json","https://dashral.com/r/field.json"],"files":[{"path":"registry/dashral/checkbox.tsx","type":"registry:file","target":"components/dashral/checkbox.tsx","content":"\"use client\"\n\nimport * as React from \"react\"\nimport { Checkbox as CheckboxPrimitive } from \"radix-ui\"\nimport { CheckIcon, MinusIcon } from \"lucide-react\"\n\nimport { cn } from \"./lib/utils\"\nimport { ChoiceField, joinIds, type ChoiceOwnProps, type FieldClassNames } from \"./field\"\n\ntype ControlColor = \"primary\" | \"neutral\" | \"info\" | \"success\" | \"warning\" | \"destructive\" | \"highlight\"\n\n// Ticked: filled with the color. Every class is written out in full so Tailwind finds it.\nconst solidColors: Record<ControlColor, string> = {\n  primary: \"data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=indeterminate]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground\",\n  neutral: \"data-[state=checked]:border-foreground data-[state=checked]:bg-foreground data-[state=checked]:text-background data-[state=indeterminate]:border-foreground data-[state=indeterminate]:bg-foreground data-[state=indeterminate]:text-background\",\n  info: \"data-[state=checked]:border-info data-[state=checked]:bg-info data-[state=checked]:text-info-foreground data-[state=indeterminate]:border-info data-[state=indeterminate]:bg-info data-[state=indeterminate]:text-info-foreground\",\n  success: \"data-[state=checked]:border-success data-[state=checked]:bg-success data-[state=checked]:text-success-foreground data-[state=indeterminate]:border-success data-[state=indeterminate]:bg-success data-[state=indeterminate]:text-success-foreground\",\n  warning: \"data-[state=checked]:border-warning data-[state=checked]:bg-warning data-[state=checked]:text-warning-foreground data-[state=indeterminate]:border-warning data-[state=indeterminate]:bg-warning data-[state=indeterminate]:text-warning-foreground\",\n  destructive: \"data-[state=checked]:border-destructive data-[state=checked]:bg-destructive data-[state=checked]:text-destructive-foreground data-[state=indeterminate]:border-destructive data-[state=indeterminate]:bg-destructive data-[state=indeterminate]:text-destructive-foreground\",\n  highlight: \"data-[state=checked]:border-highlight data-[state=checked]:bg-highlight data-[state=checked]:text-highlight-foreground data-[state=indeterminate]:border-highlight data-[state=indeterminate]:bg-highlight data-[state=indeterminate]:text-highlight-foreground\",\n}\n\n// Ticked: a colored border and mark, no fill. Every class is written out in full so Tailwind finds it.\nconst outlineColors: Record<ControlColor, string> = {\n  primary: \"data-[state=checked]:border-primary data-[state=checked]:text-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary\",\n  neutral: \"data-[state=checked]:border-foreground data-[state=checked]:text-foreground data-[state=indeterminate]:border-foreground data-[state=indeterminate]:text-foreground\",\n  info: \"data-[state=checked]:border-info data-[state=checked]:text-info data-[state=indeterminate]:border-info data-[state=indeterminate]:text-info\",\n  success: \"data-[state=checked]:border-success data-[state=checked]:text-success data-[state=indeterminate]:border-success data-[state=indeterminate]:text-success\",\n  warning: \"data-[state=checked]:border-warning data-[state=checked]:text-warning data-[state=indeterminate]:border-warning data-[state=indeterminate]:text-warning\",\n  destructive: \"data-[state=checked]:border-destructive data-[state=checked]:text-destructive data-[state=indeterminate]:border-destructive data-[state=indeterminate]:text-destructive\",\n  highlight: \"data-[state=checked]:border-highlight data-[state=checked]:text-highlight data-[state=indeterminate]:border-highlight data-[state=indeterminate]:text-highlight\",\n}\n\ntype CheckboxProps = React.ComponentProps<typeof CheckboxPrimitive.Root> &\n  ChoiceOwnProps & {\n    /** The color when ticked. */\n    color?: ControlColor\n    /** solid fills the box when ticked; outline colors only its border and mark. */\n    variant?: \"solid\" | \"outline\"\n    /** \"start\" puts the label first and the checkbox at the far end, as in a settings row. */\n    labelPosition?: \"start\" | \"end\"\n    classNames?: FieldClassNames & { checkbox?: string }\n  }\n\n/** A checkbox. Give it a label (and a description) and they sit beside it; clicking them ticks it. */\nfunction Checkbox({ label, description, error, id, disabled, labelPosition, color = \"primary\", variant = \"solid\", className, classNames, ...props }: CheckboxProps) {\n  return (\n    <ChoiceField {...{ label, description, error, id, disabled, labelPosition, classNames }} leading=\"leading-4\">\n      {(control) => (\n        <CheckboxControl\n          {...props}\n          {...control}\n          disabled={disabled}\n          aria-describedby={joinIds(props[\"aria-describedby\"], control[\"aria-describedby\"])}\n          aria-invalid={props[\"aria-invalid\"] ?? control[\"aria-invalid\"]}\n          className={cn((variant === \"outline\" ? outlineColors : solidColors)[color], className, classNames?.checkbox)}\n        />\n      )}\n    </ChoiceField>\n  )\n}\n\nfunction CheckboxControl({ className, ...props }: React.ComponentProps<typeof CheckboxPrimitive.Root>) {\n  return (\n    <CheckboxPrimitive.Root\n      data-slot=\"checkbox\"\n      className={cn(\n        \"peer group size-4 shrink-0 rounded-[4px] border border-input shadow-xs transition-[color,background-color,border-color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive\",\n        className\n      )}\n      {...props}\n    >\n      <CheckboxPrimitive.Indicator\n        data-slot=\"checkbox-indicator\"\n        // The mark springs in when checked (Radix mounts the indicator then).\n        className=\"flex animate-in items-center justify-center text-current zoom-in-50 fade-in-0 duration-(--duration-standard) ease-spring motion-reduce:animate-none\"\n      >\n        <CheckIcon className=\"size-3.5 group-data-[state=indeterminate]:hidden\" />\n        <MinusIcon className=\"hidden size-3.5 group-data-[state=indeterminate]:block\" />\n      </CheckboxPrimitive.Indicator>\n    </CheckboxPrimitive.Root>\n  )\n}\n\nexport { Checkbox, type CheckboxProps, type ControlColor }\n"}],"cssVars":{"theme":{"color-destructive-foreground":"var(--destructive-foreground)","color-destructive-text":"var(--destructive-text)","color-info":"var(--info)","color-info-foreground":"var(--info-foreground)","color-info-text":"var(--info-text)","color-success":"var(--success)","color-success-foreground":"var(--success-foreground)","color-success-text":"var(--success-text)","color-warning":"var(--warning)","color-warning-foreground":"var(--warning-foreground)","color-warning-text":"var(--warning-text)","color-highlight":"var(--highlight)","color-highlight-foreground":"var(--highlight-foreground)","color-highlight-text":"var(--highlight-text)","ease-standard":"var(--ease-standard)","ease-enter":"var(--ease-enter)","ease-exit":"var(--ease-exit)","ease-spring":"var(--ease-spring)"},"light":{"destructive-foreground":"oklch(0.985 0 0)","destructive-text":"#bd2800","info":"oklch(0.5 0.134 242.749)","info-foreground":"oklch(0.985 0 0)","info-text":"oklch(0.443 0.11 240.79)","success":"oklch(0.508 0.118 165.612)","success-foreground":"oklch(0.985 0 0)","success-text":"oklch(0.432 0.095 166.913)","warning":"#f59200","warning-foreground":"oklch(0.3 0.07 60)","warning-text":"#964e00","highlight":"#b8008c","highlight-foreground":"oklch(0.985 0 0)","highlight-text":"#a3007b","duration-fast":"160ms","duration-standard":"240ms","duration-considered":"480ms","ease-standard":"cubic-bezier(0.2, 0, 0, 1)","ease-enter":"cubic-bezier(0, 0, 0, 1)","ease-exit":"cubic-bezier(0.3, 0, 1, 1)","ease-spring":"linear(0, 0.071 4%, 0.234 8%, 0.433 12%, 0.626 17%, 0.791 21%, 0.917 25%, 1.004 29%, 1.055 33%, 1.079 38%, 1.083 42%, 1.075 46%, 1.06 50%, 1.043 54%, 1.027 58%, 1.015 62%, 1.005 67%, 0.998 71%, 0.995 75%, 0.993 79%, 0.993 83%, 0.994 88%, 0.995 92%, 0.997 96%, 1)"},"dark":{"destructive-foreground":"oklch(0.2 0 0)","destructive-text":"#ff8a5c","info":"oklch(0.685 0.169 237.323)","info-foreground":"oklch(0.2 0 0)","info-text":"oklch(0.746 0.16 232.661)","success":"oklch(0.696 0.17 162.48)","success-foreground":"oklch(0.2 0.04 160)","success-text":"oklch(0.765 0.177 163.223)","warning":"#f59200","warning-foreground":"oklch(0.25 0.06 60)","warning-text":"#ffba42","highlight":"#ff2ecf","highlight-foreground":"oklch(0.2 0 0)","highlight-text":"#ff75df"}}}