{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "author": "Lopifi (https://lopifi.com)",
  "categories": [
    "payments",
    "finance",
    "accounting"
  ],
  "dependencies": [
    "@base-ui-components/react"
  ],
  "description": "Amount, destination, timing. Hold-to-confirm.",
  "files": [
    {
      "content": "\"use client\";\n\nimport { Dialog } from \"@base-ui-components/react/dialog\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/ledger/cn\";\nimport { formatDate } from \"@/lib/ledger/fiscal-period\";\nimport type { MoneyValue } from \"@/lib/ledger/money.types\";\nimport { Button } from \"@/components/ledger/button\";\nimport { HoldToConfirm } from \"@/components/ledger/hold-to-confirm\";\nimport { Money } from \"@/components/ledger/money\";\nimport { MaskedAccount } from \"@/components/ledger/reference\";\n\nexport interface ConfirmPaymentDialogProps {\n  amount: MoneyValue;\n  arrivalDate: Date;\n  /** Wires and post-cutoff ACH: irreversible, so hold-to-confirm. */\n  irreversible?: boolean;\n  onConfirm: () => void;\n  onOpenChange: (open: boolean) => void;\n  open: boolean;\n  payeeLast4: string;\n  payeeName: string;\n}\n\n/**\n * Amount, destination, timing. In that order. Every time.\n *\n * Focus lands on Cancel, never on the destructive action. Escape cancels.\n */\nexport function ConfirmPaymentDialog({\n  open,\n  onOpenChange,\n  amount,\n  payeeName,\n  payeeLast4,\n  arrivalDate,\n  irreversible = true,\n  onConfirm,\n}: ConfirmPaymentDialogProps) {\n  const cancelRef = React.useRef<HTMLButtonElement>(null);\n\n  return (\n    <Dialog.Root onOpenChange={onOpenChange} open={open}>\n      <Dialog.Portal>\n        <Dialog.Backdrop className=\"fixed inset-0 z-overlay bg-[oklch(0.21_0.02_265/0.4)] data-[open]:animate-[ledger-enter_240ms_var(--ease-out)]\" />\n        <Dialog.Popup\n          className={cn(\n            // Dialogs stay centred. No transform-origin games.\n            \"fixed left-1/2 top-1/2 z-dialog w-[calc(100vw-32px)] max-w-[420px]\",\n            \"-translate-x-1/2 -translate-y-1/2 rounded-xl border border-border bg-surface-raised p-6\",\n            \"shadow-elevation-4 outline-none\",\n            \"data-[open]:ledger-enter\",\n          )}\n          /* Money leaves the building here: focus lands on Cancel. */\n          initialFocus={cancelRef}\n          role=\"alertdialog\"\n        >\n          <Dialog.Title className=\"text-title-md font-medium\">\n            Send <Money className=\"align-baseline\" size=\"md\" value={amount} /> to {payeeName}?\n          </Dialog.Title>\n          <Dialog.Description className=\"mt-2 space-y-1 text-body text-text-secondary\" render={<div />}>\n            <p className=\"flex items-center gap-1\">\n              To account <MaskedAccount last4={payeeLast4} /> · Arrives {formatDate(arrivalDate)}\n            </p>\n            {irreversible ? <p className=\"text-text-primary\">This can’t be undone once submitted.</p> : null}\n          </Dialog.Description>\n\n          <div className=\"mt-6 flex flex-col gap-3\">\n            {irreversible ? (\n              <HoldToConfirm\n                label={`Hold to send ${plain(amount)}`}\n                onConfirm={() => {\n                  onConfirm();\n                  onOpenChange(false);\n                }}\n                typedConfirmation=\"SEND\"\n              />\n            ) : (\n              <Button\n                onClick={() => {\n                  onConfirm();\n                  onOpenChange(false);\n                }}\n                variant=\"primary\"\n              >\n                Send {plain(amount)}\n              </Button>\n            )}\n            <Dialog.Close render={<Button ref={cancelRef} variant=\"secondary\" />}>Cancel</Dialog.Close>\n          </div>\n        </Dialog.Popup>\n      </Dialog.Portal>\n    </Dialog.Root>\n  );\n}\n\nfunction plain(value: MoneyValue) {\n  return new Intl.NumberFormat(\"en-US\", {\n    currency: value.currency,\n    currencyDisplay: \"narrowSymbol\",\n    style: \"currency\",\n  }).format(Number(value.amount) / 10 ** (value.scale ?? 2));\n}\n",
      "path": "components/ledger/confirm-payment-dialog.tsx",
      "target": "components/ledger/confirm-payment-dialog.tsx",
      "type": "registry:component"
    }
  ],
  "name": "confirm-payment-dialog",
  "registryDependencies": [
    "@lopifi/theme",
    "@lopifi/button",
    "@lopifi/cn",
    "@lopifi/fiscal-period",
    "@lopifi/hold-to-confirm",
    "@lopifi/money",
    "@lopifi/money.types",
    "@lopifi/reference"
  ],
  "title": "ConfirmPaymentDialog",
  "type": "registry:component"
}
