{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "cart-items",
  "type": "registry:block",
  "title": "Cart items",
  "description": "The lines of a shopping cart: picture, name, options, a quantity stepper, the line price and a remove button.",
  "author": "Box Kite <https://www.box-kite.dev>",
  "categories": [
    "ecommerce",
    "cart"
  ],
  "dependencies": [
    "@box-kite/react"
  ],
  "registryDependencies": [
    "https://www.box-kite.dev/r/store-design.json"
  ],
  "files": [
    {
      "path": "registry/designs/store/cart-items.tsx",
      "content": "'use client';\nimport Box from '@box-kite/react';\nimport Button from '@box-kite/react/components/button';\nimport Flex from '@box-kite/react/components/flex';\nimport { Li, Link, Span, Ul } from '@box-kite/react/components/semantics';\nimport ProductArt from './product-art';\nimport QuantityStepper from './quantity-stepper';\nimport { type CartLine, formatPrice, finishes, productBySlug } from './store-data';\nimport { useStoreLinks } from './store-design';\n\nexport interface CartItemsProps {\n  lines: readonly CartLine[];\n  onLinesChange: (lines: CartLine[]) => void;\n}\n\n/**\n * The lines of a cart: picture, name, the options chosen, a quantity stepper, the line's price and a way\n * out. It holds no state — the cart is the page's, so the summary beside it reads the same list.\n */\nexport default function CartItems({ lines, onLinesChange }: CartItemsProps) {\n  const links = useStoreLinks();\n  const update = (id: string, quantity: number) => onLinesChange(lines.map((line) => (line.id === id ? { ...line, quantity } : line)));\n  const remove = (id: string) => onLinesChange(lines.filter((line) => line.id !== id));\n\n  return (\n    <Ul listStyle=\"none\" m={0} p={0} bt={1} borderColor=\"stone-200\" theme={{ dark: { borderColor: 'stone-800' } }}>\n      {lines.map((line) => {\n        const product = productBySlug(line.slug);\n\n        return (\n          <Li key={line.id} display=\"flex\" gap={4} py={5} bb={1} borderColor=\"stone-200\" theme={{ dark: { borderColor: 'stone-800' } }}>\n            <Box flexShrink={0} width={24} height={24} sm={{ width: 28, height: 28 }}>\n              <ProductArt shape={product.shape} finish={line.finish} stroke={1} radius={3} />\n            </Box>\n            <Flex d=\"column\" flex1 minWidth={0} gap={1}>\n              <Flex jc=\"space-between\" gap={3}>\n                <Span fontSize={15} fontWeight={500}>\n                  <Link\n                    props={{ href: links.product(product.slug) }}\n                    color=\"currentColor\"\n                    textDecoration=\"none\"\n                    hover={{ textDecoration: 'underline' }}\n                  >\n                    {product.name}\n                  </Link>\n                </Span>\n                <Span fontWeight={500}>{formatPrice(product.price * line.quantity)}</Span>\n              </Flex>\n              <Span fontSize={14} color=\"stone-600\" theme={{ dark: { color: 'stone-400' } }}>\n                {[finishes[line.finish].name, line.size].filter(Boolean).join(' · ')}\n                {line.quantity > 1 && ` · ${formatPrice(product.price)} each`}\n              </Span>\n              <Flex ai=\"center\" jc=\"space-between\" gap={3} mt=\"auto\" pt={3}>\n                <QuantityStepper value={line.quantity} onChange={(quantity) => update(line.id, quantity)} item={product.name} />\n                <Button\n                  variant=\"ghost\"\n                  px={3}\n                  py={1.5}\n                  fontSize={14}\n                  textDecoration=\"underline\"\n                  onClick={() => remove(line.id)}\n                  props={{ 'aria-label': `Remove ${product.name} from the cart` }}\n                >\n                  Remove\n                </Button>\n              </Flex>\n            </Flex>\n          </Li>\n        );\n      })}\n    </Ul>\n  );\n}\n",
      "type": "registry:block",
      "target": "@components/box-kite/store/cart-items.tsx"
    }
  ],
  "docs": "Render <CartItems lines={lines} onLinesChange={setLines} /> — the cart is yours to keep. Wrap it in <StoreSurface> from store-design.tsx, or render it inside one of the store pages."
}
