import "./ledger.css"; import { type ReactNode } from "react"; import type * as React from "react"; import { useRender } from "@base-ui/react/use-render"; import { type StyleProps } from "./style_props"; /** Signed display: negatives render as "− " (a receipt against charges). * `n + 0` normalizes -0 (a zero receipts sum passed negated) to plain 0. * Exported for `RunningLedger`, which shares this exact glyph rule for every * money/quantity figure it renders — one definition, so the two components' * output can never drift into two different negative-number conventions. */ export declare function signed(format: (n: number) => string, n: number): string; export interface LedgerProps extends StyleProps { /** Money formatting shared by every row, sum, and total (e.g. `formatMoney`). */ formatValue: (n: number) => string; children: ReactNode; testID?: string; ref?: React.Ref; render?: useRender.RenderProp; } export declare function Ledger({ formatValue, children, testID, render, ref, ...props }: LedgerProps): React.JSX.Element; export interface LedgerGroupProps extends StyleProps { /** The group name ("Charges", "Received", a category). It travels WITH the sum when * there is one, and captions the rows from above when there is not. */ label: string; /** The group's sum, closing the rows BELOW it. Sign renders as "−" (pass receipts * negative). It must EQUAL the rows it closes — derive the rows and the sum from one * list, never from two predicates that can drift apart. * * Omit it for a group that only NAMES its rows: a sum earns its place by adding * something the rows do not already say, which a one-row group's sum does not. */ total?: number; children: ReactNode; testID?: string; ref?: React.Ref; render?: useRender.RenderProp; } /** * One side of the ledger — a run of rows, closed by its sum. * * **The sum FOLLOWS its rows.** It sat in the header for a version, which is how a * caption behaves, not how a subtotal does: every invoice, statement and receipt puts * a subtotal after the lines it sums, and above them the reader either trusts a figure * before seeing its parts or reads down and jumps back up to find it. * * It also sat at the LABEL's weight — xs muted — so the number summarising three rows * came out smaller and greyer than the rows themselves. A subtotal is of the same * magnitude class as its lines, so it takes their SIZE and one step of weight above * them: `sm/medium` against rows at `sm/regular`, under a total at `md/semibold`. Three * rungs, each one step, and the eye can rank them without reading a word. * * The LABEL travels with the sum rather than being repeated: a group that closes with * "Invoiced 1.430.000 ₫" does not also need to announce "INVOICED" before its rows — * that is the same word twice for one group. A group with no `total` therefore keeps the * caption ABOVE its rows, because there is nothing for its label to travel with — and a * group can legitimately have no sum: naming a category is one job, summing it is * another, and a one-row group's sum only restates the row. * * **Do not mix the two inside one `Ledger`.** The label sits above an unsummed group and * below a summed one, so a statement holding both moves its own group names around and * reads as though the placement were an accident. Pick one shape per statement: if any * group earns a sum, give every group one (grouping a single row is then the thing to * avoid — let that row stand bare, or fold it into a neighbouring group). * * Naming a side at the BOTTOM means the reader meets its rows before its name, so the * rows must say which side they are on by themselves — which they do when the sides * carry opposite SIGNS (charges positive, receipts "−" and `tone="success"`). Two * same-signed groups are not two sides of one statement; they are two statements, and * they want two `Ledger`s under their own headings. */ export declare function LedgerGroup({ label, total, children, testID, render, ref, ...props }: LedgerGroupProps): React.ReactElement>; export interface LedgerBasisProps extends StyleProps { /** What the figure IS ("Customs value (CIF)", "Gross revenue", "Principal"). */ label: string; value: number; /** How the figure was arrived at — the FX rate it was converted at, the period * it covers. Not a second label: it qualifies the number, it does not name it. */ meta?: string; testID?: string; ref?: React.Ref; render?: useRender.RenderProp; } /** * The figure the rows below are computed FROM — a statement's premise, not one of * its lines. * * Some statements are not `charges → total`. Duty is `customs value → levies → * payable`; commission is `gross → rates → owed`; interest is `principal → accrual * → balance`. In all of them one number is the BASE and the rest are derived from * it, and a ledger that can only say "row" has to lie about which is which. * * Rendering the base as a `LedgerRow` claims it is a peer of the levies — that you * could add it to them. Putting it in a one-row `LedgerGroup` is worse: a group's * sum earns its place only when it sums more than one visible row, so a single-row * group states the same fact twice, at two weights, and the reader has to work out * that the repetition means nothing. * * So it takes the THIRD treatment on the ledger's one money column — between a * plain row and the total — and its `Divider` sits BELOW it, because a premise * separates itself from what it feeds. (`LedgerTotal`'s rule sits above, closing * what came before.) Order is the caller's: a basis first reads as "from this", * which is the only order that makes the levies beneath it legible. */ export declare function LedgerBasis({ label, value, meta, testID, render, ref, ...props }: LedgerBasisProps): React.ReactElement>; export interface LedgerRowProps extends StyleProps { /** The line's name — what was charged / received. */ label: string; /** * Inline context after the label — a date, a method, a basis, a period. A neutral * QUALIFIER on the figure, rendered as a caption (xs, muted) because it is * subordinate to the thing it qualifies. * * Never a PROBLEM or a state ("awaiting approval", "missing method"). It reads * inconsistent the moment one row's meta is a fact and another's is a complaint — * two unlike things in one treatment — and a caption is the wrong weight for * something that wants acting on. A problem belongs on the row that can FIX it (a * `DetailRow`'s `warning` beside its editor), and in a statement the arithmetic has * usually said it already: an unpaid line is what the outstanding total IS. */ meta?: string; /** The amount. Negative renders "− " (a receipt). */ value: number; /** Valence of the amount (a receipt reads success). */ tone?: "default" | "success" | "danger"; /** The line's PARTICULARS — set it and the whole row becomes a pressable * door that floats this node in an anchored popover. Put any links (the * invoice, the tariff) INSIDE the peek: a row is never a button holding * another button, so `reference` is ignored while `peek` is set. */ peek?: ReactNode; /** Peek PANEL width — the panel's own box, inset included. Default 324. */ peekWidth?: number; /** A trailing reference link (an issued invoice, a receipt no.) for a row * WITHOUT `peek`. */ reference?: { label: string; onPress: () => void; }; /** Accessible name for a peekable row. Defaults to "