import { ReactNode } from 'react'; /** Direction a column is currently sorted. */ export type SortDirection = "asc" | "desc"; export interface DataTableColumn { /** Unique identifier for the column. Used for visibility + width persistence. */ id: string; /** Header label. */ header: ReactNode; /** * Cell renderer. Receives the row and returns a React node. Pure * functions are encouraged so memoization stays effective. */ render: (row: T, index: number) => ReactNode; /** Optional minimum column width in pixels. */ minWidth?: number; /** * Optional maximum column width in pixels. Values above this limit are * clamped for pointer and keyboard resizing. Resizable columns default to * 1200 pixels so every separator exposes a finite ARIA maximum. A * `noResize` column keeps its existing unbounded width unless it explicitly * supplies this property. */ maxWidth?: number; /** Optional initial width in pixels (only honored on the first paint). */ initialWidth?: number; /** When `true`, the column cannot be resized. Defaults to `false`. */ noResize?: boolean; /** When `true`, the column cannot be hidden by the user. Defaults to `false`. */ alwaysVisible?: boolean; /** Extra `class` for the column's `` and `` cells. */ className?: string; /** * When provided, the value is exposed via the `align` style on the * column's cells. Useful for right-aligned numeric columns. */ align?: "left" | "right" | "center"; /** * When `true`, the column header renders a sort affordance and clicking * (or pressing Enter / Space) cycles through ascending → descending → * unsorted states. Defaults to `false`. */ sortable?: boolean; /** * Extracts a primitive comparable value from a row for sorting purposes. * Used when the default ascending/descending behavior is sufficient. * Mutually exclusive with `sortComparator` — if both are provided, * `sortComparator` takes precedence. * * @example * ```tsx * sortValueAccessor: (row) => row.name.toLowerCase() * ``` */ sortValueAccessor?: (row: T) => string | number | boolean | null | undefined; /** * Custom comparator used for sorting. Receives two rows and the active * sort direction. Return a negative number if `a` should come first, a * positive number if `b` should come first, or `0` if they are equal. * The table applies a stable fallback on `0` to preserve original order. * * @example * ```tsx * sortComparator: (a, b, dir) => * dir === "asc" * ? a.createdAt - b.createdAt * : b.createdAt - a.createdAt * ``` */ sortComparator?: (a: T, b: T, direction: SortDirection) => number; /** * The sort direction applied when this column is first activated. * Defaults to `"asc"`. */ defaultSortDirection?: SortDirection; } export interface DataTablePersistedState { /** column id → user-overridden width in pixels. */ widths: Record; /** column id → visibility flag. Missing keys count as visible. */ visibility: Record; } export interface DataTableProps { /** Column definitions, in display order. */ columns: DataTableColumn[]; /** Row data. */ rows: T[]; /** * Stable identifier accessor — used as the React key for each row. * Must be deterministic for the lifetime of the row. */ getRowKey: (row: T, index: number) => string; /** Render this node when `rows` is empty. */ emptyState?: ReactNode; /** Render this node when `loading` is `true`. */ loadingState?: ReactNode; /** When `true`, the loading slot replaces the table body. */ loading?: boolean; /** * Column widths and visibility, controlled by the caller. * * This component used to take a `persistKey` and write to `localStorage` * itself. Storage is a policy decision that belongs to the consumer: where * it goes, under which key, whether it is per user or per workspace, and * whether it exists at all in a host that has no `localStorage`. A * rendering component that answers those questions on its own cannot be * reused by a consumer that answers them differently. */ columnState?: DataTablePersistedState; /** * Called whenever the user resizes a column or toggles its visibility. * Pair it with `columnState` to persist wherever the consumer keeps * preferences; omit both to get a table that forgets on unmount. */ onColumnStateChange?: (state: DataTablePersistedState) => void; /** Extra class for the table's wrapping element. */ className?: string; /** ARIA label for the table. Defaults to "Data table". */ ariaLabel?: string; /** * Produces the accessible name for a resizable column's separator. The * default is `Resize column`; pass a product's translated label * when column ids are not suitable for people to hear. */ resizeHandleLabel?: (column: DataTableColumn) => string; /** * Produces the human-readable current width announced by a resize * separator. The default is ` pixels`; pass a translated formatter * when the host localizes measurements. */ resizeValueText?: (width: number, column: DataTableColumn) => string; /** Test ID for testing harnesses. */ testId?: string; /** * Callback invoked when a row is clicked. When provided, rows render * with a clickable affordance (cursor: pointer + keyboard binding). */ onRowClick?: (row: T) => void; /** * Narrows `onRowClick` to the rows that can actually act on it, for a table * that mixes actionable and informational rows. A row this returns `false` * for gets no pointer affordance, no tab stop, and no keyboard binding, so it * is not announced as a button it cannot be. */ isRowClickable?: (row: T, index: number) => boolean; /** * Extra class for one row, for flagging a specific row without forking the * table: a transient deep-link highlight, a stale entry, a row being removed. * A falsy return adds nothing. */ rowClassName?: (row: T, index: number) => string | undefined | false | null; /** * Controlled — the column currently being sorted. Pass `undefined` to * indicate no active sort. When this prop is present, the component * operates in controlled mode: the caller is responsible for updating * the sort state via `onSortChange`. */ sortColumnId?: string; /** * Controlled — the direction of the active sort. Ignored when * `sortColumnId` is `undefined`. */ sortDirection?: SortDirection; /** * Called when the user activates a sortable column header. In * controlled mode the caller must propagate this back as * `sortColumnId` / `sortDirection`. In uncontrolled mode this prop is * purely observational. * * @param columnId The column being sorted, or `undefined` when the * sort is cleared. * @param direction The new direction. */ onSortChange?: (columnId: string | undefined, direction: SortDirection | undefined) => void; } declare function DataTableInner({ columns, rows, getRowKey, emptyState, loadingState, loading, columnState, onColumnStateChange, className, ariaLabel, resizeHandleLabel, resizeValueText, testId, onRowClick, isRowClickable, rowClassName, sortColumnId: controlledSortColumnId, sortDirection: controlledSortDirection, onSortChange, }: DataTableProps): import("react").JSX.Element; export declare const DataTable: typeof DataTableInner; export default DataTable;