{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "billing-5",
  "title": "Saved Payment Methods",
  "description": "Payment methods list of saved cards with a default badge, set-default and remove actions, and an add-card dialog.",
  "dependencies": [
    "@base-ui/react"
  ],
  "registryDependencies": [
    "badge",
    "button",
    "dialog",
    "field",
    "input",
    "separator"
  ],
  "files": [
    {
      "path": "registry/blocks/billing/5/billing-block.tsx",
      "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from \"@/components/ui/dialog\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport { Separator } from \"@/components/ui/separator\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\ntype CardEntry = {\n  id: string\n  brand: string\n  last4: string\n  expiry: string\n}\n\nconst initialCards: CardEntry[] = [\n  { id: \"c1\", brand: \"Visa\", last4: \"4242\", expiry: \"08/27\" },\n  { id: \"c2\", brand: \"Mastercard\", last4: \"5100\", expiry: \"01/26\" },\n]\n\nexport default function BillingBlock() {\n  const [cards, setCards] = useState(initialCards)\n  const [defaultId, setDefaultId] = useState(\"c1\")\n  const [open, setOpen] = useState(false)\n\n  return (\n    <section className=\"flex w-full items-start justify-center bg-background px-6 py-16 text-foreground\">\n      <div className=\"w-full max-w-lg rounded-xl border border-border bg-card\">\n        <div className=\"flex items-center justify-between border-b border-border px-5 py-4\">\n          <div className=\"flex flex-col gap-0.5\">\n            <h2 className=\"font-heading text-sm font-semibold tracking-tight\">\n              Payment methods\n            </h2>\n            <p className=\"text-xs text-muted-foreground\">\n              Manage the cards used to pay for your subscription.\n            </p>\n          </div>\n          <Dialog open={open} onOpenChange={setOpen}>\n            <DialogTrigger render={<Button size=\"sm\" variant=\"outline\" />}>\n              <IconPlaceholder\n                lucide=\"Plus\"\n                tabler=\"IconPlus\"\n                hugeicons=\"Add01Icon\"\n                phosphor=\"Plus\"\n                remixicon=\"RiAddLine\"\n                data-icon=\"inline-start\"\n                aria-hidden=\"true\"\n              />\n              Add\n            </DialogTrigger>\n            <DialogContent>\n              <DialogHeader>\n                <DialogTitle>Add payment method</DialogTitle>\n                <DialogDescription>\n                  Your card is encrypted and stored securely.\n                </DialogDescription>\n              </DialogHeader>\n              <FieldGroup>\n                <Field>\n                  <FieldLabel htmlFor=\"number\">Card number</FieldLabel>\n                  <Input id=\"number\" placeholder=\"1234 1234 1234 1234\" />\n                </Field>\n                <div className=\"grid grid-cols-2 gap-3\">\n                  <Field>\n                    <FieldLabel htmlFor=\"expiry\">Expiry</FieldLabel>\n                    <Input id=\"expiry\" placeholder=\"MM/YY\" />\n                  </Field>\n                  <Field>\n                    <FieldLabel htmlFor=\"cvc\">CVC</FieldLabel>\n                    <Input id=\"cvc\" placeholder=\"123\" />\n                  </Field>\n                </div>\n              </FieldGroup>\n              <DialogFooter>\n                <Button variant=\"outline\" onClick={() => setOpen(false)}>\n                  Cancel\n                </Button>\n                <Button onClick={() => setOpen(false)}>Add card</Button>\n              </DialogFooter>\n            </DialogContent>\n          </Dialog>\n        </div>\n\n        <ul className=\"flex flex-col divide-y divide-border\">\n          {cards.map((card) => (\n            <li key={card.id} className=\"flex items-center gap-3 px-5 py-4\">\n              <span className=\"flex size-9 shrink-0 items-center justify-center rounded-md border border-border\">\n                <IconPlaceholder\n                  lucide=\"CreditCard\"\n                  tabler=\"IconCreditCard\"\n                  hugeicons=\"CreditCardIcon\"\n                  phosphor=\"CreditCard\"\n                  remixicon=\"RiBankCardLine\"\n                  className=\"size-4\"\n                  aria-hidden=\"true\"\n                />\n              </span>\n              <div className=\"flex min-w-0 flex-1 flex-col\">\n                <span className=\"flex items-center gap-2 text-sm font-medium\">\n                  {card.brand} •••• {card.last4}\n                  {card.id === defaultId && (\n                    <Badge variant=\"secondary\" className=\"text-[10px]\">\n                      Default\n                    </Badge>\n                  )}\n                </span>\n                <span className=\"text-xs text-muted-foreground tabular-nums\">\n                  Expires {card.expiry}\n                </span>\n              </div>\n              <div className=\"flex items-center gap-1\">\n                {card.id !== defaultId && (\n                  <Button\n                    variant=\"ghost\"\n                    size=\"xs\"\n                    onClick={() => setDefaultId(card.id)}\n                  >\n                    Set default\n                  </Button>\n                )}\n                <Button\n                  variant=\"ghost\"\n                  size=\"xs\"\n                  className=\"text-muted-foreground hover:text-foreground\"\n                  disabled={card.id === defaultId}\n                  onClick={() =>\n                    setCards((prev) => prev.filter((c) => c.id !== card.id))\n                  }\n                >\n                  Remove\n                </Button>\n              </div>\n            </li>\n          ))}\n        </ul>\n\n        <Separator />\n        <p className=\"px-5 py-3 text-xs text-muted-foreground\">\n          Payments are processed securely. We never store your full card number.\n        </p>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component"
    }
  ],
  "meta": {
    "height": "387px",
    "tier": "free"
  },
  "docs": "Requires a `base-*` style in components.json (the `shadcn init` default). Legacy `new-york`/`radix-*` styles install Radix primitives, which reject the `render` prop this block uses.",
  "categories": [
    "billing"
  ],
  "type": "registry:block"
}