{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"checkbox","type":"registry:component","title":"Checkbox","description":"Checkbox on a real checkbox input, with a check mark that pops in rather than just appearing.","author":"Ryan","dependencies":["clsx","lucide-react","tailwind-merge"],"registryDependencies":[],"files":[{"path":"components/motion/checkbox.tsx","type":"registry:component","target":"@components/motion/checkbox.tsx","content":"\"use client\";\n// easeui.dev/components/motion/checkbox\n\nimport { Check } from \"lucide-react\";\nimport { forwardRef, type InputHTMLAttributes, useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n  /** Controlled checked state. */\n  checked?: boolean;\n  /** Starting state when uncontrolled. Default false. */\n  defaultChecked?: boolean;\n  /** Called with the next state each time the checkbox is toggled. */\n  onCheckedChange?: (checked: boolean) => void;\n}\n\n/**\n * A checkbox on a real checkbox input, with a check mark that pops in rather\n * than just appearing. Put it inside a label and the whole row becomes the\n * tap target, with no dead space between the text and the box.\n */\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n  { checked, defaultChecked = false, onCheckedChange, className, onChange, ...props },\n  ref,\n) {\n  const [uncontrolled, setUncontrolled] = useState(defaultChecked);\n  const isControlled = checked !== undefined;\n  const on = isControlled ? checked : uncontrolled;\n\n  return (\n    <span className={cn(\"relative inline-flex h-5 w-5 shrink-0 items-center justify-center\", className)}>\n      <input\n        ref={ref}\n        type=\"checkbox\"\n        checked={on}\n        onChange={(event) => {\n          onChange?.(event);\n          if (!isControlled) setUncontrolled(event.target.checked);\n          onCheckedChange?.(event.target.checked);\n        }}\n        className={cn(\n          \"peer absolute inset-0 m-0 h-5 w-5 shrink-0 touch-manipulation cursor-pointer appearance-none rounded-md outline-none\",\n          \"shadow-[0_0_0_1px_var(--border-strong)] transition-colors duration-150 ease-out\",\n          \"checked:bg-accent checked:shadow-[0_0_0_1px_var(--accent)]\",\n          \"focus-visible:ring-2 focus-visible:ring-foreground/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n          \"disabled:cursor-not-allowed disabled:opacity-50\",\n          // Grows the hit area to about 44px without changing the layout.\n          \"after:absolute after:-inset-3\",\n        )}\n        {...props}\n      />\n      <Check\n        aria-hidden=\"true\"\n        strokeWidth={3}\n        className=\"pointer-events-none relative h-3.5 w-3.5 scale-50 text-accent-foreground opacity-0 transition-[opacity,scale] duration-150 ease-out peer-checked:scale-100 peer-checked:opacity-100 motion-reduce:transition-none\"\n      />\n    </span>\n  );\n});\n"},{"path":"lib/utils.ts","type":"registry:lib","target":"@lib/utils.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"}]}