{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "shipping-method",
  "type": "registry:block",
  "title": "Shipping method selector",
  "description": "Delivery options as selectable cards over a native radio group, priced, with a free tier above an order total.",
  "author": "Box Kite <https://www.box-kite.dev>",
  "categories": [
    "ecommerce",
    "checkout",
    "form"
  ],
  "dependencies": [
    "@box-kite/react"
  ],
  "registryDependencies": [
    "https://www.box-kite.dev/r/store-design.json"
  ],
  "files": [
    {
      "path": "registry/designs/store/shipping-method.tsx",
      "content": "'use client';\nimport Flex from '@box-kite/react/components/flex';\nimport RadioGroup from '@box-kite/react/components/radioGroup';\nimport { Span } from '@box-kite/react/components/semantics';\nimport { formatPrice, type ShippingMethod as Method, shippingMethods } from './store-data';\n\nexport interface ShippingMethodProps {\n  methods?: readonly Method[];\n  value?: string;\n  onValueChange?: (id: string) => void;\n  /** Standard shipping is free above this subtotal. */\n  freeStandard?: boolean;\n}\n\n/**\n * Delivery options as cards. Each card is the `<label>` of a native radio, so the whole card is the\n * target, the set is one tab stop with the arrow keys inside it, and the chosen card is styled with\n * `:has(:checked)` — the radio itself stays visible, because it is what says this is a choice of one.\n */\nexport default function ShippingMethod({ methods = shippingMethods, value, onValueChange, freeStandard }: ShippingMethodProps) {\n  const priceOf = (method: Method) => (freeStandard && method.id === 'standard' ? 0 : method.price);\n\n  return (\n    <RadioGroup\n      label=\"Delivery\"\n      name=\"shipping.method\"\n      value={value}\n      defaultValue={value === undefined ? methods[0].id : undefined}\n      onValueChange={(id) => id && onValueChange?.(id)}\n      gap={3}\n    >\n      {methods.map((method) => (\n        <RadioGroup.Item\n          key={method.id}\n          value={method.id}\n          flexShrink={0}\n          labelProps={{\n            display: 'flex',\n            ai: 'center',\n            gap: 3,\n            p: 4,\n            b: 1,\n            borderRadius: 3,\n            cursor: 'pointer',\n            borderColor: 'stone-300',\n            bgColor: 'transparent',\n            hover: { borderColor: 'stone-500' },\n            has: { ':checked': { borderColor: 'stone-900', ring: 1, ringColor: 'stone-900' } },\n            theme: {\n              dark: {\n                borderColor: 'stone-700',\n                bgColor: 'transparent',\n                hover: { borderColor: 'stone-500' },\n                has: { ':checked': { borderColor: 'stone-100', ringColor: 'stone-100' } },\n              },\n            },\n          }}\n          label={\n            <Flex flex1 jc=\"space-between\" ai=\"center\" gap={4}>\n              <Flex d=\"column\" gap={0.5}>\n                <Span fontWeight={500}>{method.name}</Span>\n                <Span fontSize={14} color=\"stone-600\" theme={{ dark: { color: 'stone-400' } }}>\n                  {method.detail}\n                </Span>\n              </Flex>\n              <Span fontWeight={500}>{priceOf(method) ? formatPrice(priceOf(method)) : 'Free'}</Span>\n            </Flex>\n          }\n        />\n      ))}\n    </RadioGroup>\n  );\n}\n",
      "type": "registry:block",
      "target": "@components/box-kite/store/shipping-method.tsx"
    }
  ],
  "docs": "Render <ShippingMethod value={method} onValueChange={setMethod} />. Wrap it in <StoreSurface> from store-design.tsx, or render it inside one of the store pages."
}
