import { type ComponentType, type ReactNode } from "react"; import { type BreakpointKey, type LayoutStyle } from "../../style/index.js"; import { type CheckboxProps } from "../../atoms/checkbox/checkbox.shared.js"; import { type PaginationProps } from "../../atoms/pagination/pagination.shared.js"; import { type SkeletonProps } from "../../atoms/skeleton/skeleton.shared.js"; import { type Density, type DataTableSkin } from "./data-table.styles.js"; export type { Density }; /** * A column descriptor. Plain strings stay supported (a string is shorthand for * `{ label }`); the object form unlocks per-column alignment, fixed widths, and * sorting. */ export interface DataTableColumn { /** Column header label. */ label: string; /** Stable identity used by `sort.column`; defaults to the label. */ key?: string; /** Right-align the header and cells (amounts, counts, measurements). */ numeric?: boolean; /** Center the header and cells (short status/flag columns). */ centered?: boolean; /** Fixed width in px instead of the equal flex share. Wins over `fit`, `grow` and `minWidth`. */ width?: number; /** * Size the column to its widest cell, its heading included, instead of the equal flex * share: a grid's `max-content` track. The table measures the column's cells and holds * every one at the widest, so a column of buttons lines up at the width of its longest * label. Wins over `grow` and `minWidth`; a table holding a `fit` column pans once the * measured columns add up to more than it has. */ fit?: boolean; /** * The column's relative weight in the width the fixed columns leave: a column with * `grow: 2` takes twice the share of one with `grow: 1` (the default every column * has), the way a grid's `2fr` does beside `1fr`. Mixes freely with fixed `width`s. */ grow?: number; /** * The narrowest the column's box (its cell padding included) may get, in px, as a * grid's `minmax(min, fr)` floor. Once the declared floors add up to more than the * table's width, the table pans horizontally at any width instead of crushing the * columns (a table without a declared floor pans only below the `sm` width). */ minWidth?: number; /** * Opt this column into header-press sorting. Unnecessary when the table-level * `sortable` is set (there it opts back OUT via `sortable: false`). */ sortable?: boolean; /** * Derive the comparable value for sorting when this column's cells are custom * ReactNodes (a Badge, a link). String/number cells sort out of the box; * without this, custom-node cells sort last. Keep this function pure: its * results are cached until rows or columns change. If it closes over changing * external data, replace the function, its descriptor, and the columns array. */ sortValue?: (cell: ReactNode, row: ReactNode[], rowIndex: number) => string | number | null | undefined; } /** * A titled group of rows (`groups`): a band spanning every column above the group's * rows, carrying its label, an optional adornment and an optional count. */ export interface DataTableGroup { /** The band's label. A string takes the band's label type; any other node renders as given. */ label: ReactNode; /** A node after the label, such as a `pick one` marking the group's rule. */ adornment?: ReactNode; /** A count after the adornment, in the muted monospace meta type. */ count?: string | number; /** The group's rows, in the shape `rows` takes. */ rows: ReactNode[][]; } /** The active sort: which column (by `key`, or label) and which direction. */ export interface DataTableSort { /** The sorted column's `key` (the label when no key was given). */ column: string; /** Descending when true; ascending otherwise. */ descending?: boolean; } export interface DataTableProps { /** * Columns: a header label per column, or a `DataTableColumn` descriptor for * per-column alignment (`numeric`/`centered`), a fixed `width`, and sorting * (`sortable`, `sortValue`). Strings and descriptors mix freely. Treat the * array and descriptors as immutable: replace both when a column changes. */ columns: Array; /** * Row data: an array of rows, each an array of cells (one per column). A cell is * a string (rendered in the default cell type) or any ReactNode for a custom * cell, such as a link, a `Badge`, or a monospace name (rendered directly). * Treat this data as immutable: replace the outer array and each changed row * when data changes, so cached sorting and pagination update correctly. */ rows?: ReactNode[][]; /** * Group the rows under titled bands (the props table's "Intent", "Size" and "State" * groups): each group draws a band spanning every column, its label, an optional * adornment and an optional count on the sunken fill, then its own rows. Given * `groups`, the table's rows are the groups' rows in order and `rows` is ignored; * every row index a callback reports (`onRowPress`, `onRowEdit`, `rowKey` and the * rest) counts through them in that order. Sorting reorders rows within their group * and never moves a group; paging pages the rows, and each page draws the band of * every group it shows. A group with no rows draws no band. */ groups?: DataTableGroup[]; /** Tint every other data row for easier horizontal scanning. */ striped?: boolean; /** Draw the table's frame on the firmer field boundary rather than the hairline. */ bordered?: boolean; /** * The table sits flush inside a frame its parent draws (a `flush` Card, a * bordered panel that clips to its corners), so it draws no frame of its own. * Without it a standalone table frames itself * * (on the web and Android, a * hairline at the table corner over the card fill), * * which is the standalone * look. */ attached?: boolean; /** * Responsive: when the table's own CONTAINER is at or below `stackBreakpoint` * (default `sm` = 640), each row lays its cells out top to bottom at the full * width instead of side by side, so long text reads at the width of the * table rather than a column's share of it. The first cell leads the row as * its title; every later cell carries its column label above its value. The * header row is drawn only while it holds a control (a sortable column, or * the box that selects every row), as a band of its labels that wraps; the * selection box and the row actions stay at the row's leading and trailing * edges. A stacked table never pans, * * and on iOS it stacks instead of * collapsing to its first column. * * Container-measured with a viewport seed for * the first frame, like Row `stacks`; crossing the breakpoint changes the * layout only. */ stacks?: boolean; /** The breakpoint at and below which `stacks` stacks the rows (default * `"sm"`). Only meaningful with `stacks` (DEV warns without it). */ stackBreakpoint?: BreakpointKey; /** Tighter vertical padding on header and data cells. */ compact?: boolean; /** Looser vertical padding on header and data cells. */ comfortable?: boolean; /** * The reference sheet (a component page's props table): the column headings as the * page's small uppercase mono label on a header row with no fill of its own, 12 px above * and below whatever the density; rows 10 px above and below with a rule above each; * the columns 16 px apart and 16 px in from the frame's sides; and the frame at the * panel corner on the `border` hairline over the card fill, so `bordered` only firms the * hairline and `attached` still drops the frame. * * On iOS the table keeps its own look and this changes nothing. * * * The table keeps its own look and this changes nothing. * */ reference?: boolean; /** * The bare hairline table: no frame and no fill, a `field-border` rule under the * headings (the reference sheet's mono uppercase label) and a `border` rule under every * row, the first column flush with the table's start, each cell keeping 12 px clear at * its end inside its column's width, and 12 px above and below whatever the density. * `reference` wins over it. * * On iOS the table keeps its own look and this changes nothing. * * * The table keeps its own look and this changes nothing. * */ bare?: boolean; /** * The specimen matrix (a section page's states grid): no frame, no fill and no rules, the * headings as the page's small uppercase mono label in the third ink, the cells unpadded, * the rows 12 px apart and the columns 20 px apart. Pair it with `fit` columns for the * hand-off's content-sized tracks. `reference` and `bare` win over it. * * On iOS the table keeps its own look and this changes nothing. * * * The table keeps its own look and this changes nothing. * */ matrix?: boolean; /** * Align every cell to the top of its row rather than its middle, so a row whose * description wraps keeps its name, type and default beside the description's first * line. The selection box and the row actions center on that first line, as they do in * a stacked row. */ alignTop?: boolean; /** * A row drawn inside the table's frame under the last row (and under the pagination * bar when `paginated`): 44 px tall with its content centered, for a "Show all" * control or a note. A hairline separates it from what sits above it: the one the last * row draws already, or its own where nothing above it draws one. */ footer?: ReactNode; /** * Make every column sortable: pressing a header cycles ascending, descending, * off. A column descriptor opts back out with `sortable: false`. Sorting is * self-managed out of the box; control it via `sort`/`onSortChange`. */ sortable?: boolean; /** Controlled sort state (`null` = unsorted). Omit for uncontrolled use. */ sort?: DataTableSort | null; /** Initial sort for uncontrolled use. */ defaultSort?: DataTableSort | null; /** Fired with the next sort (or `null` when cleared) on header press. */ onSortChange?: (sort: DataTableSort | null) => void; /** * Row selection: a leading checkbox column with a select-all header checkbox * (indeterminate on a partial selection). Selection is keyed by `rowKey` (the * row's original index when omitted) and self-managed out of the box; control * it via `selectedKeys`/`onSelectionChange`. When no `onRowPress` is set, * pressing anywhere on a row toggles it. */ selectable?: boolean; /** Controlled selected row keys. Omit for uncontrolled use. */ selectedKeys?: Array; /** Initial selected row keys for uncontrolled use. */ defaultSelectedKeys?: Array; /** Fired with the next selected keys when a row or the select-all is toggled. */ onSelectionChange?: (keys: Array) => void; /** * Page the rows through a built-in footer (the kit Pagination): a * "Showing X-Y of N" range with Prev/Next, plus the selection count when * `selectable`. Sorting applies before paging. Self-managed out of the box; * control the page via `page`/`onPageChange`. */ paginated?: boolean; /** Rows per page (CONTROLLED; default 10, or the first of `pageSizes`). */ pageSize?: number; /** Initial rows per page for uncontrolled use. */ defaultPageSize?: number; /** * Selectable rows-per-page values. Supplying them upgrades the footer to the * Pagination `withSize` variant (a "Rows per page" selector). */ pageSizes?: number[]; /** Fired with the next rows-per-page value when the footer selector changes it. */ onPageSizeChange?: (size: number) => void; /** Current page, 1-based (CONTROLLED). Omit for uncontrolled use. */ page?: number; /** Initial page for uncontrolled use. */ defaultPage?: number; /** Fired with the next 1-based page when the footer pagination navigates. */ onPageChange?: (page: number) => void; /** * Loading state: the body renders pulsing skeleton placeholder rows (one per * would-be row on the page) instead of data. */ loading?: boolean; /** * What to render, centered under the header, when `rows` is empty (and not * `loading`). A string gets the muted caption type; any ReactNode renders as * given (an `EmptyState`, a retry Button). Omitted = just the header row, as * before. */ emptyMessage?: ReactNode; /** * When set, each data row is pressable, reporting the row data and its index * in `rows`. A press anywhere on the row acts; the keyboard and screen-reader * path is a button inside the row's FIRST column, named from the row's plain * text cells (or, when it has none, by that cell's own content). The row * itself stays a `row`, so keep your own controls out of the first column * here: a control there would nest inside the activator. */ onRowPress?: (row: ReactNode[], index: number) => void; /** * Row editing: passing this adds a trailing actions column with a pencil * button per row. Pressing the pencil opens the row's edit mode (its string * cells become fields with a trailing Save/Cancel pair) and fires this with * the row's original index in `rows`. Save reports the edited cells through * `onRowCommit`; Cancel (or Escape in a field) closes without committing. */ onRowEdit?: (rowIndex: number) => void; /** * Row deletion: passing this adds a delete (bin) button to the trailing * actions column. Delete is second-press confirm: the first press ARMS it * (the bin turns destructive and its accessible name says confirm), a second * press within the confirm window fires this with the row's original index, * and pressing anywhere else in the table (or the window lapsing) disarms. */ onRowDelete?: (rowIndex: number) => void; /** * Let string cells be edited in place: pressing one swaps it to a field. * Enter or blur commits through `onCellCommit`; Escape restores the cell. * Custom ReactNode cells (badges, links) are not editable. */ inlineEdit?: boolean; /** * Fired when an `inlineEdit` cell commits (Enter or blur) with a changed * value: the row's original index in `rows`, the column index, and the next * text. Data stays yours: re-render with updated `rows` to keep the edit. */ onCellCommit?: (rowIndex: number, colIndex: number, next: string) => void; /** * Fired when a pencil-opened row edit is saved: the row's original index in * `rows` and the full cells array with the edited strings in place (custom * ReactNode cells pass through unchanged). */ onRowCommit?: (rowIndex: number, cells: ReactNode[]) => void; /** * Render the data rows through a windowed `FlatList` instead of mounting every * row up front, for large tables. The header row stays fixed above it. Give the * table a bounded height (via `style`, e.g. `{ maxHeight: 400 }`) so the body can * scroll; without one it warns and renders eagerly. Default mounts all rows. */ virtualized?: boolean; /** * Stable key for a row, derived from the row data and its index in `rows`. * Selection is keyed by it, and it keeps React row identity stable when rows * reorder (sorting, live data) and a cell is a stateful custom ReactNode. When * omitted, rows key off their original array index (safe for string/number * cells and stateless custom cells; selection then tracks row POSITIONS, so * supply a real key when the data itself can be reordered, inserted, or * deleted). Keep this function pure; replace its identity when external data * changes how keys are derived, so the cached selection summary updates. */ rowKey?: (row: ReactNode[], index: number) => string | number; /** E2E hook forwarded to the root element. */ testID?: string; /** Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds. */ style?: LayoutStyle; } export declare function densityOf(p: DataTableProps): Density; export declare function lookOf(p: Pick): "reference" | "bare" | "matrix" | "table"; export declare function rowAlignOf(p: Pick): "top" | "center"; export declare function columnAlignOf(col: Pick): "end" | "center" | "start"; export interface DataTableParts { Checkbox: ComponentType; Pagination: ComponentType; Skeleton: ComponentType; } /** Build a DataTable component from a platform skin plus its platform parts. */ export declare function createDataTable(skin: DataTableSkin, parts: DataTableParts): (props: DataTableProps) => import("react").JSX.Element; //# sourceMappingURL=data-table.shared.d.ts.map