{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "upsell-addon-checkbox",
  "type": "registry:component",
  "title": "Add-on checkbox",
  "description": "One optional add-on row: warranty, refill, sample or packaging. Unchecked by default.",
  "author": "StoreKit <hello@storekit.dev>",
  "categories": [
    "upsell",
    "any"
  ],
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://storekit-eight.vercel.app/r/cn.json",
    "https://storekit-eight.vercel.app/r/sk-analytics.json"
  ],
  "files": [
    {
      "path": "upsell/upsell-addon-checkbox.tsx",
      "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { motion, useReducedMotion } from \"motion/react\"\nimport { cn, money } from \"@/components/storekit/lib/cn\"\nimport { useSkBlock } from \"@/components/storekit/lib/sk-analytics\"\n\n/* One optional add-on as a single checkbox row: a warranty, a refill, a\n   sample, gift packaging. The whole row is the hit target. Starts unchecked\n   by default, because a pre-ticked add-on is a charge the shopper did not\n   choose. Price is integer cents. */\n\nconst EASE = [0.23, 1, 0.32, 1] as const\nconst RING = \"outline-none focus-visible:ring-2 focus-visible:ring-sk-accent focus-visible:ring-offset-2 focus-visible:ring-offset-sk-paper\"\n\nexport function UpsellAddonCheckbox({\n  title = \"Add an electrolytes travel pack\",\n  description = \"10 sticks for the gym bag. Ships in the same box.\",\n  price = 900,\n  compareAt,\n  image,\n  checked: controlled,\n  defaultChecked = false,\n  onChange,\n  className,\n}: {\n  title?: string\n  description?: string\n  /** Add-on price in integer cents. 0 renders \"Free\". */\n  price?: number\n  compareAt?: number\n  image?: string\n  checked?: boolean\n  defaultChecked?: boolean\n  onChange?: (checked: boolean) => void\n  className?: string\n}) {\n  const reduce = useReducedMotion()\n  const sk = useSkBlock(\"upsell\", \"upsell-addon-checkbox\")\n  const [inner, setInner] = useState(defaultChecked)\n  const on = controlled ?? inner\n\n  const toggle = () => {\n    const next = !on\n    sk.emit(\"interact\", next ? \"addon_on\" : \"addon_off\", price)\n    if (controlled === undefined) setInner(next)\n    onChange?.(next)\n  }\n\n  return (\n    <button\n      {...sk.attrs}\n      ref={sk.ref as React.RefObject<HTMLButtonElement>}\n      type=\"button\"\n      role=\"checkbox\"\n      aria-checked={on}\n      onClick={toggle}\n      className={cn(\n        \"flex min-h-[64px] w-full items-center gap-3 rounded-sk-card border p-3 text-left transition-[border-color,background-color,transform] duration-200 active:scale-[0.97] sm:p-4\",\n        on ? \"border-sk-accent bg-sk-accent/[0.05]\" : \"border-sk-line border-dashed bg-sk-card hover:border-sk-ink/30\",\n        RING,\n        className\n      )}\n    >\n      <span\n        aria-hidden\n        className={cn(\n          \"grid h-5 w-5 shrink-0 place-items-center rounded-[6px] border transition-[background-color,border-color] duration-200\",\n          on ? \"border-sk-accent bg-sk-accent text-sk-accent-ink\" : \"border-sk-line bg-sk-card\"\n        )}\n      >\n        <svg viewBox=\"0 0 16 16\" className=\"h-3.5 w-3.5\" fill=\"none\">\n          <motion.path\n            d=\"M3.5 8.5l3 3 6-7\"\n            stroke=\"currentColor\"\n            strokeWidth={2.25}\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            initial={false}\n            animate={{ pathLength: on ? 1 : 0, opacity: on ? 1 : 0 }}\n            transition={{ duration: reduce ? 0 : 0.25, ease: EASE }}\n          />\n        </svg>\n      </span>\n      {image ? <img src={image} alt=\"\" className=\"h-11 w-11 shrink-0 rounded-sk-btn bg-sk-surface object-cover\" /> : null}\n      <span className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n        <span className=\"text-sm font-medium text-sk-ink\">{title}</span>\n        {description ? <span className=\"text-[13px] leading-[1.5] text-sk-muted\">{description}</span> : null}\n      </span>\n      <span className=\"flex shrink-0 flex-col items-end tabular-nums\">\n        <span className=\"text-sm font-semibold text-sk-price\">{price === 0 ? \"Free\" : `+${money(price)}`}</span>\n        {compareAt && compareAt > price ? <s className=\"text-[12px] text-sk-muted\">{money(compareAt)}</s> : null}\n      </span>\n    </button>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/storekit/upsell/upsell-addon-checkbox.tsx"
    }
  ],
  "meta": {
    "section": "upsell",
    "variant": "addon",
    "niche": [
      "any"
    ],
    "commerce": [
      "addon"
    ],
    "previewHeight": 300
  }
}