import type { ReactNode, Ref } from 'react'; import type { Row, RowData } from '@tanstack/react-table'; import type { TestableProps } from '../../utils/testId'; declare module '@tanstack/react-table' { interface ColumnMeta { headerClassName?: string; cellClassName?: string; /** Sort label type — controls the wording in the sort submenu */ sortType?: 'text' | 'number' | 'date' | 'duration' | 'score' | 'boolean' | 'version' | 'severity' | 'size'; /** Cell text alignment. Defaults to 'right' for number/score/size sortType, 'left' otherwise */ align?: 'left' | 'center' | 'right'; /** Optional description — shown as text below the title or as a tooltip on hover. Title gets dashed underline. */ description?: { type: 'text' | 'tooltip'; content: string; }; /** Resize behavior: 'resize' adapts content to fit (default), 'cut' truncates content */ resizeType?: 'cut' | 'resize'; /** Render the three-dots contextual menu shown on hover */ renderMenuAction?: (row: Row) => ReactNode; } } /** Virtualization mode */ export type TableVirtualized = 'container' | 'window'; /** Sorting state: array of `{ id, desc }` */ export type TableSortingState = { id: string; desc: boolean; }[]; /** Row selection state: `{ [rowId]: boolean }` */ export type TableRowSelectionState = Record; /** Column sizing state: `{ [columnId]: number }` */ export type TableColumnSizingState = Record; /** Column pinning state */ export type TableColumnPinningState = { left?: string[]; right?: string[]; }; /** Expanded state: `true` (all) or `{ [rowId]: boolean }` */ export type TableExpandedState = true | Record; /** Grouping state: array of column IDs */ export type TableGroupingState = string[]; /** Column visibility state: `{ [columnId]: boolean }` */ export type TableVisibilityState = Record; /** State updater — value or functional update */ export type TableUpdater = T | ((prev: T) => T); /** Options for the imperative `scrollToRow` method */ export interface TableScrollToRowOptions { /** Alignment within the viewport. Default: 'auto'. */ align?: 'start' | 'center' | 'end' | 'auto'; /** Scroll behavior. Default: 'auto'. */ behavior?: 'auto' | 'smooth'; } /** * Imperative handle exposed via `ref` on ``. The only supported way * to programmatically scroll the table to a row that may be outside the * currently rendered virtual window. */ export interface TableHandle { /** * Scrolls to the row with the given id. * * Returns `true` if the row was found in the current row model and a * scroll was initiated. Returns `false` if the id is not in the current * rows or the virtualizer has not yet mounted — the caller decides * whether to load more pages or retry on the next frame. */ scrollToRow(id: string, opts?: TableScrollToRowOptions): boolean; } /** onChange callback */ export type TableOnChangeFn = (updaterOrValue: TableUpdater) => void; /** Public row interface — structural subset of TanStack Row */ export interface TableRow { id: string; original: T; subRows: TableRow[]; getIsExpanded: () => boolean; getToggleExpandedHandler: () => () => void; getIsSelected: () => boolean; getToggleSelectedHandler: () => (event: unknown) => void; getIsGrouped: () => boolean; } /** Public cell context — structural subset of TanStack CellContext */ export interface TableCellContext { getValue: () => V; row: TableRow; } /** Column meta — mirrors the ColumnMeta augmentation */ export interface TableColumnMeta { headerClassName?: string; cellClassName?: string; sortType?: 'text' | 'number' | 'date' | 'duration' | 'score' | 'boolean' | 'version' | 'severity' | 'size'; /** Cell text alignment. Defaults to 'right' for number/score/size sortType, 'left' otherwise */ align?: 'left' | 'center' | 'right'; /** Optional description — shown as text below the title or as a tooltip on hover. Title gets dashed underline. */ description?: { type: 'text' | 'tooltip'; content: string; }; /** Resize behavior: 'resize' adapts content to fit (default), 'cut' truncates content */ resizeType?: 'cut' | 'resize'; /** Render the three-dots contextual menu shown on hover */ renderMenuAction?: (row: TableRow) => ReactNode; } /** Shared column properties */ export interface TableColumnBase { header?: string | ((ctx: { column: { id: string; }; }) => ReactNode); cell?: (ctx: TableCellContext) => ReactNode; size?: number; minSize?: number; maxSize?: number; enableSorting?: boolean; enableResizing?: boolean; enableColumnPinning?: boolean; enableHiding?: boolean; meta?: TableColumnMeta; } /** Accessor column — maps to a data property */ export interface TableAccessorColumnDef extends TableColumnBase { accessorKey: keyof T & string; id?: string; } /** Display column — no data accessor, render-only */ export interface TableDisplayColumnDef extends TableColumnBase { id: string; accessorKey?: never; } /** * Union column def type. * `any` is required: V is invariant (contravariant callback params like `cell`), * so `unknown` would reject concrete types like `TableAccessorColumnDef`. * This mirrors TanStack Table's own `ColumnDef`. */ export type TableColumnDef = TableAccessorColumnDef | TableDisplayColumnDef; export interface TableProps extends TestableProps { /** Data array for rows */ data: T[]; /** Column definitions */ columns: TableColumnDef[]; /** Show skeleton rows */ isLoading?: boolean; /** * Show skeleton rows above the first row while a previous page is being * fetched (bidirectional infinite scroll — the start-edge counterpart of * `isLoading`). Pair with `onStartReached`. */ isLoadingPrevious?: boolean; /** Number of skeleton rows to display when loading (default: 6) */ skeletonCount?: number; /** Slot for TableActionBar, TableEmptyState, and other compound components */ children?: ReactNode; /** Row id accessor for stable row identity */ getRowId?: (row: T, index: number) => string; /** Accessible label for the table */ 'aria-label'?: string; /** Additional CSS class for the root container */ className?: string; sorting?: TableSortingState; onSortingChange?: TableOnChangeFn; /** * When `true`, disables TanStack's client-side sort. The table renders rows * in the order they appear in `data` and only fires `onSortingChange` on * header clicks. Use this when sorting is performed server-side and the * server returns pre-sorted rows. * * Default: `false` (client-side sort via TanStack's `getSortedRowModel`). */ manualSorting?: boolean; rowSelection?: TableRowSelectionState; onRowSelectionChange?: TableOnChangeFn; columnSizing?: TableColumnSizingState; onColumnSizingChange?: TableOnChangeFn; columnPinning?: TableColumnPinningState; onColumnPinningChange?: TableOnChangeFn; columnOrder?: string[]; onColumnOrderChange?: TableOnChangeFn; grouping?: TableGroupingState; onGroupingChange?: TableOnChangeFn; renderGroupRow?: (row: TableRow) => ReactNode; /** Sub-row accessor for hierarchical/tree data (used with renderGroupRow) */ getSubRows?: (row: T) => T[] | undefined; expanded?: TableExpandedState; onExpandedChange?: TableOnChangeFn; renderExpandedRow?: (row: TableRow) => ReactNode; columnVisibility?: TableVisibilityState; onColumnVisibilityChange?: TableOnChangeFn; defaultColumnVisibility?: TableVisibilityState; defaultColumnOrder?: string[]; /** Enable row virtualization. `'container'` virtualizes within the scroll container; `'window'` virtualizes against the browser window. */ virtualized?: TableVirtualized; estimateRowHeight?: (index: number) => number; overscan?: number; /** Callback fired when the user scrolls near the end (bottom) of the table */ onEndReached?: () => void; /** Distance from the bottom (in px) to trigger onEndReached (default: 200) */ onEndReachedThreshold?: number; /** Callback fired when the user scrolls near the start (top) of the table */ onStartReached?: () => void; /** Distance from the top (in px) to trigger onStartReached (default: 200) */ onStartReachedThreshold?: number; /** * Row id to anchor the initial scroll position to. The table scrolls this row * into view on mount and arms the edge detectors only after that initial * scroll settles. Use for deep-linking into the middle of a dataset. */ initialScrollToRowId?: string; /** Callback fired when the master cell is clicked. Receives the row ID. */ onMasterCellClick?: (rowId: string) => void; /** ID of the currently active (highlighted) row, or null. Controls row highlighting via data-preview-active attribute. */ activeRowId?: string | null; /** Imperative handle — exposes `scrollToRow(id, opts)`. See {@link TableHandle}. */ ref?: Ref; }