{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "author": "Lopifi (https://lopifi.com)",
  "categories": [
    "cards",
    "finance",
    "accounting"
  ],
  "dependencies": [],
  "description": "A flagged deviation with its explanation.",
  "files": [
    {
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/ledger/cn\";\nimport type { MoneyValue, Polarity } from \"@/lib/ledger/money.types\";\nimport { Button } from \"@/components/ledger/button\";\nimport { Card } from \"@/components/ledger/card\";\nimport { Delta } from \"@/components/ledger/delta\";\nimport { ExclamationTriangleIcon } from \"@/components/ledger/icons\";\nimport { Money } from \"@/components/ledger/money\";\nimport { Tooltip } from \"@/components/ledger/tooltip\";\n\nexport interface AnomalyCardProps extends React.ComponentPropsWithoutRef<\"div\"> {\n  baseline: MoneyValue;\n  baselineLabel: string;\n  delta: MoneyValue;\n  explanation: string;\n  /** The comparison that triggered the flag. An anomaly without its baseline is noise. */\n  observed: MoneyValue;\n  onApprove?: () => void;\n  onCreateRule?: () => void;\n  onFlag?: () => void;\n  /** Required, no default. Most anomalies are spend (`inverted`), but a revenue\n      or cash anomaly is `standard`, and the card cannot tell which it holds. */\n  polarity: Polarity;\n  title: string;\n}\n\nexport const AnomalyCard = React.forwardRef<HTMLDivElement, AnomalyCardProps>(\n  (\n    {\n      className,\n      title,\n      observed,\n      baseline,\n      baselineLabel,\n      delta,\n      polarity,\n      explanation,\n      onApprove,\n      onFlag,\n      onCreateRule,\n      ...props\n    },\n    ref,\n  ) => (\n    <Card className={cn(\"flex flex-col gap-4\", className)} ref={ref} {...props}>\n      <div className=\"flex items-start gap-3\">\n        <div className=\"grid size-8 shrink-0 place-items-center rounded-sm bg-warning-subtle\">\n          <ExclamationTriangleIcon aria-hidden=\"true\" className=\"size-4 text-warning\" />\n        </div>\n        <div className=\"min-w-0\">\n          <p className=\"text-body font-medium\">{title}</p>\n          {/* The explanation is the card's substance, so it stays on the card —\n              but capped at two lines. A five-line paragraph pushes the figures\n              it exists to explain below the fold of a dashboard tile. */}\n          <Tooltip content={explanation} display=\"block\">\n            <p className=\"mt-1 line-clamp-2 text-caption text-text-secondary\">{explanation}</p>\n          </Tooltip>\n        </div>\n      </div>\n\n      <div className=\"grid grid-cols-2 gap-4 rounded-md bg-surface-sunken p-3\">\n        <div>\n          <span className=\"block text-caption text-text-secondary\">This period</span>\n          <Money className=\"mt-0.5\" size=\"md\" value={observed} />\n        </div>\n        <div>\n          <span className=\"block text-caption text-text-secondary\">{baselineLabel}</span>\n          <Money className=\"mt-0.5\" size=\"md\" tone=\"secondary\" value={baseline} />\n        </div>\n        <div className=\"col-span-2\">\n          {/* The baseline is the column header two inches away; repeating it\n              inline is the third mention. It rides on hover instead. */}\n          <Delta basisTooltip={`vs. ${baselineLabel.toLowerCase()}`} polarity={polarity} value={delta} />\n        </div>\n      </div>\n\n      <div className=\"flex flex-wrap gap-2\">\n        <Button onClick={onApprove} size=\"sm\" variant=\"primary\">\n          Approve\n        </Button>\n        <Button onClick={onFlag} size=\"sm\" variant=\"secondary\">\n          Flag for review\n        </Button>\n        <Button onClick={onCreateRule} size=\"sm\" variant=\"ghost\">\n          Create a rule\n        </Button>\n      </div>\n    </Card>\n  ),\n);\nAnomalyCard.displayName = \"AnomalyCard\";\n",
      "path": "components/ledger/anomaly-card.tsx",
      "target": "components/ledger/anomaly-card.tsx",
      "type": "registry:component"
    }
  ],
  "meta": {
    "license": "MIT"
  },
  "name": "anomaly-card",
  "registryDependencies": [
    "@lopifi/theme",
    "@lopifi/button",
    "@lopifi/card",
    "@lopifi/cn",
    "@lopifi/delta",
    "@lopifi/icons",
    "@lopifi/money",
    "@lopifi/money.types",
    "@lopifi/tooltip"
  ],
  "title": "AnomalyCard",
  "type": "registry:component"
}
