{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "checkbox",
  "title": "Checkbox",
  "description": "Square toggle that fills and draws its check within 150 ms of the press, and announces the change through aria-checked.",
  "dependencies": [
    "radix-ui",
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "utils",
    "https://miseui.junsu4621.workers.dev/r/motion.json"
  ],
  "files": [
    {
      "path": "registry/miseui/ui/checkbox.tsx",
      "content": "import type * as React from \"react\"\nimport { useState } from \"react\"\nimport { Checkbox as CheckboxPrimitive } from \"radix-ui\"\nimport { Check } from \"lucide-react\"\nimport { motion, useReducedMotion } from \"motion/react\"\nimport { SPRING_DEFAULT } from \"@/registry/miseui/lib/motion\"\nimport { cn } from \"@/registry/miseui/lib/utils\"\n\nconst ROOT_CLASS = [\n  \"peer size-4 shrink-0 rounded-sm border border-input shadow-xs\",\n  \"transition-[color,background-color,border-color,box-shadow] duration-(--duration-fast) ease-(--ease-mise)\",\n  \"outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50\",\n  \"data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground\",\n  \"aria-invalid:border-destructive aria-invalid:ring-destructive/20\",\n  \"disabled:cursor-not-allowed disabled:opacity-50\",\n]\n\nconst DRAW_ROOT_CLASS = [\n  \"data-[state=checked]:border-mise data-[state=checked]:bg-mise data-[state=checked]:text-mise-foreground\",\n  \"data-[state=indeterminate]:border-mise data-[state=indeterminate]:bg-mise data-[state=indeterminate]:text-mise-foreground\",\n]\n\nconst CHECK_PATH = \"M3.25 8.5 6.5 11.75 12.75 4.5\"\nconst DASH_PATH = \"M4 8H12\"\nconst STROKE_WIDTH = 2.25\n/** A zero-length stroke with round caps still paints a dot, so the stroke fades once it has mostly retracted. */\nconst UNDRAW_FADE = { delay: 0.2, duration: 0.05 }\nconst REDUCED_TRANSITION = { pathLength: { duration: 0 }, opacity: { duration: 0.1 } }\n\ntype CheckboxEffect = \"draw\"\ntype CheckboxRootProps = React.ComponentProps<typeof CheckboxPrimitive.Root>\ntype CheckedValue = NonNullable<CheckboxRootProps[\"checked\"]>\n\ntype CheckboxProps = CheckboxRootProps & {\n  /** `draw` strokes the check on a spring, as if written by hand, and retracts it on the way out. */\n  effect?: CheckboxEffect\n}\n\nfunction Checkbox({ effect, className, ...props }: CheckboxProps) {\n  if (effect === \"draw\") return <DrawCheckbox className={className} {...props} />\n  return (\n    <CheckboxPrimitive.Root data-slot=\"checkbox\" className={cn(ROOT_CLASS, className)} {...props}>\n      <CheckboxPrimitive.Indicator\n        data-slot=\"checkbox-indicator\"\n        className=\"grid place-content-center text-current\"\n      >\n        <Check className=\"size-3.5\" aria-hidden=\"true\" />\n      </CheckboxPrimitive.Indicator>\n    </CheckboxPrimitive.Root>\n  )\n}\n\nfunction DrawCheckbox({ className, checked, defaultChecked, onCheckedChange, ...props }: CheckboxRootProps) {\n  const reduceMotion = useReducedMotion() ?? false\n  // Mirrors Radix's own state, because the stroke's target length has to be known in React.\n  const [uncontrolled, setUncontrolled] = useState<CheckedValue>(defaultChecked ?? false)\n  const state = checked ?? uncontrolled\n\n  return (\n    <CheckboxPrimitive.Root\n      data-slot=\"checkbox\"\n      data-effect=\"draw\"\n      className={cn(ROOT_CLASS, DRAW_ROOT_CLASS, className)}\n      checked={checked}\n      defaultChecked={defaultChecked}\n      onCheckedChange={(next) => {\n        setUncontrolled(next)\n        onCheckedChange?.(next)\n      }}\n      {...props}\n    >\n      {/* forceMount: Radix unmounts through CSS animations only, which would cut a retracting stroke short. */}\n      <CheckboxPrimitive.Indicator\n        forceMount\n        data-slot=\"checkbox-indicator\"\n        className=\"grid place-content-center text-current\"\n      >\n        <svg aria-hidden=\"true\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"size-3.5\">\n          <DrawStroke part=\"check\" d={CHECK_PATH} drawn={state === true} reduceMotion={reduceMotion} />\n          <DrawStroke part=\"dash\" d={DASH_PATH} drawn={state === \"indeterminate\"} reduceMotion={reduceMotion} />\n        </svg>\n      </CheckboxPrimitive.Indicator>\n    </CheckboxPrimitive.Root>\n  )\n}\n\ninterface DrawStrokeProps {\n  part: \"check\" | \"dash\"\n  d: string\n  drawn: boolean\n  reduceMotion: boolean\n}\n\nfunction DrawStroke({ part, d, drawn, reduceMotion }: DrawStrokeProps) {\n  return (\n    <motion.path\n      data-slot={`checkbox-${part}`}\n      data-drawn={drawn ? \"true\" : \"false\"}\n      d={d}\n      stroke=\"currentColor\"\n      strokeWidth={STROKE_WIDTH}\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      initial={false}\n      animate={{ pathLength: drawn ? 1 : 0, opacity: drawn ? 1 : 0 }}\n      transition={\n        reduceMotion ? REDUCED_TRANSITION : { pathLength: SPRING_DEFAULT, opacity: drawn ? { duration: 0 } : UNDRAW_FADE }\n      }\n    />\n  )\n}\n\nexport { Checkbox, type CheckboxEffect, type CheckboxProps }\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "forms"
  ],
  "type": "registry:ui"
}