/** Data Display component prop types — @see docs/COMPONENTS.md#data-display */ import type * as React from "react"; /** @see CodeBlock — a block of preformatted text (request bodies, logs, snippets). */ export type CodeBlockProp = { /** * The text. Pass a string, or a highlighter's spans. * * Tag each span `data-code-token="keyword" | "string" | "comment" | …` — the twelve names Shiki's * `createCssVariablesTheme` emits — and the package colours it from the `--code-block-token-*` * knobs. Do NOT put `style={{ color }}` or a palette `className` on the spans: both are visual * overrides, and this used to be the only spelling available, which made the documented path * unbuildable for a rule-following consumer (gh#784). */ children?: ChildrenProp; /** Soft-wrap long lines (default true). `false` scrolls horizontally instead. */ wrap?: boolean; /** Scroll inside the block past this height. Default `none` (grows with the content). */ maxHeight?: "sm" | "md" | "lg" | "none" | { value: string; }; /** Type size. Default `sm`. */ size?: Extract; /** Lands on `data-language`; no highlighter is bundled — see `children` for colouring its output. */ language?: string; className?: ClassNameProp; }; /** * @see Prose — typography for rendered content (Markdown, CMS bodies). Styles descendant semantic * HTML from the tokens; it has no opinion about where the HTML comes from. */ export type ProseProp = { /** Body size. `md` is the page body size; `sm` is the compact step. Default `md`. */ size?: Extract; /** `fit` scales images to the column (default); `original` shows them at their authored size. */ imageSize?: "fit" | "original"; className?: ClassNameProp; children?: ChildrenProp; }; import type { ActionProp, ClassNameProp, DescriptionProp, IconProp, TitleProp, ColumnDefProp, GetRowIdProp, GetRowLabelProp, OnRowClickProp, OnSelectChangeProp, OnSortChangeProp, OnTableDensityChangeProp, SelectedIdsProp, SortStateProp, TableDensityProp, TablePresetProp, BreakpointProp, DensityProp, ChildrenProp, PendingProp, ToneProp, AvatarShapeProp, HeadingLevelProp, HandlerProp, SizeProp, LabelProp, IdProp, DescriptionsLayoutProp, DescriptionsColumnProp, DescriptionsSpanProp, DescriptionsItemsProp, GapProp, SortDirectionProp, OnColumnFilterChangeProp, OnRowProp, TableExpandableProp, TableRowSelectionProp, TableScrollProp, TableStickyProp, TableSummaryProp, DisabledProp, OnClickProp, ValueProp, DefaultValueProp, OnValueChangeProp } from "../vocabulary/index.js"; import type { TreeFieldNamesProp, TreeOptionProp } from "./data-entry.prop.js"; /** * One key in a `Legend`: a tone, and the words that tone stands for. * * `label` is required and there is no way to omit it. That is the point of a key — colour alone * never carries meaning (WCAG 1.4.1), and a legend whose entries could be wordless would be a * component that lets a caller build the exact failure it exists to prevent. */ export type LegendItemProp = { /** The tone this key explains — the SAME tone the marks it stands for are drawn in. */ tone: ToneProp; label: LabelProp; }; /** @see Legend — the key for a colour-coded surface: a breakdown bar, a chart, a status column. */ export type LegendProp = Omit, "children"> & { items: LegendItemProp[]; className?: ClassNameProp; }; /** * @see Swatch — a READ-ONLY sample of ONE colour a person chose. * * ## Why it is not a Legend, a ColorPicker or a Badge * * `Legend` is a KEY: a closed set of semantic TONES, each with required words beside it, because * there the colour stands FOR something. Here the colour IS the content — a brand's * `primary_color`, a calendar category, a label a user tinted — so there is no tone it maps to and * no second thing for a word to name. `ColorPicker` is the INPUT for the same value, and rendering * a disabled input to display one reads as a control that broke. `Badge` is a chip: tinted fill, * border, clickable affordance — not a sample of the exact colour. * * Its mark is the same square Legend draws, one type step larger, because it stands beside a name * rather than inside an 11px key. */ export type SwatchProp = Omit, "children" | "color"> & { /** * The colour to show, as a CSS colour VALUE — `#7C3AED`, `rgb(…)`, `oklch(…)`. It is DATA the * same way `Badge`'s `color` is: a value a person picked in a settings screen, so it arrives as * a prop and is never written into a stylesheet. Passing a semantic token's own colour here is * the one thing to avoid — a tone that MEANS something belongs on a component that names the * meaning (`Badge tone`, `Legend`), not on a sample. */ color: string; /** * The accessible NAME of the sample, and the reason this component can exist without a visible * label. Say what the colour is FOR and what it is: `aria-label={`${t.primaryColor}: ${hex}`}`. * * With it, the swatch is a `role="img"` that announces that sentence. Without it the swatch is * `aria-hidden` — correct, and the only correct option, when a visible line beside it already * states the colour. Either way colour is never the sole carrier of the meaning (WCAG 1.4.1); * what is NOT offered is a third path where it is. */ "aria-label"?: string; }; /** * Whether a `FeatureList` line is in, out, or in with a limit. * * Three members and no fourth: the axis is INCLUSION, and a list that also carried "coming soon", * "beta" or "deprecated" would be encoding a roadmap on the same glyph column as a fact about * today. Those are a `Badge` beside the label, which is content the screen already owns. */ export type FeatureStateProp = "included" | "excluded" | "limited"; /** * One line of a `FeatureList`: what state it is in, what it is called, and — optionally — a * sentence about it that WRAPS. * * There is deliberately no field for a quantity ("10,000 req/mo"). Composing it into `label` as * `<>API calls 10,000 req/mo` is already legal and already * audit-clean, so a prop for it would fail question 1 of docs/WHAT-BELONGS-HERE.md — the consumer * has a move. What the consumer did NOT have a move for is the glyph column and its alignment, * which is what this component owns. */ export type FeatureItemProp = { /** In, out, or in with a limit. Drives the glyph, its mark colour and the `sr-only` prefix. */ state: FeatureStateProp; /** What the line is about. Wraps. */ label: LabelProp; /** An optional muted sentence under the label. Wraps; long unbroken tokens break. */ description?: DescriptionProp; }; /** * @see FeatureList — a list of statements, each with a leading state glyph: what a plan includes, * what a tier supports, which requirements a submission met. */ export type FeatureListProp = Omit, "children"> & { items: FeatureItemProp[]; className?: ClassNameProp; }; /** * Fixed BLOCK size of a `Thumbnail`; the inline size stays intrinsic. * * A subset of the shared `SizeProp` ladder — `xs` is off the bottom because a 48px frame with a * 1px hairline is a favicon, not a thumbnail, and nothing in the reported cases wanted one. */ export type ThumbnailSizeProp = Extract; /** * @see Thumbnail — a framed image at a FIXED HEIGHT and its own intrinsic width, for a wrapping * row of pictures whose aspect ratios differ. */ export type ThumbnailProp = Omit, "alt"> & { /** Image URL. */ src: string; /** * Required, with no way to omit it. Pass `""` for a picture that carries no information the * page does not already say — the empty string is a DECISION the author has to make, where a * missing attribute is an omission nobody notices (WCAG 1.1.1). */ alt: string; /** Frame height. Default `md`. The width follows the picture's own ratio. */ size?: ThumbnailSizeProp; className?: ClassNameProp; }; /** @see EmptyState */ /** * Semantic intent of the EmptyState icon medallion — a subset of the shared `ToneProp` vocabulary * (no `default`/`neutral`; `destructive` is the DS name for a "danger" state). Drives the * `--empty-state-icon-foreground` / `--empty-state-icon-tint` role tokens. */ export type EmptyStateToneProp = Extract; export type EmptyStateProp = { icon?: IconProp; title: TitleProp; description?: DescriptionProp; action?: ActionProp; /** Visual weight appropriate to the empty condition. Default `page`. */ variant?: "page" | "section" | "compact"; /** Medallion colour intent. Default `muted` (the neutral placeholder look). */ tone?: EmptyStateToneProp; /** Semantic heading level (`h1`–`h4`) for the title. Default `3`. */ titleLevel?: HeadingLevelProp; /** * Render the title as a non-heading element (`p` / `div`) instead of a heading. Use for a * `compact`/`section` empty state placed inside a section that already owns its heading, so the * zero-state message is not announced as a heading and cannot skip an outline level. */ titleAs?: "h1" | "h2" | "h3" | "h4" | "p" | "div"; className?: ClassNameProp; }; /** * @see Descriptions — composed with `Descriptions.Item` CHILDREN, not an `items` array. * This type had drifted from the component (it described a long-gone items-based API and was * missing `layout`/`labelAlign` entirely, which the generated manifest already listed). */ export type DescriptionsProp = { /** `Descriptions.Item` children — one label/value pair each. */ children?: React.ReactNode; /** * Column count. `1 | 2 | 3` keeps this library's own mobile-first ladder; any other number, or * antd's responsive `{ sm, md, lg, xl }` object, drives the token-published grid instead. */ columns?: DescriptionsColumnProp; /** Label placement within each item. Default `vertical` (label over value). */ layout?: DescriptionsLayoutProp; /** Label text alignment inside the label column. Applies only to `layout="horizontal"`. */ labelAlign?: "start" | "end"; /** Draw the grid as a bordered table with shaded label cells (antd `bordered`). */ bordered?: boolean; /** Declarative items (antd `items`) — the alternative to composing `Descriptions.Item`. */ items?: DescriptionsItemsProp; className?: ClassNameProp; }; export type DescriptionsItemProp = { label: React.ReactNode; value: React.ReactNode; mono?: boolean; /** Columns this item occupies — number | `"filled"` | responsive object (antd `span`). */ span?: DescriptionsSpanProp; }; /** * @see Avatar * * Identity mark. `shape` is the ONLY appearance knob: the default `circle` is the person avatar * (unchanged — an existing `` renders identically), `square` is the entity-header * organization / service mark (compact rounded square on the brand surface). Every value it * paints — radius, box size, fill, glyph colour — comes from the `--avatar-square-*` component * tokens (cardinal rule #45), so a service retunes the entity mark once in its theme instead of * overriding `className` per call site. */ export type AvatarProp = React.ComponentPropsWithoutRef<"span"> & { shape?: AvatarShapeProp; /** * Box size on the shared control ladder — `md` (default) is `--control-height`, and `xs`/`sm`/ * `lg` are `--control-height-xs/-sm/-lg`, the SAME tier Button and Input read. State it when the * mark has to sit in a row the row's height already decided: inside an `icon-sm` trigger, in a * 24px dense table row, beside a `size="sm"` Button. Before gh#716 the box was welded to * `--control-height`, so a 32px mark inside a 28px trigger overflowed it and the only legal move * left was raising the whole row. * * The initials' type step and a glyph's box move with the box — one step of the type scale and * one step of the `--icon-size-*` scale per step — so a small mark is small, not clipped. * `shape="square"` rides the identical ladder. Beyond the ladder (a 96px profile mark) is a * `className` size utility, exactly as before; the ladder is for the control row. */ size?: SizeProp; appearance?: AvatarAppearanceProp; /** * Presence — WHO is reachable right now, drawn as an indicator at the block-end/inline-end * corner of the mark with a localized `sr-only` label folded into the avatar's accessible text. * Never colour alone (WCAG 1.4.1): each value also has its own silhouette (filled · half-filled * · barred · hollow). */ presence?: AvatarPresenceProp; /** * Override the localized presence text (`t("dataDisplay.avatar.presence.online")` …) when the * product has a more precise phrasing ("In a meeting until 15:00"). Visually hidden either way — * a presence dot never carries visible text; that is `Badge status`. */ presenceLabel?: LabelProp; className?: ClassNameProp; children?: ChildrenProp; }; /** * Avatar presence status — a person's realtime reachability. * * A DELIBERATELY separate vocabulary from the lifecycle `BadgeStatusProp`: presence is volatile, * per-person and pushed over a socket, while a lifecycle status is a record's state and renders as * a labelled chip. Each value is encoded twice over — a semantic role colour AND a shape — so the * four are told apart in greyscale, by a deuteranope and under forced colors: * * - `"online"` — filled disc (`--success`). * - `"away"` — half-filled disc (`--warning`). * - `"busy"` — filled disc cut by a horizontal bar, the do-not-disturb mark (`--destructive`). * - `"offline"` — hollow ring (`--muted-foreground`). * * Retune every constant with `--avatar-presence-*`. * * @see Avatar */ export type AvatarPresenceProp = "online" | "away" | "busy" | "offline"; /** * Avatar fill treatment. * * - `"default"` — the identity fill: `--muted` for a person, the solid brand mark for * `shape="square"`. * - `"tinted"` — the **capability medallion**: a soft role wash behind a role-coloured glyph. * This is the plate a capability/feature icon sits on (`shape="square" appearance="tinted"` for * the canonical rounded square). It exists because the medallion is a composition — `Avatar` + * a Lucide glyph, per docs/COMPOSITION-VS-COMPONENT.md — but its *tint* was not reachable from * a token, so consumers were re-deriving `hsl(var(--primary) / 0.1)` in page CSS or giving up * and rendering a bare glyph. Retune with `--avatar-tinted-*`. * * @see Avatar */ export type AvatarAppearanceProp = "default" | "tinted"; /** @see Badge */ export type BadgeProp = { /** * Render element — `div` (default) or `span` when the chip sits in a phrasing context where a * `
` is invalid HTML (inside a `