{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "alert-dialog",
  "type": "registry:ui",
  "title": "Alert Dialog",
  "description": "@interlace/ui — alert-dialog primitive (shadcn-compatible).",
  "dependencies": [
    "@base-ui/react"
  ],
  "registryDependencies": [
    "theme"
  ],
  "files": [
    {
      "path": "registry/interlace-ui/alert-dialog.tsx",
      "target": "components/ui/alert-dialog.tsx",
      "type": "registry:ui",
      "content": "'use client';\n\n/**\n * @interlace/ui — AlertDialog\n *\n * A modal confirmation dialog for *destructive or otherwise consequential*\n * actions (\"Delete project\", \"Sign out everywhere\"). Distinct from `Dialog`:\n * the underlying Base UI primitive disables outside-click and Escape-only\n * dismissal so the user MUST acknowledge with a deliberate Cancel/Confirm\n * action (WAI-ARIA `alertdialog` pattern). All keyboard / focus / ARIA come\n * from `@base-ui/react/alert-dialog`; this file is a pure styled surface.\n *\n * ## Anatomy\n *\n *   AlertDialog (Root, controlled or uncontrolled)\n *     ├─ AlertDialogTrigger (the originating button)\n *     └─ AlertDialogPortal (escape stacking context)\n *         ├─ AlertDialogBackdrop (fixed scrim — bg-foreground/60)\n *         └─ AlertDialogPopup (centered card — data-min-viewport root)\n *             ├─ AlertDialogTitle (\"Delete project?\")\n *             ├─ AlertDialogDescription (\"This cannot be undone.\")\n *             └─ AlertDialogClose (Cancel + Confirm slots — consumer-composed)\n *\n * ## MIN_VIEWPORT — 320\n *\n * A destructive confirmation must work on the narrowest supported phone\n * (iPhone SE, 320 CSS px). The popup is capped at `--container-prose`\n * (65ch) and centered with `inset-0` + flex — it gracefully shrinks below\n * its max-width on small viewports, so the 320-floor is structurally safe.\n *\n * | Rule | Concept                          | Where in this file                                            |\n * | ---- | -------------------------------- | ------------------------------------------------------------- |\n * | R4   | Extends Base UI part props       | `React.ComponentProps<typeof BaseAlertDialog.*>` on every part |\n * | R6   | data-slot on every named part    | `data-slot=\"alert-dialog\"` / `\"alert-dialog-trigger\"` / `…-portal\"` / `…-backdrop\"` / `…-popup\"` / `…-title\"` / `…-description\"` / `…-close\"` |\n * | R7   | className merged + ...rest       | `cn(BASE, className)` + `{...props}` spread on every part      |\n * | R8   | No `isXxx` prefix on booleans    | All booleans inherited from Base UI use the no-`is` form       |\n * | R11  | Composition over prop-drilling   | Trigger / Portal / Backdrop / Popup / Title / Description / Close compound parts |\n * | R12  | Reuse — don't wrap               | No bespoke Cancel/Confirm buttons — consumers slot their own   |\n * | R13  | Build with the ecosystem         | `@base-ui/react/alert-dialog` owns keyboard / focus / portal / ARIA |\n * | R14  | Controlled + uncontrolled        | Inherited from `BaseAlertDialog.Root` — `open` + `onOpenChange` + `defaultOpen` |\n * | R17  | API parity with shadcn           | Part names mirror shadcn/ui AlertDialog                        |\n * | R18  | Tailwind only — no inline style  | Every visual class is Tailwind; zero `style={{}}`              |\n * | R19  | Tokens only — no raw hex/rgba    | `bg-foreground/60`, `bg-card`, `text-card-foreground`, `p-(--spacing-lg)`, `max-w-(--container-prose)`, `text-h4`, `text-body`, `text-muted-foreground` |\n * | R20  | AA contrast                      | `bg-card` + `text-card-foreground` token pair clears AA in light + dark |\n * | R23  | CLS=0                            | Backdrop + popup are `fixed`; never affect document flow       |\n * | R24  | Product-neutral vocabulary       | Structural names only (Title, Description, Close)             |\n * | R25  | Client component                 | `'use client'` — Base UI dialog needs hooks + portals          |\n * | R26  | A11y from headless primitive     | Base UI implements WAI-ARIA `alertdialog`; focus trap inherited |\n */\n\nimport * as React from 'react';\nimport { AlertDialog as BaseAlertDialog } from '@base-ui/react/alert-dialog';\n\nimport { cn } from '@/lib/utils';\n\n/**\n * Minimum viable viewport (CSS px) for this primitive. The popup max-width\n * collapses to the available width below `--container-prose`, so a 320px\n * phone still renders a usable confirmation surface.\n */\nexport const MIN_VIEWPORT = 320 as const;\n\nfunction AlertDialog(props: React.ComponentProps<typeof BaseAlertDialog.Root>) {\n  return <BaseAlertDialog.Root data-slot=\"alert-dialog\" {...props} />;\n}\n\nfunction AlertDialogTrigger(\n  props: React.ComponentProps<typeof BaseAlertDialog.Trigger>,\n) {\n  return <BaseAlertDialog.Trigger data-slot=\"alert-dialog-trigger\" {...props} />;\n}\n\nfunction AlertDialogPortal(\n  props: React.ComponentProps<typeof BaseAlertDialog.Portal>,\n) {\n  return <BaseAlertDialog.Portal data-slot=\"alert-dialog-portal\" {...props} />;\n}\n\nfunction AlertDialogBackdrop({\n  className,\n  ...props\n}: React.ComponentProps<typeof BaseAlertDialog.Backdrop>) {\n  return (\n    <BaseAlertDialog.Backdrop\n      data-slot=\"alert-dialog-backdrop\"\n      className={cn(\n        'fixed inset-0 z-50 bg-foreground/60 data-[open]:animate-in data-[closed]:animate-out data-[closed]:fade-out-0 data-[open]:fade-in-0',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction AlertDialogPopup({\n  className,\n  ...props\n}: React.ComponentProps<typeof BaseAlertDialog.Popup>) {\n  return (\n    <BaseAlertDialog.Popup\n      data-slot=\"alert-dialog-popup\"\n      data-min-viewport={String(MIN_VIEWPORT)}\n      className={cn(\n        'fixed top-1/2 left-1/2 z-50 grid w-full max-w-(--container-prose) -translate-x-1/2 -translate-y-1/2 gap-md rounded-lg border bg-card p-(--spacing-lg) text-card-foreground shadow-xl outline-hidden data-[open]:animate-in data-[closed]:animate-out data-[closed]:fade-out-0 data-[open]:fade-in-0 data-[closed]:zoom-out-95 data-[open]:zoom-in-95',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction AlertDialogTitle({\n  className,\n  ...props\n}: React.ComponentProps<typeof BaseAlertDialog.Title>) {\n  return (\n    <BaseAlertDialog.Title\n      data-slot=\"alert-dialog-title\"\n      className={cn('font-body text-h4 font-semibold', className)}\n      {...props}\n    />\n  );\n}\n\nfunction AlertDialogDescription({\n  className,\n  ...props\n}: React.ComponentProps<typeof BaseAlertDialog.Description>) {\n  return (\n    <BaseAlertDialog.Description\n      data-slot=\"alert-dialog-description\"\n      className={cn('font-body text-body text-muted-foreground', className)}\n      {...props}\n    />\n  );\n}\n\nfunction AlertDialogClose(\n  props: React.ComponentProps<typeof BaseAlertDialog.Close>,\n) {\n  return <BaseAlertDialog.Close data-slot=\"alert-dialog-close\" {...props} />;\n}\n\nexport {\n  AlertDialog,\n  AlertDialogTrigger,\n  AlertDialogPortal,\n  AlertDialogBackdrop,\n  AlertDialogPopup,\n  AlertDialogTitle,\n  AlertDialogDescription,\n  AlertDialogClose,\n};\n"
    }
  ]
}
