{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "checkbox",
  "type": "registry:ui",
  "title": "Checkbox",
  "description": "Native-input-backed Checkbox primitive with token-backed checked, indeterminate, focus, invalid, disabled, read-only, density, dark mode, and FormField-compatible styling.",
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://components.dethink.co.uk/r/dethink-base.json"
  ],
  "files": [
    {
      "path": "packages/components/src/components/checkbox/checkbox.tsx",
      "type": "registry:file",
      "target": "~/components/dethink/components/checkbox/checkbox.tsx",
      "content": "import {\n  forwardRef,\n  useEffect,\n  useRef,\n  useState,\n  type ChangeEventHandler,\n  type InputHTMLAttributes,\n  type MouseEventHandler,\n  type Ref,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type CheckboxCheckedState = boolean | \"indeterminate\";\nexport type CheckboxControlSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface CheckboxProps extends Omit<\n  InputHTMLAttributes<HTMLInputElement>,\n  \"checked\" | \"defaultChecked\" | \"onChange\" | \"size\" | \"type\"\n> {\n  \"data-slot\"?: string;\n  checked?: CheckboxCheckedState;\n  controlSize?: CheckboxControlSize;\n  defaultChecked?: CheckboxCheckedState;\n  invalid?: boolean;\n  onChange?: ChangeEventHandler<HTMLInputElement>;\n  onCheckedChange?: (checked: CheckboxCheckedState) => void;\n}\n\nconst checkboxRootBaseClasses =\n  \"group/checkbox relative inline-flex shrink-0 items-center justify-center align-middle\";\n\nconst checkboxControlSizeClasses: Record<CheckboxControlSize, string> = {\n  sm: \"[--choice-control-size:calc(var(--dt-density-control)*0.4)] size-[var(--choice-control-size)]\",\n  md: \"[--choice-control-size:calc(var(--dt-density-control)*0.5)] size-[var(--choice-control-size)]\",\n  lg: \"[--choice-control-size:calc(var(--dt-density-control)*0.6)] size-[var(--choice-control-size)]\",\n};\n\nconst checkboxInputClasses =\n  \"peer absolute inset-0 z-10 m-0 size-full cursor-pointer opacity-0 disabled:cursor-not-allowed\";\n\nconst checkboxIndicatorBaseClasses =\n  \"pointer-events-none flex size-full items-center justify-center rounded border border-input bg-background text-transparent shadow-sm outline-none motion-safe:transition-[background-color,border-color,box-shadow,color,opacity] motion-safe:duration-[var(--dt-motion-fast)] motion-safe:ease-control peer-disabled:opacity-60 peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-2 peer-focus-visible:ring-offset-background group-disabled/field-set:opacity-60 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 data-[invalid=true]:border-destructive data-[invalid=true]:ring-2 data-[invalid=true]:ring-destructive/15 data-[disabled=true]:opacity-60 data-[readonly=true]:bg-muted/40 data-[readonly=true]:text-muted-foreground\";\n\nfunction isAriaInvalid(value: CheckboxProps[\"aria-invalid\"]) {\n  return (\n    value === true ||\n    value === \"true\" ||\n    value === \"grammar\" ||\n    value === \"spelling\"\n  );\n}\n\nfunction getCheckboxState(checked: CheckboxCheckedState) {\n  if (checked === \"indeterminate\") {\n    return \"indeterminate\";\n  }\n\n  return checked ? \"checked\" : \"unchecked\";\n}\n\nfunction setRef<T>(ref: Ref<T> | undefined, node: T | null) {\n  if (typeof ref === \"function\") {\n    ref(node);\n    return;\n  }\n\n  if (ref) {\n    (ref as { current: T | null }).current = node;\n  }\n}\n\nfunction composeRefs<T>(...refs: Array<Ref<T> | undefined>) {\n  return (node: T | null) => {\n    for (const ref of refs) {\n      setRef(ref, node);\n    }\n  };\n}\n\nexport function checkboxClassNames({\n  className,\n  controlSize = \"md\",\n}: Pick<CheckboxProps, \"className\" | \"controlSize\"> = {}) {\n  return cn(\n    checkboxRootBaseClasses,\n    checkboxControlSizeClasses[controlSize],\n    className,\n  );\n}\n\nfunction CheckIcon() {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className=\"size-3.5\"\n      fill=\"none\"\n      viewBox=\"0 0 16 16\"\n    >\n      <path\n        d=\"m3.5 8 3 3 6-6.5\"\n        stroke=\"currentColor\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"2\"\n      />\n    </svg>\n  );\n}\n\nfunction MinusIcon() {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className=\"size-3.5\"\n      fill=\"none\"\n      viewBox=\"0 0 16 16\"\n    >\n      <path\n        d=\"M3.5 8h9\"\n        stroke=\"currentColor\"\n        strokeLinecap=\"round\"\n        strokeWidth=\"2\"\n      />\n    </svg>\n  );\n}\n\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(\n  (\n    {\n      \"aria-invalid\": ariaInvalid,\n      \"data-slot\": dataSlot,\n      checked,\n      className,\n      controlSize = \"md\",\n      defaultChecked = false,\n      disabled,\n      invalid = false,\n      onChange,\n      onCheckedChange,\n      onClick,\n      readOnly,\n      required,\n      ...props\n    },\n    ref,\n  ) => {\n    const inputRef = useRef<HTMLInputElement | null>(null);\n    const isControlled = checked !== undefined;\n    const [uncontrolledChecked, setUncontrolledChecked] =\n      useState<CheckboxCheckedState>(defaultChecked);\n    const checkedState = isControlled ? checked : uncontrolledChecked;\n    const resolvedInvalid = invalid || isAriaInvalid(ariaInvalid);\n    const state = getCheckboxState(checkedState);\n\n    useEffect(() => {\n      if (inputRef.current) {\n        inputRef.current.indeterminate = checkedState === \"indeterminate\";\n      }\n    }, [checkedState]);\n\n    const restoreReadOnlyState = () => {\n      if (inputRef.current) {\n        inputRef.current.checked = checkedState === true;\n        inputRef.current.indeterminate = checkedState === \"indeterminate\";\n      }\n    };\n\n    const handleClick: MouseEventHandler<HTMLInputElement> = (event) => {\n      if (readOnly) {\n        event.preventDefault();\n        restoreReadOnlyState();\n        queueMicrotask(restoreReadOnlyState);\n        return;\n      }\n\n      onClick?.(event);\n    };\n\n    const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n      if (readOnly) {\n        event.preventDefault();\n        restoreReadOnlyState();\n        queueMicrotask(restoreReadOnlyState);\n        return;\n      }\n\n      onChange?.(event);\n\n      if (event.defaultPrevented) {\n        return;\n      }\n\n      const nextChecked = event.currentTarget.checked;\n\n      if (!isControlled) {\n        setUncontrolledChecked(nextChecked);\n      }\n\n      onCheckedChange?.(nextChecked);\n    };\n\n    return (\n      <span\n        data-slot={dataSlot ?? \"checkbox\"}\n        data-size={controlSize}\n        data-state={state}\n        data-checked={checkedState === true ? \"true\" : undefined}\n        data-disabled={disabled ? \"true\" : undefined}\n        data-indeterminate={\n          checkedState === \"indeterminate\" ? \"true\" : undefined\n        }\n        data-invalid={resolvedInvalid ? \"true\" : undefined}\n        data-readonly={readOnly ? \"true\" : undefined}\n        data-required={required ? \"true\" : undefined}\n        className={checkboxClassNames({ className, controlSize })}\n      >\n        <input\n          {...props}\n          ref={composeRefs(inputRef, ref)}\n          aria-checked={checkedState === \"indeterminate\" ? \"mixed\" : undefined}\n          aria-invalid={invalid ? true : ariaInvalid}\n          aria-readonly={readOnly ? true : undefined}\n          checked={checkedState === true}\n          className={checkboxInputClasses}\n          data-slot=\"checkbox-input\"\n          data-size={controlSize}\n          data-state={state}\n          data-checked={checkedState === true ? \"true\" : undefined}\n          data-disabled={disabled ? \"true\" : undefined}\n          data-indeterminate={\n            checkedState === \"indeterminate\" ? \"true\" : undefined\n          }\n          data-invalid={resolvedInvalid ? \"true\" : undefined}\n          data-readonly={readOnly ? \"true\" : undefined}\n          data-required={required ? \"true\" : undefined}\n          disabled={disabled}\n          onChange={handleChange}\n          onClick={handleClick}\n          readOnly={readOnly}\n          required={required}\n          type=\"checkbox\"\n        />\n        <span\n          aria-hidden=\"true\"\n          data-slot=\"checkbox-indicator\"\n          data-size={controlSize}\n          data-state={state}\n          data-checked={checkedState === true ? \"true\" : undefined}\n          data-disabled={disabled ? \"true\" : undefined}\n          data-indeterminate={\n            checkedState === \"indeterminate\" ? \"true\" : undefined\n          }\n          data-invalid={resolvedInvalid ? \"true\" : undefined}\n          data-readonly={readOnly ? \"true\" : undefined}\n          data-required={required ? \"true\" : undefined}\n          className={checkboxIndicatorBaseClasses}\n        >\n          <span className=\"grid place-items-center\">\n            <span\n              data-slot=\"checkbox-check\"\n              className={cn(\n                \"motion-safe:ease-control col-start-1 row-start-1 motion-safe:transition-[opacity,scale] motion-safe:duration-[var(--dt-motion-fast)]\",\n                checkedState === true\n                  ? \"scale-100 opacity-100\"\n                  : \"opacity-0 motion-safe:scale-50\",\n              )}\n            >\n              <CheckIcon />\n            </span>\n            <span\n              data-slot=\"checkbox-mixed\"\n              className={cn(\n                \"motion-safe:ease-control col-start-1 row-start-1 motion-safe:transition-[opacity,scale] motion-safe:duration-[var(--dt-motion-fast)]\",\n                checkedState === \"indeterminate\"\n                  ? \"scale-100 opacity-100\"\n                  : \"opacity-0 motion-safe:scale-50\",\n              )}\n            >\n              <MinusIcon />\n            </span>\n          </span>\n        </span>\n      </span>\n    );\n  },\n);\n\nCheckbox.displayName = \"Checkbox\";\n"
    },
    {
      "path": "packages/components/src/components/checkbox/index.ts",
      "type": "registry:file",
      "target": "~/components/dethink/components/checkbox/index.ts",
      "content": "export {\n  Checkbox,\n  checkboxClassNames,\n  type CheckboxCheckedState,\n  type CheckboxControlSize,\n  type CheckboxProps,\n} from \"./checkbox\";\n"
    },
    {
      "path": "packages/components/src/utils/cn.ts",
      "type": "registry:file",
      "target": "~/components/dethink/utils/cn.ts",
      "content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n"
    }
  ]
}
