{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "author": "Lopifi (https://lopifi.com)",
  "categories": [
    "cards",
    "finance",
    "accounting"
  ],
  "dependencies": [],
  "description": "Bank account with available vs. current.",
  "files": [
    {
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/ledger/cn\";\nimport { formatTimestamp } from \"@/lib/ledger/fiscal-period\";\nimport type { MoneyValue } from \"@/lib/ledger/money.types\";\nimport { AsOf } from \"@/components/ledger/as-of\";\nimport { Button } from \"@/components/ledger/button\";\nimport { Card } from \"@/components/ledger/card\";\nimport { EntityMark } from \"@/components/ledger/entity-mark\";\nimport { ChevronRightIcon, ExclamationTriangleIcon } from \"@/components/ledger/icons\";\nimport { InfoTip } from \"@/components/ledger/info-tip\";\nimport { Money } from \"@/components/ledger/money\";\nimport { MaskedAccount } from \"@/components/ledger/reference\";\n\nexport interface AccountCardProps extends React.ComponentPropsWithoutRef<\"div\"> {\n  accountType: string;\n  available: MoneyValue | null;\n  connection?: \"connected\" | \"disconnected\" | \"reauth-required\";\n  current: MoneyValue | null;\n  institution: string;\n  institutionSrc?: string;\n  last4: string;\n  lastSynced: Date;\n  onOpen?: () => void;\n  onReconnect?: () => void;\n}\n\n/**\n * A stale bank connection silently showing an old balance is a real\n * financial hazard, so disconnected and reauth-required are prominent\n * states, not a subtle badge.\n */\nexport const AccountCard = React.forwardRef<HTMLDivElement, AccountCardProps>(\n  (\n    {\n      className,\n      institution,\n      institutionSrc,\n      accountType,\n      last4,\n      available,\n      current,\n      lastSynced,\n      connection = \"connected\",\n      onOpen,\n      onReconnect,\n      ...props\n    },\n    ref,\n  ) => {\n    const broken = connection !== \"connected\";\n    const syncedAt = formatTimestamp(lastSynced);\n    return (\n      <Card className={cn(\"flex flex-col gap-4\", className)} ref={ref} stale={broken} {...props}>\n        <div className=\"flex items-start gap-3\">\n          <EntityMark category=\"bank\" name={institution} size={40} src={institutionSrc} />\n          <div className=\"min-w-0 flex-1\">\n            <p className=\"truncate text-body font-medium\">{institution}</p>\n            <p className=\"flex items-center gap-2 text-caption text-text-secondary\">\n              {accountType}\n              <span aria-hidden=\"true\">·</span>\n              <MaskedAccount last4={last4} />\n            </p>\n          </div>\n          {onOpen ? (\n            <Button\n              aria-label={`Open ${institution} transactions`}\n              onClick={onOpen}\n              size=\"icon\"\n              variant=\"ghost\"\n            >\n              <ChevronRightIcon aria-hidden=\"true\" className=\"size-4\" />\n            </Button>\n          ) : null}\n        </div>\n\n        <div className=\"grid grid-cols-2 gap-4\">\n          <div>\n            <span className=\"block text-caption text-text-secondary\">Available</span>\n            <Money className=\"mt-0.5\" size=\"md\" value={available} />\n          </div>\n          <div>\n            <span className=\"block text-caption text-text-secondary\">Current</span>\n            <Money className=\"mt-0.5\" size=\"md\" tone=\"secondary\" value={current} />\n          </div>\n        </div>\n\n        {broken ? (\n          <div className=\"flex items-center gap-2 rounded-sm bg-negative-subtle px-3 py-2\">\n            <ExclamationTriangleIcon aria-hidden=\"true\" className=\"size-3.5 shrink-0 text-negative\" />\n            <span className=\"flex min-w-0 flex-1 items-center gap-1.5\">\n              <span className=\"truncate text-caption font-medium text-negative\">\n                {connection === \"reauth-required\" ? \"Reauthorization required\" : \"Disconnected\"}\n              </span>\n              <InfoTip\n                about={`Why ${institution} needs reconnecting`}\n                align=\"start\"\n                label=\"This balance may be out of date\"\n                side=\"top\"\n                triggerClassName=\"text-negative\"\n              >\n                {connection === \"reauth-required\"\n                  ? `${institution} revoked this connection's authorization — usually a password change or an expired consent.`\n                  : `The connection to ${institution} is down.`}{\" \"}\n                Last synced {syncedAt}.\n              </InfoTip>\n            </span>\n            <Button onClick={onReconnect} size=\"sm\" variant=\"secondary\">\n              Reconnect\n            </Button>\n          </div>\n        ) : (\n          <AsOf date={lastSynced} prefix=\"Synced\" />\n        )}\n      </Card>\n    );\n  },\n);\nAccountCard.displayName = \"AccountCard\";\n",
      "path": "components/ledger/account-card.tsx",
      "target": "components/ledger/account-card.tsx",
      "type": "registry:component"
    }
  ],
  "name": "account-card",
  "registryDependencies": [
    "@lopifi/theme",
    "@lopifi/as-of",
    "@lopifi/button",
    "@lopifi/card",
    "@lopifi/cn",
    "@lopifi/entity-mark",
    "@lopifi/fiscal-period",
    "@lopifi/icons",
    "@lopifi/info-tip",
    "@lopifi/money",
    "@lopifi/money.types",
    "@lopifi/reference"
  ],
  "title": "AccountCard",
  "type": "registry:component"
}
