{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"switch","type":"registry:component","title":"Switch","description":"On and off switch with a quick slide and no bounce. Inside a label, the whole row is the tap target.","author":"Ryan","dependencies":["clsx","tailwind-merge"],"registryDependencies":[],"files":[{"path":"components/motion/switch.tsx","type":"registry:component","target":"@components/motion/switch.tsx","content":"\"use client\";\n// easeui.dev/components/motion/switch\n\nimport { type ButtonHTMLAttributes, forwardRef, useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport type SwitchSize = \"sm\" | \"md\";\n\nexport interface SwitchProps\n  extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"onChange\" | \"value\" | \"defaultValue\"> {\n  /** Controlled on state. */\n  checked?: boolean;\n  /** Starting state when uncontrolled. Default false. */\n  defaultChecked?: boolean;\n  /** Called with the next state each time the switch is toggled. */\n  onCheckedChange?: (checked: boolean) => void;\n  /** Track size. Default \"md\". */\n  size?: SwitchSize;\n}\n\nconst SIZES: Record<SwitchSize, { track: string; thumb: string }> = {\n  sm: { track: \"h-5 w-9\", thumb: \"h-4 w-4 group-data-[state=on]:translate-x-4\" },\n  md: { track: \"h-6 w-11\", thumb: \"h-5 w-5 group-data-[state=on]:translate-x-5\" },\n};\n\n/**\n * An on and off switch. Put it inside a label and the whole row becomes the\n * tap target, with no dead space between the text and the track.\n */\nexport const Switch = forwardRef<HTMLButtonElement, SwitchProps>(function Switch(\n  { checked, defaultChecked = false, onCheckedChange, size = \"md\", className, onClick, ...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    <button\n      ref={ref}\n      type=\"button\"\n      role=\"switch\"\n      aria-checked={on}\n      data-state={on ? \"on\" : \"off\"}\n      onClick={(event) => {\n        onClick?.(event);\n        if (event.defaultPrevented) return;\n        if (!isControlled) setUncontrolled(!on);\n        onCheckedChange?.(!on);\n      }}\n      className={cn(\n        \"group relative inline-flex shrink-0 touch-manipulation items-center rounded-full p-0.5 outline-none\",\n        \"bg-foreground/15 transition-colors duration-150 ease-out data-[state=on]:bg-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 tall without changing the layout.\n        \"after:absolute after:-inset-x-1 after:-inset-y-2.5\",\n        SIZES[size].track,\n        className,\n      )}\n      {...props}\n    >\n      <span\n        aria-hidden=\"true\"\n        className={cn(\n          \"block rounded-full bg-white shadow-[0_1px_2px_rgb(0_0_0/0.25)] transition-[translate] duration-150 ease-out motion-reduce:transition-none\",\n          SIZES[size].thumb,\n        )}\n      />\n    </button>\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"}]}