import "./summary.css"; import type * as React from "react"; import { useRender } from "@base-ui/react/use-render"; import { type MetricFormat, type MetricTone } from "./metric"; import { type TotalsLineItem } from "./totals_line"; import { type StyleProps } from "./style_props"; /** * One bucket of the set being summarized — a slice of the whole, with the colour * it wears wherever it appears. * * The buckets PARTITION the set: their values sum to the total, which is why the * total is derived rather than passed. A count that belongs to the same rows but * does not partition them — a condition rather than a position, "overdue" beside * "draft / sent / paid" — is not a bucket and must not be one, or the bar starts * claiming a share for something that is already inside another segment. Pass * those as `facts`. */ export interface SummaryBucket { key: string; /** Reads AFTER the value, like every other label in this family. */ label: string; value: number; /** The segment's colour, and the swatch's. Use the same value this bucket * wears in the rest of the product — a bar that disagrees with the badge * beside it is worse than no bar. */ color: string; /** What this bucket means — the ⓘ beside its count. */ info?: string; /** * Valence on the bucket's COUNT, for a bucket that represents work someone has * to do. Reserve it: a screen where every bucket is toned has said nothing, and * the bucket holding the largest number is usually the one that needs it least * (work that has left the building is not a queue). * * It colours the figure only. The segment keeps the bucket's own `color`, so * the bar goes on reading as a distribution rather than as a heat map. */ tone?: MetricTone; } /** The headline: the set's SIZE at display scale, and what it counts. */ export interface SummaryTotal { /** What the figure counts — "records", "khách hàng". Reads after it. */ label: string; /** * A total with its OWN authority, counted by the same source that counted the * buckets. Omit it and the buckets are summed, which is the point: a page that * restates its own total eventually restates it wrongly — a bucket is added, * the constant does not move, and the headline quietly disagrees with the bar * directly beneath it. * * A server-paginated register is the case that earns it: the buckets are * per-stage `COUNT`s over the filtered view and the size is a fourth count * over that same view, so summing the three client-side would replace an * authoritative number with a derived one that can differ. Pass it when * something ELSE counted it, never to write a literal. */ value?: number; /** For a total whose unit is not a plain count. Default: the reader's locale * grouping — a set of 12,345 must not read "12345" in the one place on the * screen sized to be read first. */ formatValue?: (n: number) => string; } /** * A second headline figure that is NOT part of the distribution — a sum of money * over the same rows, an average, a rate. * * Deliberately not a bucket: it does not partition the set, so the bar must not * carry it. It sits on the header row because a reader opening a register asks * two questions ("how much of this is there" and "what is it worth"), and the * answers belong side by side. */ export interface SummaryMetric { value: number | string | null | undefined; label: string; format?: MetricFormat; currency?: string; compact?: boolean; emptyLabel?: string; tone?: MetricTone; } export interface SummaryProps extends StyleProps { buckets: readonly SummaryBucket[]; total: SummaryTotal; /** Figures beside the headline, in order. */ metrics?: readonly SummaryMetric[]; /** * The bar's thickness. `false` leaves the shape undrawn, for a band whose * buckets are a key rather than a distribution. */ distribution?: number | false; /** * Aggregates appended to the legend AFTER the buckets, with no swatch — the * visual difference is the point: a reader can see that the unswatched figure * is not a slice of the bar. */ facts?: readonly TotalsLineItem[]; testID?: string; ref?: React.Ref; render?: useRender.RenderProp; } /** * The register's summary band — a headline figure, the set's DISTRIBUTION, and * the buckets named. * * **Why one entry and not a compound.** The band encodes a correspondence that is * easy to break and impossible to see broken: the bar, the legend and the * headline all describe ONE set. The buckets are declared once and everything * derives from them — the total is their sum, the segments are their values, the * swatches are their colours, the legend is their labels. Nothing is restated, so * nothing can disagree. That correspondence is the reason this is a primitive at * all; this kit does not extract a composition for saving lines of layout. * * Reach for it when the set has a SHAPE worth showing. A summary that is only a * few aggregates stays `TotalsLine`, which is this band's legend row on its own; * a boxed dashboard stat band is `MetricStrip`; a drill-down facet browser over a * large population is `Breakdown`. * * */ export declare function Summary({ buckets, total, metrics, distribution, facts, testID, render, ref, ...props }: SummaryProps): React.ReactElement>;