{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "author": "Lopifi (https://lopifi.com)",
  "categories": [
    "swaps-fx",
    "finance",
    "accounting"
  ],
  "dependencies": [],
  "description": "Position by currency with unrealized gain/loss.",
  "files": [
    {
      "content": "import * as React from \"react\";\nimport { useScrollEdges } from \"@/hooks/ledger/use-scroll-edges\";\nimport { cn } from \"@/lib/ledger/cn\";\nimport type { MoneyValue } from \"@/lib/ledger/money.types\";\nimport { AsOf } from \"@/components/ledger/as-of\";\nimport { CurrencyBadge } from \"@/components/ledger/currency-badge\";\nimport { Delta } from \"@/components/ledger/delta\";\nimport { Money } from \"@/components/ledger/money\";\nimport { Rule } from \"@/components/ledger/rule\";\n\nexport type Position = {\n  currency: string;\n  position: MoneyValue;\n  /** In the presentation currency, at the stated rate. */\n  presentationValue: MoneyValue;\n  rate: number;\n  /** Realized and unrealized are different facts. Never combined. */\n  unrealized: MoneyValue;\n  realized: MoneyValue;\n};\n\nexport interface FxExposureProps extends React.ComponentPropsWithoutRef<\"div\"> {\n  asOf: Date;\n  /** Caps the scroller so the header and the currency column can freeze. */\n  maxHeight?: number;\n  positions: Position[];\n  presentationCurrency: string;\n  totalRealized: MoneyValue;\n  totalUnrealized: MoneyValue;\n}\n\nexport const FxExposure = React.forwardRef<HTMLDivElement, FxExposureProps>(\n  (\n    {\n      className,\n      positions,\n      presentationCurrency,\n      totalUnrealized,\n      totalRealized,\n      asOf,\n      maxHeight = 520,\n      ...props\n    },\n    ref,\n  ) => {\n    const scroller = useScrollEdges<HTMLDivElement>();\n    return (\n      <div className={cn(\"rounded-xl border border-border bg-surface\", className)} ref={ref} {...props}>\n        <div className=\"px-6 pb-4 pt-6\">\n          <p className=\"text-title-sm font-medium\">FX exposure</p>\n          <p className=\"text-caption text-text-secondary\">\n            Presented in {presentationCurrency} · <AsOf date={asOf} />\n          </p>\n        </div>\n        <div className=\"ledger-frozen scrollbar-thin\" ref={scroller} style={{ maxHeight }}>\n          <table className=\"w-full min-w-[640px]\">\n            <caption className=\"sr-only\">FX exposure, presented in {presentationCurrency}</caption>\n            <thead>\n              <tr className=\"border-b border-border-subtle\">\n                <th className=\"px-6 py-3 text-left text-label text-text-secondary\" scope=\"col\">\n                  Currency\n                </th>\n                <th className=\"px-3 py-3 text-right text-label text-text-secondary\" scope=\"col\">\n                  Position\n                </th>\n                <th className=\"px-3 py-3 text-right text-label text-text-secondary\" scope=\"col\">\n                  Rate\n                </th>\n                <th className=\"px-3 py-3 text-right text-label text-text-secondary\" scope=\"col\">\n                  Value ({presentationCurrency})\n                </th>\n                <th className=\"px-3 py-3 text-right text-label text-text-secondary\" scope=\"col\">\n                  Unrealized\n                </th>\n                <th className=\"px-6 py-3 text-right text-label text-text-secondary\" scope=\"col\">\n                  Realized\n                </th>\n              </tr>\n            </thead>\n            <tbody>\n              {positions.map((p) => (\n                <tr className=\"border-b border-border-subtle\" key={p.currency}>\n                  <th className=\"px-6 py-3 text-left\" scope=\"row\">\n                    <CurrencyBadge currency={p.currency} />\n                  </th>\n                  <td className=\"px-3 py-3 text-right\">\n                    <Money accounting showCode value={p.position} />\n                  </td>\n                  <td className=\"numeric px-3 py-3 text-right text-figure-sm text-text-secondary\">\n                    {p.rate.toFixed(5)}\n                  </td>\n                  <td className=\"px-3 py-3 text-right\">\n                    <Money accounting value={p.presentationValue} />\n                  </td>\n                  <td className=\"px-3 py-3 text-right\">\n                    <Delta polarity=\"standard\" showArrow={false} value={p.unrealized} />\n                  </td>\n                  <td className=\"px-6 py-3 text-right\">\n                    <Delta polarity=\"standard\" showArrow={false} value={p.realized} />\n                  </td>\n                </tr>\n              ))}\n            </tbody>\n            <tfoot>\n              <tr>\n                <td colSpan={4} />\n                <td className=\"px-3\">\n                  <Rule variant=\"subtotal\" />\n                </td>\n                <td className=\"px-6\">\n                  <Rule variant=\"subtotal\" />\n                </td>\n              </tr>\n              <tr>\n                <th className=\"px-6 py-3 text-left text-label font-medium\" scope=\"row\">\n                  Total\n                </th>\n                <td colSpan={3} />\n                <td className=\"px-3 py-3 text-right\">\n                  <Money accounting size=\"md\" value={totalUnrealized} />\n                </td>\n                <td className=\"px-6 py-3 text-right\">\n                  <Money accounting size=\"md\" value={totalRealized} />\n                </td>\n              </tr>\n            </tfoot>\n          </table>\n        </div>\n      </div>\n    );\n  },\n);\nFxExposure.displayName = \"FxExposure\";\n",
      "path": "components/ledger/fx-exposure.tsx",
      "target": "components/ledger/fx-exposure.tsx",
      "type": "registry:component"
    }
  ],
  "name": "fx-exposure",
  "registryDependencies": [
    "@lopifi/theme",
    "@lopifi/as-of",
    "@lopifi/cn",
    "@lopifi/currency-badge",
    "@lopifi/delta",
    "@lopifi/money",
    "@lopifi/money.types",
    "@lopifi/rule",
    "@lopifi/use-scroll-edges"
  ],
  "title": "FxExposure",
  "type": "registry:component"
}
