{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "author": "Lopifi (https://lopifi.com)",
  "categories": [
    "statements",
    "finance",
    "accounting"
  ],
  "dependencies": [],
  "description": "P&L with period comparison and variance.",
  "files": [
    {
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/ledger/cn\";\nimport {\n  type DrilldownTarget,\n  type StatementHeader,\n  type StatementLine,\n  StatementTable,\n} from \"@/components/ledger/statement-table\";\n\nexport interface ProfitAndLossProps {\n  className?: string;\n  /** Offer the period columns to hide. See `StatementTable`. */\n  columnManager?: boolean;\n  header: Omit<StatementHeader, \"statement\">;\n  /** Margin rows are Percent, not Money, and visually distinguished. */\n  margins?: StatementLine[];\n  materiality?: { absolute: number; relative: number };\n  /** Caps the scroller so the column headers freeze. See `StatementTable`. */\n  maxHeight?: number;\n  /** EBITDA is not a P&L line. If shown, it appears below, separated. */\n  nonGaap?: React.ReactNode;\n  onDrilldown?: (line: StatementLine, target: DrilldownTarget) => void;\n  periods: string[];\n  /** Revenue → COGS → Gross profit → Opex → Operating income → Other → Net income. */\n  sections: StatementLine[];\n  showVariance?: boolean;\n}\n\n/**\n * Expense rows are `polarity=\"inverted\"` — an increase in COGS is not good\n * news, and defaulting it to green is the bug this whole system exists to\n * prevent. The polarity is read from the account type, not chosen per call.\n */\nexport function ProfitAndLoss({\n  header,\n  periods,\n  sections,\n  margins = [],\n  showVariance = true,\n  materiality,\n  onDrilldown,\n  nonGaap,\n  maxHeight,\n  columnManager,\n  className,\n}: ProfitAndLossProps) {\n  const lines = React.useMemo(\n    () => [...sections, ...(margins.length ? [MARGIN_SECTION, ...margins] : [])],\n    [sections, margins],\n  );\n\n  return (\n    <div className={cn(\"w-full\", className)}>\n      <StatementTable\n        columnManager={columnManager}\n        header={{ ...header, statement: \"Profit and loss\" }}\n        lines={lines}\n        materiality={materiality}\n        maxHeight={maxHeight}\n        onDrilldown={onDrilldown}\n        periods={periods}\n        roundingNote=\"Figures are rounded once, at the display boundary. Parts may not sum.\"\n        showVariance={showVariance}\n      />\n      {nonGaap ? (\n        // Non-GAAP measures appear below net income, in a separated block,\n        // never inside the P&L.\n        <section className=\"mt-6 rounded-xl border border-dashed border-border bg-surface-sunken p-6\">\n          <h3 className=\"text-title-sm font-medium\">Non-GAAP measures</h3>\n          <p className=\"mb-4 text-caption text-text-secondary\">\n            Not defined by the framework. Every adjustment is named below.\n          </p>\n          {nonGaap}\n        </section>\n      ) : null}\n    </div>\n  );\n}\n\nconst MARGIN_SECTION: StatementLine = {\n  id: \"margins\",\n  label: \"Margins\",\n  level: 1,\n  values: [],\n  variant: \"section\",\n};\n",
      "path": "components/ledger/profit-and-loss.tsx",
      "target": "components/ledger/profit-and-loss.tsx",
      "type": "registry:component"
    }
  ],
  "name": "profit-and-loss",
  "registryDependencies": [
    "@lopifi/theme",
    "@lopifi/cn",
    "@lopifi/statement-table"
  ],
  "title": "ProfitAndLoss",
  "type": "registry:component"
}
