# LedgerTable

> Double-entry with debit/credit columns and a balance check.

Source: https://lopifi.com/components/ledger-table
Part of: Lopifi — US GAAP books on autopilot, reviewed by a CPA (https://lopifi.com)

---

- **Family:** Ledger & tables — 
- **Status:** Implemented
- **Spec:** https://lopifi.com/docs/catalog/05-ledger-tables

## Install

```bash
npx shadcn@latest add @lopifi/theme
npx shadcn@latest add @lopifi/ledger-table
```

## Specification

Double-entry. **Debit and credit as two separate columns**, never one signed column — collapsing them destroys the reader's ability to verify, which is the entire purpose of double-entry. Column totals with the balance check displayed; a failing check is a prominent error state, not a silent discrepancy.

### The shared grid model

Every table in this family — and in statements, schedules and the close — is
driven by the same two primitives, because an accountant does not distinguish
between them. They arrive from a spreadsheet and press the arrow keys.

- **`useGridNav`** for tables that are already client components (`TransactionTable`).
  **`GridKeyboard`** wraps the ones that are deliberately server-rendered, reading
  the DOM they produced rather than forcing a rewrite — a 400-row statement should
  not ship 400 rows of JavaScript to be rendered twice.
- **One tab stop per grid.** Tab *to* the table, arrow *within* it. Arrows move,
  `Cmd`+arrow jumps to the edge, `PageUp`/`PageDown` move a screen, `Home`/`End`
  the row, `Space` selects, `Enter` opens, `Escape` collapses.
- **`Shift`+arrows select a block, `Cmd`+C copies it** — as TSV *and* as HTML, so
  every paste target gets its best flavour.
- **The clipboard carries the value, not the presentation.** `Money` stamps every
  figure with `data-raw`, so a copied column lands in Excel as `-1240.56` and
  sums. `($1,240.56)` pastes as text, and a column of text does not add up.
- **The label column freezes.** Any table wider than its container pins its row
  header with `FROZEN_LABEL` — scrolling a general ledger sideways and losing the
  account name is the exact motion this family exists to support.
- **Every column sorts and drags.** `ColumnHeader` for the tables that render their own
  rows, `TableColumns` for the ones that render on the server — the same split, and the
  same reason, as `useGridNav` and `GridKeyboard`.

## Rules this component obeys

Money is minor units, never floats. `null` is not `0` and neither is redacted. Negatives render in accounting parentheses with the parenthesis column reserved on both sides. Debit and credit are two columns. Per-currency decimal places. Polarity is explicit — up is not always good. Every figure states its period, entity, currency, basis and as-of.
