@jielga/tmdatagrid 0.2.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/index.d.ts +1337 -94
  2. package/dist/index.js +2812 -1189
  3. package/dist/index.js.map +1 -1
  4. package/dist/styles.css +1 -1
  5. package/package.json +2 -2
  6. package/skills/columns/SKILL.md +1 -1
  7. package/skills/features/SKILL.md +61 -11
  8. package/skills/getting-started/SKILL.md +41 -6
  9. package/skills/options/SKILL.md +12 -2
  10. package/skills/server-side/SKILL.md +1 -1
  11. package/src/tmdatagrid/TMDataGridContext.ts +26 -0
  12. package/src/tmdatagrid/components/TMDataGrid.module.css +21 -1
  13. package/src/tmdatagrid/components/TMDataGrid.tsx +29 -1
  14. package/src/tmdatagrid/components/TMDataGridColumnsPanel.tsx +12 -6
  15. package/src/tmdatagrid/components/TMDataGridDetailsColumn.module.css +33 -0
  16. package/src/tmdatagrid/components/TMDataGridDetailsColumn.tsx +160 -0
  17. package/src/tmdatagrid/components/TMDataGridFilterPanel.module.css +15 -0
  18. package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +192 -37
  19. package/src/tmdatagrid/components/TMDataGridFilterPills.module.css +35 -0
  20. package/src/tmdatagrid/components/TMDataGridFilterPills.tsx +136 -0
  21. package/src/tmdatagrid/components/TMDataGridFooter.module.css +8 -0
  22. package/src/tmdatagrid/components/TMDataGridFooter.tsx +63 -43
  23. package/src/tmdatagrid/components/TMDataGridGroupColumn.module.css +48 -0
  24. package/src/tmdatagrid/components/TMDataGridGroupColumn.tsx +159 -0
  25. package/src/tmdatagrid/components/TMDataGridHeaderCell.module.css +18 -0
  26. package/src/tmdatagrid/components/TMDataGridHeaderCell.tsx +249 -44
  27. package/src/tmdatagrid/components/TMDataGridSearch.tsx +122 -0
  28. package/src/tmdatagrid/components/TMDataGridSelectColumn.tsx +103 -16
  29. package/src/tmdatagrid/components/TMDataGridTable.module.css +160 -5
  30. package/src/tmdatagrid/components/TMDataGridTable.tsx +1380 -43
  31. package/src/tmdatagrid/components/TMDataGridToolbar.tsx +33 -7
  32. package/src/tmdatagrid/components/icons.ts +6 -0
  33. package/src/tmdatagrid/components/sticky.module.css +77 -16
  34. package/src/tmdatagrid/core/autosize.ts +125 -0
  35. package/src/tmdatagrid/core/capabilities.ts +122 -11
  36. package/src/tmdatagrid/core/cellExport.ts +321 -0
  37. package/src/tmdatagrid/core/cellNavigation.ts +103 -0
  38. package/src/tmdatagrid/core/cellRange.ts +118 -0
  39. package/src/tmdatagrid/core/columnOptions.ts +123 -0
  40. package/src/tmdatagrid/core/columnUtils.ts +18 -0
  41. package/src/tmdatagrid/core/expanding.ts +93 -0
  42. package/src/tmdatagrid/core/filterOperators.ts +198 -12
  43. package/src/tmdatagrid/core/grouping.ts +21 -0
  44. package/src/tmdatagrid/core/labels.ts +211 -0
  45. package/src/tmdatagrid/core/labelsSv.ts +108 -0
  46. package/src/tmdatagrid/core/persistence.ts +12 -0
  47. package/src/tmdatagrid/core/rowSelection.ts +202 -0
  48. package/src/tmdatagrid/core/summary.ts +35 -0
  49. package/src/tmdatagrid/index.ts +96 -2
  50. package/src/tmdatagrid/useTMDataGrid.tsx +558 -37
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { Column, ColumnPinningState, Row, RowData, Table, TableFeatures, TableOptions, TableState } from "@tanstack/react-table";
1
+ import { Cell, Column, ColumnPinningState, ExpandedState, Row, RowData, RowSelectionState, Table, TableFeatures, TableOptions, TableState, aggregationFns } from "@tanstack/react-table";
2
2
  import { CSSProperties, ReactNode } from "react";
3
+ import { MantineSize, MenuProps } from "@mantine/core";
3
4
  import { Store } from "@tanstack/store";
4
- import { MantineSize } from "@mantine/core";
5
5
  //#region .types-tmp/components/TMDataGridColumnsPanel.d.ts
6
6
  /**
7
7
  * The "Manage columns" surface. Reachable from every column header menu and
@@ -19,6 +19,121 @@ declare function TMDataGridColumnsPanel(): import("react").JSX.Element;
19
19
  */
20
20
  declare function TMDataGridFilterPanel(): import("react").JSX.Element | null;
21
21
  //#endregion
22
+ //#region .types-tmp/core/sizes.d.ts
23
+ type TMDataGridSize = MantineSize;
24
+ declare const DEFAULT_TMDATAGRID_SIZE: TMDataGridSize;
25
+ /**
26
+ * Row height per size, in px.
27
+ *
28
+ * The virtualizer needs this as a number — it cannot read the CSS variable —
29
+ * so the scale lives here and `TMDataGrid.module.css` mirrors it. `meta.rowHeight`
30
+ * overrides it when a grid needs a height the scale doesn't offer.
31
+ */
32
+ declare const SIZE_ROW_HEIGHT: Record<TMDataGridSize, number>;
33
+ /** Size of the Mantine controls rendered inside the grid chrome. */
34
+ declare const SIZE_CONTROL_SIZE: Record<TMDataGridSize, MantineSize>;
35
+ //#endregion
36
+ //#region .types-tmp/TMDataGridContext.d.ts
37
+ /**
38
+ * Row shape the chrome components work against. They only ever touch columns,
39
+ * rows and cells generically, so the concrete row type is erased at the context
40
+ * boundary — the same trick Mantine uses for its compound components.
41
+ */
42
+ type TMDataGridRowData = Record<string, unknown>;
43
+ type TMDataGridContextValue = TMDataGridApi<TMDataGridRowData> & {
44
+ size: TMDataGridSize;
45
+ /** Row height in px, already resolved from `size` and `meta.rowHeight`. */
46
+ rowHeight: number;
47
+ /** Mantine control size that pairs with `size`. */
48
+ controlSize: TMDataGridSize;
49
+ };
50
+ declare function useTMDataGridContext(): TMDataGridContextValue;
51
+ /**
52
+ * What a control inside a *body* cell should put in its `tabIndex`.
53
+ *
54
+ * `-1` once cell selection is on, and this is what makes the promise of one tab
55
+ * stop true. Without it the browser walks Tab into the checkbox of every
56
+ * mounted row — a grid showing twenty rows would be twenty tab stops, and
57
+ * scrolling would change how many. Enter or F2 steps into the cell instead,
58
+ * which reaches a `-1` control perfectly well.
59
+ *
60
+ * Header controls are not covered: the header row is not part of cell
61
+ * navigation, so its sort buttons and menus stay in the tab order, where they
62
+ * are the only way to reach them.
63
+ *
64
+ * A custom cell renderer with a control in it wants the same:
65
+ *
66
+ * ```tsx
67
+ * cell: ({ row }) => (
68
+ * <Button tabIndex={useCellControlTabIndex()} onClick={...}>Open</Button>
69
+ * )
70
+ * ```
71
+ */
72
+ declare function useCellControlTabIndex(): 0 | -1;
73
+ //#endregion
74
+ //#region .types-tmp/core/columnOptions.d.ts
75
+ /**
76
+ * One choice of a `select` / `multiSelect` column. A bare string in any options
77
+ * list is shorthand for `{ value }`.
78
+ */
79
+ type TMDataGridOption = {
80
+ value: string;
81
+ /** Shown in dropdowns. Defaults to the value itself. */
82
+ label?: string;
83
+ /** Mantine colour for the value's badge, where a cell renders one. */
84
+ color?: string;
85
+ disabled?: boolean;
86
+ /** Dropdown group heading. Ungrouped options render first. */
87
+ group?: string;
88
+ };
89
+ type TMDataGridOptionsArgs = {
90
+ table: TMDataGridTable<TMDataGridRowData>;
91
+ column: Column<TMDataGridFeatures, TMDataGridRowData, unknown>;
92
+ /** The row an editor is standing on. Absent when the filter panel asks. */
93
+ row?: Row<TMDataGridFeatures, TMDataGridRowData>;
94
+ /**
95
+ * Source to use when the column declares none. The filter panel passes
96
+ * `"faceted"` so a select column with no `meta.options` still offers the
97
+ * values that exist, rather than an empty dropdown.
98
+ */
99
+ fallback?: TMDataGridOptionsSource;
100
+ };
101
+ /**
102
+ * Where a column's options come from — `meta.options`. One declaration feeds
103
+ * both the filter panel's value control and the cell editor.
104
+ *
105
+ * | Form | For |
106
+ * | --- | --- |
107
+ * | array | a known, fixed set |
108
+ * | `"faceted"` | low-cardinality data columns: the distinct values present, via `getFacetedUniqueValues` |
109
+ * | function | large or contextual sets — `row` is set when an editor asks, so options can depend on the record (city given country) |
110
+ */
111
+ type TMDataGridOptionsSource = ReadonlyArray<TMDataGridOption | string> | "faceted" | ((args: TMDataGridOptionsArgs) => ReadonlyArray<TMDataGridOption | string>);
112
+ /**
113
+ * A column's options as a normalised list, whatever form `meta.options` took.
114
+ * Empty for a column that declares none.
115
+ *
116
+ * `"faceted"` reads the distinct values actually present in the data. A
117
+ * multiSelect cell holds an array, so array values contribute their elements
118
+ * rather than the array itself.
119
+ */
120
+ declare function resolveColumnOptions({ table, column, row, fallback }: TMDataGridOptionsArgs): Array<TMDataGridOption>;
121
+ type ComboboxItem = {
122
+ value: string;
123
+ label: string;
124
+ disabled?: boolean;
125
+ };
126
+ type ComboboxData = Array<ComboboxItem | {
127
+ group: string;
128
+ items: ComboboxItem[];
129
+ }>;
130
+ /**
131
+ * The same list in the shape Mantine's `Select` / `MultiSelect` take, with
132
+ * `group` fields folded into Mantine's group entries. Ungrouped options come
133
+ * first, then the groups in first-appearance order.
134
+ */
135
+ declare function optionsToComboboxData(options: ReadonlyArray<TMDataGridOption>): ComboboxData;
136
+ //#endregion
22
137
  //#region .types-tmp/core/filterOperators.d.ts
23
138
  /**
24
139
  * The value shape stored in `columnFilters` for every TMDataGrid column.
@@ -27,20 +142,43 @@ declare function TMDataGridFilterPanel(): import("react").JSX.Element | null;
27
142
  * inside the filter *value* instead. That keeps the whole filter model plain,
28
143
  * serialisable JSON — which is what makes it portable to a server-side
29
144
  * `manualFiltering` table (just forward `columnFilters` to the API).
145
+ *
146
+ * `value` is a string array under `isAnyOf` / `isNoneOf` (the set the cell is
147
+ * tested against) and a single string everywhere else — dates travel as ISO
148
+ * `YYYY-MM-DD` strings, booleans as `"true"` / `"false"`. Still plain JSON.
30
149
  */
31
150
  type TMDataGridFilterValue = {
32
151
  operator: TMDataGridFilterOperator;
33
- value: string;
152
+ value: string | ReadonlyArray<string>;
34
153
  };
35
- type TMDataGridColumnType = "string" | "number";
36
- type TMDataGridFilterOperator = "contains" | "equals" | "notEquals" | "startsWith" | "endsWith" | "greaterThan" | "greaterThanOrEqual" | "lessThan" | "lessThanOrEqual" | "isEmpty" | "isNotEmpty";
154
+ type TMDataGridColumnType = "string" | "number" | "boolean" | "date" | "select" | "multiSelect";
155
+ type TMDataGridFilterOperator = "contains" | "equals" | "notEquals" | "startsWith" | "endsWith" | "greaterThan" | "greaterThanOrEqual" | "lessThan" | "lessThanOrEqual" | "before" | "after" | "onOrBefore" | "onOrAfter" | "isAnyOf" | "isNoneOf" | "isEmpty" | "isNotEmpty";
37
156
  declare const FILTER_OPERATOR_LABELS: Record<TMDataGridFilterOperator, string>;
157
+ declare function getOperatorsForType(type: TMDataGridColumnType): readonly TMDataGridFilterOperator[];
158
+ declare function getDefaultOperator(type: TMDataGridColumnType): TMDataGridFilterOperator;
159
+ declare function operatorNeedsValue(operator: TMDataGridFilterOperator): boolean;
160
+ /** Whether the operator's value is a string array — `isAnyOf` / `isNoneOf`. */
161
+ declare function operatorTakesArrayValue(operator: TMDataGridFilterOperator): boolean;
38
162
  /**
39
163
  * A filter only narrows the row set once it has something to compare against.
40
164
  * Half-typed filters stay in state (so the panel keeps rendering their row) but
41
165
  * are treated as inactive for the funnel indicator and for row matching.
42
166
  */
43
167
  declare function isFilterActive(value: unknown): boolean;
168
+ /**
169
+ * One-line description of a single filter, as shown on a filter pill.
170
+ *
171
+ * The type's default operator is left implicit — "First name: Sofia" reads the
172
+ * way a person would say it — while any other operator is spelled out, since
173
+ * that is the part a reader cannot guess.
174
+ */
175
+ declare function formatFilterLabel({ label, type, filter, operatorLabels }: {
176
+ label: string;
177
+ type: TMDataGridColumnType;
178
+ filter: TMDataGridFilterValue;
179
+ /** Localized operator names — `labels.operators`. Defaults to English. */
180
+ operatorLabels?: Record<TMDataGridFilterOperator, string>;
181
+ }): string;
44
182
  /**
45
183
  * The single filter function every TMDataGrid column uses. It dispatches on the
46
184
  * operator carried by the filter value, which is what lets one column offer
@@ -48,6 +186,102 @@ declare function isFilterActive(value: unknown): boolean;
48
186
  */
49
187
  declare function tmDataGridFilterFn<TFeatures extends TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: unknown): boolean;
50
188
  //#endregion
189
+ //#region .types-tmp/core/labels.d.ts
190
+ /**
191
+ * Every user-facing string in the grid — menu items, panels, tooltips, the
192
+ * pager, and the `aria-label`s a screen reader speaks. One flat object, so an
193
+ * override is a spread rather than a deep merge; `operators` is the single
194
+ * nested record and {@link mergeLabels} folds it separately.
195
+ *
196
+ * Labels that carry a value are functions rather than template strings, so a
197
+ * language is free to put the value wherever its grammar wants it.
198
+ */
199
+ type TMDataGridLabels = {
200
+ /** Filter operator names, as shown in the operator dropdown and on pills. */
201
+ operators: Record<TMDataGridFilterOperator, string>;
202
+ /** "Manage columns" — the burger button and the header menu item. */
203
+ manageColumns: string;
204
+ /** "Filters" — the funnel button and the filter panel's title. */
205
+ filters: string;
206
+ searchPlaceholder: string;
207
+ searchLabel: string;
208
+ clearSearch: string;
209
+ columnsSearchPlaceholder: string;
210
+ columnsNoMatch: (search: string) => string;
211
+ columnsShowHideAll: string;
212
+ columnsReset: string;
213
+ filterColumn: string;
214
+ filterOperator: string;
215
+ filterValue: string;
216
+ filterValuePlaceholder: string;
217
+ /** What a boolean column's `true` reads as — its filter choice and cell text. */
218
+ booleanTrue: string;
219
+ booleanFalse: string;
220
+ addFilter: string;
221
+ clearAllFilters: string;
222
+ closeFilters: string;
223
+ removeFilter: string;
224
+ activeFilters: string;
225
+ clearFilter: (column: string) => string;
226
+ sortAsc: string;
227
+ sortDesc: string;
228
+ filterMenuItem: string;
229
+ groupBy: (column: string) => string;
230
+ ungroup: (column: string) => string;
231
+ expandAllGroups: string;
232
+ collapseAllGroups: string;
233
+ pinLeft: string;
234
+ pinRight: string;
235
+ unpin: string;
236
+ moveLeft: string;
237
+ moveRight: string;
238
+ autosizeColumn: string;
239
+ hideColumn: string;
240
+ filterOn: (column: string) => string;
241
+ sortColumn: (column: string) => string;
242
+ columnMenu: (column: string) => string;
243
+ rowsPerPage: string;
244
+ pageRange: (args: {
245
+ from: number;
246
+ to: number;
247
+ total: number;
248
+ }) => string;
249
+ groupedAllRows: (total: number) => string;
250
+ pagingSuspendedHint: string;
251
+ previousPage: string;
252
+ nextPage: string;
253
+ noResults: string;
254
+ loading: string;
255
+ cellCount: (count: number) => string;
256
+ copy: string;
257
+ exportCsv: string;
258
+ includeHeaders: string;
259
+ selectColumnLabel: string;
260
+ selectAllRows: string;
261
+ selectRow: string;
262
+ selectGroup: string;
263
+ detailsColumnLabel: string;
264
+ showDetails: string;
265
+ hideDetails: string;
266
+ expandAllDetails: string;
267
+ collapseAllDetails: string;
268
+ groupColumnLabel: string;
269
+ blankGroupValue: string;
270
+ expandGroup: (label: string) => string;
271
+ collapseGroup: (label: string) => string;
272
+ };
273
+ /**
274
+ * What the `labels` option accepts: any subset, merged over the English
275
+ * defaults — so `{ noResults: "Inga rader" }` is a complete configuration.
276
+ */
277
+ type TMDataGridLabelsOverride = Partial<Omit<TMDataGridLabels, "operators">> & {
278
+ operators?: Partial<Record<TMDataGridFilterOperator, string>>;
279
+ };
280
+ /** The built-in defaults. Also the reference for what a preset must cover. */
281
+ declare const TMDATAGRID_LABELS_EN: TMDataGridLabels;
282
+ /** A partial override folded over the English defaults. */
283
+ declare function mergeLabels(override?: TMDataGridLabelsOverride): TMDataGridLabels;
284
+ //#endregion
51
285
  //#region .types-tmp/core/persistence.d.ts
52
286
  type GridState = TableState<TMDataGridFeatures>;
53
287
  /**
@@ -69,12 +303,12 @@ type GridState = TableState<TMDataGridFeatures>;
69
303
  * State slices describing what the user is looking at. Derived from the data,
70
304
  * so they can go stale as it changes.
71
305
  */
72
- declare const DATA_STATE_SLICES: readonly ["columnFilters", "globalFilter", "sorting", "pagination"];
306
+ declare const DATA_STATE_SLICES: readonly ["columnFilters", "globalFilter", "sorting", "pagination", "expanded"];
73
307
  /**
74
308
  * State slices describing how the user configured the grid. Independent of the
75
309
  * data, and the ones users notice losing.
76
310
  */
77
- declare const SETTINGS_STATE_SLICES: readonly ["columnVisibility", "columnSizing", "columnOrder", "columnPinning"];
311
+ declare const SETTINGS_STATE_SLICES: readonly ["columnVisibility", "columnSizing", "columnOrder", "columnPinning", "grouping"];
78
312
  type TMDataGridDataSlice = (typeof DATA_STATE_SLICES)[number];
79
313
  type TMDataGridSettingsSlice = (typeof SETTINGS_STATE_SLICES)[number];
80
314
  /**
@@ -99,36 +333,6 @@ type TMDataGridPersistence = {
99
333
  deserialize?: (value: string) => unknown;
100
334
  };
101
335
  //#endregion
102
- //#region .types-tmp/core/sizes.d.ts
103
- type TMDataGridSize = MantineSize;
104
- declare const DEFAULT_TMDATAGRID_SIZE: TMDataGridSize;
105
- /**
106
- * Row height per size, in px.
107
- *
108
- * The virtualizer needs this as a number — it cannot read the CSS variable —
109
- * so the scale lives here and `TMDataGrid.module.css` mirrors it. `meta.rowHeight`
110
- * overrides it when a grid needs a height the scale doesn't offer.
111
- */
112
- declare const SIZE_ROW_HEIGHT: Record<TMDataGridSize, number>;
113
- /** Size of the Mantine controls rendered inside the grid chrome. */
114
- declare const SIZE_CONTROL_SIZE: Record<TMDataGridSize, MantineSize>;
115
- //#endregion
116
- //#region .types-tmp/TMDataGridContext.d.ts
117
- /**
118
- * Row shape the chrome components work against. They only ever touch columns,
119
- * rows and cells generically, so the concrete row type is erased at the context
120
- * boundary — the same trick Mantine uses for its compound components.
121
- */
122
- type TMDataGridRowData = Record<string, unknown>;
123
- type TMDataGridContextValue = TMDataGridApi<TMDataGridRowData> & {
124
- size: TMDataGridSize;
125
- /** Row height in px, already resolved from `size` and `meta.rowHeight`. */
126
- rowHeight: number;
127
- /** Mantine control size that pairs with `size`. */
128
- controlSize: TMDataGridSize;
129
- };
130
- declare function useTMDataGridContext(): TMDataGridContextValue;
131
- //#endregion
132
336
  //#region .types-tmp/core/capabilities.d.ts
133
337
  /**
134
338
  * Table-level feature switches, read straight off the options object.
@@ -143,29 +347,103 @@ declare function useTMDataGridContext(): TMDataGridContextValue;
143
347
  * what applies the per-column overrides.
144
348
  */
145
349
  /**
146
- * How rows are selected — see `rowSelectionMode` on {@link UseTMDataGridOptions}.
350
+ * How rows are selected — see `selectionMode` on {@link UseTMDataGridOptions}.
351
+ *
352
+ * One axis, because the two things a config could set independently — which
353
+ * chrome selects, and what a bare row click does — cannot both be free: a click
354
+ * can either toggle a multi-selection or move the highlight, never both. Folding
355
+ * them into one value makes that conflict unrepresentable rather than something
356
+ * to warn about.
147
357
  */
148
- type TMDataGridRowSelectionMode = "checkbox" | "row";
358
+ type TMDataGridSelectionMode =
359
+ /** Checkbox column, multi-select. Clicking a row elsewhere does nothing. */
360
+ "checkbox" |
361
+ /** No checkbox column; row click multi-selects, with Ctrl/Shift modifiers. */
362
+ "row" |
363
+ /** Checkbox column multi-selects, and a row click highlights one row. */
364
+ "checkboxAndHighlight" |
365
+ /** No selection at all — a row click only highlights. Master-detail. */
366
+ "highlight";
367
+ /**
368
+ * How cells are selected — see `cellSelection` on {@link UseTMDataGridOptions}.
369
+ *
370
+ * A mode rather than a pair of booleans, for the reason
371
+ * {@link TMDataGridSelectionMode} is one: "cells can be selected" and "more
372
+ * than one at a time" are not independent, and a range that cannot be anchored
373
+ * anywhere is not a state worth being able to write down.
374
+ */
375
+ type TMDataGridCellSelectionMode =
376
+ /** No cell cursor at all. The body's tab stop stays on the row. */
377
+ "none" |
378
+ /** One cell takes the focus and the arrow keys move it. */
379
+ "single" |
380
+ /** As `"single"`, plus a rectangle: drag, Shift+click, Shift+arrows, Ctrl+C. */
381
+ "range";
149
382
  type TMDataGridFeatureFlags = {
150
383
  sorting: boolean;
151
384
  filtering: boolean;
385
+ /** Whether the quick search may filter — `enableGlobalFilter`. */
386
+ globalFiltering: boolean;
152
387
  hiding: boolean;
153
388
  pinning: boolean;
154
389
  resizing: boolean;
155
390
  ordering: boolean;
391
+ /** Whether any row selection is possible. Off outright under `"highlight"`. */
156
392
  rowSelection: boolean;
157
- /** Only meaningful while `rowSelection` is on. Defaults to `"checkbox"`. */
158
- rowSelectionMode: TMDataGridRowSelectionMode;
393
+ /** Defaults to `"checkbox"`. */
394
+ selectionMode: TMDataGridSelectionMode;
395
+ /** Whether the generated checkbox column is prepended. */
396
+ selectColumn: boolean;
397
+ /** Whether a bare row click toggles the selection. Only under `"row"`. */
398
+ rowClickSelects: boolean;
399
+ /**
400
+ * Whether more than one row can be selected at once — TanStack's
401
+ * `enableMultiRowSelection`. Off, the grid drops the select-all header
402
+ * checkbox: TanStack's `toggleAllRowsSelected` only consults `getCanSelect`,
403
+ * so that control would select every row and walk straight past the limit.
404
+ *
405
+ * A per-row predicate counts as on, since some rows may still multi-select.
406
+ */
407
+ multiRowSelection: boolean;
159
408
  /** Whether a selected row takes the highlight colour. Follows the mode. */
160
- highlightSelectedRows: boolean;
409
+ showSelectedBackground: boolean;
410
+ /**
411
+ * The single highlighted row — clicking a row highlights it, for a detail
412
+ * panel to follow. State of its own, not a slice of `rowSelection`, which is
413
+ * what lets it coexist with a checkbox multi-selection.
414
+ */
415
+ highlightRow: boolean;
416
+ /**
417
+ * Whether cells can be selected at all. Off unless `cellSelection` asks for
418
+ * it — it takes the body's tab stop off the row and puts it on a cell, and
419
+ * reports the grid to assistive technology as a `grid` rather than a `table`,
420
+ * which is a different promise about what the keyboard does.
421
+ */
422
+ cellSelection: boolean;
423
+ /** Defaults to `"none"`. */
424
+ cellSelectionMode: TMDataGridCellSelectionMode;
425
+ /** Whether a rectangle of cells can be selected. Only under `"range"`. */
426
+ cellRangeSelection: boolean;
161
427
  /**
162
428
  * The one default-off flag: pagination must be asked for, either with the
163
429
  * grid's `enablePagination` or implicitly by declaring `manualPagination`.
164
430
  * Off, the grid renders every filtered row and relies on virtualization.
165
431
  */
166
432
  pagination: boolean;
433
+ /**
434
+ * Row grouping: the "Group by" items in the header menu and the generated
435
+ * tree column. On unless `enableGrouping: false`, since an ungrouped grid
436
+ * looks and behaves exactly as it did before — `grouping` starts empty, and
437
+ * an empty grouping state passes straight through the row model.
438
+ *
439
+ * The exception is `manualPagination`, where the client holds one page rather
440
+ * than the whole set: grouping that page would build groups out of an
441
+ * arbitrary slice and quietly show wrong counts. A server-side grid that does
442
+ * its own grouping can still say `enableGrouping: true` to override.
443
+ */
444
+ grouping: boolean;
167
445
  };
168
- declare function readFeatureFlags<TData extends RowData>(options: Pick<UseTMDataGridOptions<TData>, "enableSorting" | "enableColumnFilters" | "enableHiding" | "enableColumnPinning" | "enableColumnResizing" | "enableColumnOrdering" | "enableRowSelection" | "rowSelectionMode" | "highlightSelectedRows" | "enablePagination" | "manualPagination">): TMDataGridFeatureFlags;
446
+ declare function readFeatureFlags<TData extends RowData>(options: Pick<UseTMDataGridOptions<TData>, "enableSorting" | "enableColumnFilters" | "enableGlobalFilter" | "enableHiding" | "enableColumnPinning" | "enableColumnResizing" | "enableColumnOrdering" | "enableRowSelection" | "enableMultiRowSelection" | "selectionMode" | "showSelectedBackground" | "cellSelection" | "enablePagination" | "manualPagination" | "enableGrouping">): TMDataGridFeatureFlags;
169
447
  /**
170
448
  * What one column's header may offer.
171
449
  *
@@ -177,6 +455,7 @@ declare function readFeatureFlags<TData extends RowData>(options: Pick<UseTMData
177
455
  * | Pin to left / right | `enableColumnPinning` / `enablePinning` |
178
456
  * | Resize dragging | `enableColumnResizing` / `enableResizing` |
179
457
  * | Header dragging, Move left / right | `enableColumnOrdering` / `meta.enableOrdering` |
458
+ * | Group by / Ungroup | `enableGrouping` (table or column) |
180
459
  */
181
460
  type TMDataGridColumnCapabilities = {
182
461
  canSort: boolean;
@@ -185,6 +464,7 @@ type TMDataGridColumnCapabilities = {
185
464
  canPin: boolean;
186
465
  canResize: boolean;
187
466
  canReorder: boolean;
467
+ canGroup: boolean;
188
468
  };
189
469
  declare function getColumnCapabilities(column: Column<TMDataGridFeatures, TMDataGridRowData, unknown>, features: TMDataGridFeatureFlags): TMDataGridColumnCapabilities;
190
470
  /** The same questions, asked of the whole grid — used to hide toolbar buttons. */
@@ -194,21 +474,154 @@ type TMDataGridCapabilities = {
194
474
  canHideAny: boolean;
195
475
  canPinAny: boolean;
196
476
  canReorderAny: boolean;
477
+ canGroupAny: boolean;
197
478
  canSelectRows: boolean;
198
479
  canPaginate: boolean;
480
+ /** At least one leaf column takes part in the global quick search. */
481
+ canSearch: boolean;
199
482
  };
200
483
  declare function getGridCapabilities(table: TMDataGridTable<TMDataGridRowData>, features: TMDataGridFeatureFlags): TMDataGridCapabilities;
201
484
  //#endregion
485
+ //#region .types-tmp/core/cellNavigation.d.ts
486
+ /**
487
+ * Which cell has the focus, by id rather than by position.
488
+ *
489
+ * Ids, because every other thing the grid does moves cells around: sorting
490
+ * reorders rows, filtering removes them, dragging a header reorders columns. A
491
+ * coordinate pair would silently come to mean a different cell after any of
492
+ * them, while a pair of ids either still resolves or does not resolve at all —
493
+ * and "does not resolve" is a state the grid can handle honestly.
494
+ *
495
+ * Indices are what navigation is actually computed in, so they are resolved
496
+ * from the ids on each keystroke and turned straight back. See resolveCellMove.
497
+ */
498
+ type TMDataGridCellPosition = {
499
+ rowId: string;
500
+ columnId: string;
501
+ };
502
+ /** Where the focused cell sits in the rows and columns on screen. */
503
+ type TMDataGridCellCoords = {
504
+ rowIndex: number;
505
+ columnIndex: number;
506
+ };
507
+ type ResolveCellMoveArgs = {
508
+ /** `KeyboardEvent.key`. */
509
+ key: string;
510
+ /** Ctrl or Cmd — Home and End jump to the corner rather than the row end. */
511
+ ctrlKey: boolean;
512
+ from: TMDataGridCellCoords;
513
+ rowCount: number;
514
+ columnCount: number;
515
+ /**
516
+ * How far PageUp and PageDown travel: one viewport of rows. Passed in rather
517
+ * than assumed, since only the body knows how tall it is.
518
+ */
519
+ pageRows: number;
520
+ };
521
+ /**
522
+ * The next cell for a navigation key, or `null` when the key is not one.
523
+ *
524
+ * Moves clamp at the edges instead of wrapping. Wrapping suits a menu, where
525
+ * the items are a short ring; a grid is a coordinate space, and a Right at the
526
+ * last column that lands on the first column of the next row loses the one
527
+ * thing arrow keys are for — knowing where you will end up without looking.
528
+ *
529
+ * A clamped move returns the position it started from rather than `null`. The
530
+ * caller still needs to know the key was handled: an arrow at the last row must
531
+ * not fall through to the scroll container, which would scroll the body out
532
+ * from under a focus that did not move.
533
+ */
534
+ declare function resolveCellMove({ key, ctrlKey, from, rowCount, columnCount, pageRows }: ResolveCellMoveArgs): TMDataGridCellCoords | null;
535
+ /** Whether two positions address the same cell. `null` equals only `null`. */
536
+ declare function isSameCell(a: TMDataGridCellPosition | null, b: TMDataGridCellPosition | null): boolean;
537
+ //#endregion
538
+ //#region .types-tmp/core/cellRange.d.ts
539
+ /**
540
+ * A selected rectangle of cells, held as the two cells that span it.
541
+ *
542
+ * Two corners rather than a list of cells, because a range is a gesture, not a
543
+ * set: dragging over 40 columns of a 100k-row grid would otherwise build — and
544
+ * rebuild, on every mouse move — a list with millions of entries in it. Two
545
+ * positions describe the same thing and cost nothing to extend.
546
+ *
547
+ * `anchor` is where the gesture started and stays put; `focus` is the end that
548
+ * moves. Which of the two is top-left depends on the direction it was dragged,
549
+ * so nothing here assumes an order — see {@link resolveRangeBounds}.
550
+ */
551
+ type TMDataGridCellRange = {
552
+ anchor: TMDataGridCellPosition;
553
+ focus: TMDataGridCellPosition;
554
+ };
555
+ /** The rectangle a range covers, in row and column indices, both ends included. */
556
+ type TMDataGridRangeBounds = {
557
+ top: number;
558
+ bottom: number;
559
+ left: number;
560
+ right: number;
561
+ };
562
+ type ResolveRangeBoundsArgs = {
563
+ range: TMDataGridCellRange | null;
564
+ /** Index of a row id among the rows on screen, or `-1`. */
565
+ rowIndexOf: (rowId: string) => number;
566
+ columnIndexOf: (columnId: string) => number;
567
+ };
568
+ /**
569
+ * Turns a range into the rectangle to paint and copy, or `null` when either
570
+ * corner no longer exists.
571
+ *
572
+ * A corner goes missing whenever a filter drops its row or a column is hidden,
573
+ * and the honest answer then is that there is no rectangle — better than
574
+ * guessing at a replacement corner and quietly copying cells the user never
575
+ * selected. The range itself is left alone: clearing it here would throw away
576
+ * a selection that comes straight back when the filter is lifted.
577
+ */
578
+ declare function resolveRangeBounds({ range, rowIndexOf, columnIndexOf }: ResolveRangeBoundsArgs): TMDataGridRangeBounds | null;
579
+ /** Whether a cell is inside the rectangle. */
580
+ declare function isWithinBounds(bounds: TMDataGridRangeBounds | null, rowIndex: number, columnIndex: number): boolean;
581
+ /** How many cells the rectangle covers. `0` for no range at all. */
582
+ declare function boundsCellCount(bounds: TMDataGridRangeBounds | null): number;
583
+ /**
584
+ * Which edges of the rectangle a cell sits on, for the outline.
585
+ *
586
+ * The border is drawn per cell rather than as one box over the top, because the
587
+ * body is a scrolling CSS grid with sticky columns in it: an overlay would have
588
+ * to be positioned against a moving target and would still be wrong the moment
589
+ * a pinned lane slid over it. Four booleans per cell need no positioning at all.
590
+ */
591
+ declare function boundsEdges(bounds: TMDataGridRangeBounds | null, rowIndex: number, columnIndex: number): {
592
+ top: boolean;
593
+ bottom: boolean;
594
+ left: boolean;
595
+ right: boolean;
596
+ } | null;
597
+ //#endregion
202
598
  //#region .types-tmp/useTMDataGrid.d.ts
203
599
  /** Per-column configuration the TMDataGrid chrome reads. */
204
600
  type TMDataGridColumnMeta = {
205
601
  /** Name shown in menus and the column manager. Falls back to a string header. */
206
602
  label?: string;
207
- /** Drives which filter operators are offered. Defaults to `"string"`. */
603
+ /**
604
+ * Drives which filter operators are offered and, once editing is on, which
605
+ * editor the cell opens. Defaults to `"string"`.
606
+ */
208
607
  type?: TMDataGridColumnType;
608
+ /**
609
+ * The choices of a `select` / `multiSelect` column — one declaration feeding
610
+ * the filter panel's value control and the cell editor alike. A static
611
+ * array, `"faceted"` (the distinct values present in the data), or a
612
+ * function of the table, column and — for editors — the row. See
613
+ * {@link TMDataGridOptionsSource}.
614
+ */
615
+ options?: TMDataGridOptionsSource;
209
616
  /** Share of the leftover width this column claims. Defaults to `1`. */
210
617
  flex?: number;
211
618
  align?: "left" | "right" | "center";
619
+ /**
620
+ * Size the column to its widest mounted content once, after the first rows
621
+ * render — unless a persisted or user-set width already covers it. The same
622
+ * measurement as double-clicking the resize divider; see `autosizeColumn`.
623
+ */
624
+ autoSize?: boolean;
212
625
  /**
213
626
  * `false` keeps the column where it is: no header dragging, no move items.
214
627
  * Column ordering is the one feature TanStack defines no column option for,
@@ -244,57 +657,72 @@ declare const tmDataGridFeatures: {
244
657
  columnSizingFeature: import("@tanstack/table-core").TableFeature;
245
658
  columnResizingFeature: import("@tanstack/table-core").TableFeature;
246
659
  columnFacetingFeature: import("@tanstack/table-core").TableFeature;
660
+ columnGroupingFeature: import("@tanstack/table-core").TableFeature;
661
+ rowExpandingFeature: import("@tanstack/table-core").TableFeature;
247
662
  filteredRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
663
+ groupedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
248
664
  sortedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
665
+ expandedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
249
666
  paginatedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
250
667
  facetedRowModel: (table: Table<any, any>, columnId: string) => () => import("@tanstack/table-core").RowModel<any, any>;
251
668
  facetedMinMaxValues: (table: Table<import("@tanstack/table-core").TableFeatures, any>, columnId: string) => () => undefined | [number, number];
252
669
  facetedUniqueValues: (table: Table<import("@tanstack/table-core").TableFeatures, any>, columnId: string) => () => Map<any, number>;
253
670
  filterFns: {
254
- arrIncludes: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValue: Array<unknown>) => boolean) & {
671
+ arrIncludes: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: Array<unknown>) => boolean) & {
255
672
  autoRemove: (val: any) => boolean;
256
673
  };
257
- arrIncludesAll: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValue: Array<unknown>) => boolean) & {
674
+ arrIncludesAll: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: Array<unknown>) => boolean) & {
258
675
  autoRemove: (val: any) => boolean;
259
676
  };
260
- arrHas: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValue: Array<unknown>) => boolean;
261
- arrIncludesSome: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValue: Array<unknown>) => boolean) & {
677
+ arrHas: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: Array<unknown>) => boolean;
678
+ arrIncludesSome: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: Array<unknown>) => boolean) & {
262
679
  autoRemove: (val: any) => boolean;
263
680
  };
264
- between: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValues: [unknown, unknown]) => boolean) & {
681
+ between: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValues: [unknown, unknown]) => boolean) & {
265
682
  autoRemove: (val: any) => boolean;
266
683
  };
267
- betweenInclusive: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValues: [unknown, unknown]) => boolean) & {
684
+ betweenInclusive: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValues: [unknown, unknown]) => boolean) & {
268
685
  autoRemove: (val: any) => boolean;
269
686
  };
270
- equals: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
687
+ equals: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
271
688
  autoRemove: (val: any) => boolean;
272
689
  };
273
- equalsString: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
690
+ equalsString: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
274
691
  autoRemove: (val: any) => boolean;
275
692
  };
276
- inNumberRange: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValue: [number, number]) => boolean) & {
693
+ inNumberRange: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: [number, number]) => boolean) & {
277
694
  resolveFilterValue: (val: [any, any]) => readonly [number, number];
278
695
  autoRemove: (val: any) => boolean;
279
696
  };
280
- includesString: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
697
+ includesString: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
281
698
  autoRemove: (val: any) => boolean;
282
699
  };
283
- includesStringSensitive: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
700
+ includesStringSensitive: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
284
701
  autoRemove: (val: any) => boolean;
285
702
  };
286
- weakEquals: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
703
+ weakEquals: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: unknown) => boolean) & {
287
704
  autoRemove: (val: any) => boolean;
288
705
  };
289
706
  tmDataGrid: typeof tmDataGridFilterFn;
290
707
  };
291
708
  sortFns: {
292
- alphanumeric: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData>, rowB: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string) => number;
293
- alphanumericCaseSensitive: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData>, rowB: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string) => number;
294
- basic: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData>, rowB: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string) => 0 | 1 | -1;
295
- datetime: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData>, rowB: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string) => 0 | 1 | -1;
296
- text: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData>, rowB: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string) => 0 | 1 | -1;
297
- textCaseSensitive: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData>, rowB: import("@tanstack/table-core").Row<TFeatures, TData>, columnId: string) => 0 | 1 | -1;
709
+ alphanumeric: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: Row<TFeatures, TData>, rowB: Row<TFeatures, TData>, columnId: string) => number;
710
+ alphanumericCaseSensitive: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: Row<TFeatures, TData>, rowB: Row<TFeatures, TData>, columnId: string) => number;
711
+ basic: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: Row<TFeatures, TData>, rowB: Row<TFeatures, TData>, columnId: string) => 0 | 1 | -1;
712
+ datetime: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: Row<TFeatures, TData>, rowB: Row<TFeatures, TData>, columnId: string) => 0 | 1 | -1;
713
+ text: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: Row<TFeatures, TData>, rowB: Row<TFeatures, TData>, columnId: string) => 0 | 1 | -1;
714
+ textCaseSensitive: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData extends RowData>(rowA: Row<TFeatures, TData>, rowB: Row<TFeatures, TData>, columnId: string) => 0 | 1 | -1;
715
+ };
716
+ aggregationFns: {
717
+ sum: typeof import("@tanstack/table-core").aggregationFn_sum;
718
+ min: typeof import("@tanstack/table-core").aggregationFn_min;
719
+ max: typeof import("@tanstack/table-core").aggregationFn_max;
720
+ extent: typeof import("@tanstack/table-core").aggregationFn_extent;
721
+ mean: typeof import("@tanstack/table-core").aggregationFn_mean;
722
+ median: typeof import("@tanstack/table-core").aggregationFn_median;
723
+ unique: typeof import("@tanstack/table-core").aggregationFn_unique;
724
+ uniqueCount: typeof import("@tanstack/table-core").aggregationFn_uniqueCount;
725
+ count: typeof import("@tanstack/table-core").aggregationFn_count;
298
726
  };
299
727
  tableMeta: TMDataGridTableMeta;
300
728
  columnMeta: TMDataGridColumnMeta;
@@ -313,61 +741,83 @@ declare function createTMDataGridColumnHelper<TData extends RowData>(): import("
313
741
  columnSizingFeature: import("@tanstack/table-core").TableFeature;
314
742
  columnResizingFeature: import("@tanstack/table-core").TableFeature;
315
743
  columnFacetingFeature: import("@tanstack/table-core").TableFeature;
744
+ columnGroupingFeature: import("@tanstack/table-core").TableFeature;
745
+ rowExpandingFeature: import("@tanstack/table-core").TableFeature;
316
746
  filteredRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
747
+ groupedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
317
748
  sortedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
749
+ expandedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
318
750
  paginatedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
319
751
  facetedRowModel: (table: Table<any, any>, columnId: string) => () => import("@tanstack/table-core").RowModel<any, any>;
320
752
  facetedMinMaxValues: (table: Table<import("@tanstack/table-core").TableFeatures, any>, columnId: string) => () => undefined | [number, number];
321
753
  facetedUniqueValues: (table: Table<import("@tanstack/table-core").TableFeatures, any>, columnId: string) => () => Map<any, number>;
322
754
  filterFns: {
323
- arrIncludes: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValue: Array<unknown>) => boolean) & {
755
+ arrIncludes: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValue: Array<unknown>) => boolean) & {
324
756
  autoRemove: (val: any) => boolean;
325
757
  };
326
- arrIncludesAll: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValue: Array<unknown>) => boolean) & {
758
+ arrIncludesAll: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValue: Array<unknown>) => boolean) & {
327
759
  autoRemove: (val: any) => boolean;
328
760
  };
329
- arrHas: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValue: Array<unknown>) => boolean;
330
- arrIncludesSome: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValue: Array<unknown>) => boolean) & {
761
+ arrHas: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValue: Array<unknown>) => boolean;
762
+ arrIncludesSome: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValue: Array<unknown>) => boolean) & {
331
763
  autoRemove: (val: any) => boolean;
332
764
  };
333
- between: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValues: [unknown, unknown]) => boolean) & {
765
+ between: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValues: [unknown, unknown]) => boolean) & {
334
766
  autoRemove: (val: any) => boolean;
335
767
  };
336
- betweenInclusive: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValues: [unknown, unknown]) => boolean) & {
768
+ betweenInclusive: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValues: [unknown, unknown]) => boolean) & {
337
769
  autoRemove: (val: any) => boolean;
338
770
  };
339
- equals: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValue: unknown) => boolean) & {
771
+ equals: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValue: unknown) => boolean) & {
340
772
  autoRemove: (val: any) => boolean;
341
773
  };
342
- equalsString: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValue: unknown) => boolean) & {
774
+ equalsString: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValue: unknown) => boolean) & {
343
775
  autoRemove: (val: any) => boolean;
344
776
  };
345
- inNumberRange: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValue: [number, number]) => boolean) & {
777
+ inNumberRange: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValue: [number, number]) => boolean) & {
346
778
  resolveFilterValue: (val: [any, any]) => readonly [number, number];
347
779
  autoRemove: (val: any) => boolean;
348
780
  };
349
- includesString: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValue: unknown) => boolean) & {
781
+ includesString: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValue: unknown) => boolean) & {
350
782
  autoRemove: (val: any) => boolean;
351
783
  };
352
- includesStringSensitive: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValue: unknown) => boolean) & {
784
+ includesStringSensitive: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValue: unknown) => boolean) & {
353
785
  autoRemove: (val: any) => boolean;
354
786
  };
355
- weakEquals: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string, filterValue: unknown) => boolean) & {
787
+ weakEquals: (<TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(row: Row<TFeatures, TData_1>, columnId: string, filterValue: unknown) => boolean) & {
356
788
  autoRemove: (val: any) => boolean;
357
789
  };
358
790
  tmDataGrid: typeof tmDataGridFilterFn;
359
791
  };
360
792
  sortFns: {
361
- alphanumeric: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData_1>, rowB: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string) => number;
362
- alphanumericCaseSensitive: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData_1>, rowB: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string) => number;
363
- basic: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData_1>, rowB: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string) => 0 | 1 | -1;
364
- datetime: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData_1>, rowB: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string) => 0 | 1 | -1;
365
- text: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData_1>, rowB: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string) => 0 | 1 | -1;
366
- textCaseSensitive: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: import("@tanstack/table-core").Row<TFeatures, TData_1>, rowB: import("@tanstack/table-core").Row<TFeatures, TData_1>, columnId: string) => 0 | 1 | -1;
793
+ alphanumeric: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: Row<TFeatures, TData_1>, rowB: Row<TFeatures, TData_1>, columnId: string) => number;
794
+ alphanumericCaseSensitive: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: Row<TFeatures, TData_1>, rowB: Row<TFeatures, TData_1>, columnId: string) => number;
795
+ basic: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: Row<TFeatures, TData_1>, rowB: Row<TFeatures, TData_1>, columnId: string) => 0 | 1 | -1;
796
+ datetime: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: Row<TFeatures, TData_1>, rowB: Row<TFeatures, TData_1>, columnId: string) => 0 | 1 | -1;
797
+ text: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: Row<TFeatures, TData_1>, rowB: Row<TFeatures, TData_1>, columnId: string) => 0 | 1 | -1;
798
+ textCaseSensitive: <TFeatures extends import("@tanstack/table-core").TableFeatures, TData_1 extends RowData>(rowA: Row<TFeatures, TData_1>, rowB: Row<TFeatures, TData_1>, columnId: string) => 0 | 1 | -1;
799
+ };
800
+ aggregationFns: {
801
+ sum: typeof import("@tanstack/table-core").aggregationFn_sum;
802
+ min: typeof import("@tanstack/table-core").aggregationFn_min;
803
+ max: typeof import("@tanstack/table-core").aggregationFn_max;
804
+ extent: typeof import("@tanstack/table-core").aggregationFn_extent;
805
+ mean: typeof import("@tanstack/table-core").aggregationFn_mean;
806
+ median: typeof import("@tanstack/table-core").aggregationFn_median;
807
+ unique: typeof import("@tanstack/table-core").aggregationFn_unique;
808
+ uniqueCount: typeof import("@tanstack/table-core").aggregationFn_uniqueCount;
809
+ count: typeof import("@tanstack/table-core").aggregationFn_count;
367
810
  };
368
811
  tableMeta: TMDataGridTableMeta;
369
812
  columnMeta: TMDataGridColumnMeta;
370
813
  }, TData>;
814
+ /** What the `renderDetails` render prop is handed for an expanded row. */
815
+ type TMDataGridDetailsArgs<TData extends RowData> = {
816
+ row: Row<TMDataGridFeatures, TData>;
817
+ table: TMDataGridTable<TData>;
818
+ };
819
+ /** Builds the panel shown underneath an expanded row. See `renderDetails`. */
820
+ type TMDataGridDetailsRenderer<TData extends RowData> = (args: TMDataGridDetailsArgs<TData>) => ReactNode;
371
821
  /**
372
822
  * Chrome state that is *not* table state: which panels are open, and which
373
823
  * column opened the filter panel. Kept in a TanStack Store so consumers can
@@ -383,6 +833,39 @@ type TMDataGridUiState = {
383
833
  * `dataTransfer`, which browsers keep unreadable until the drop.
384
834
  */
385
835
  draggedColumnId: string | null;
836
+ /**
837
+ * The single highlighted row — the one a detail panel would be showing. Its
838
+ * own concept, not a slice of `rowSelection`: under
839
+ * `selectionMode: "checkboxAndHighlight"` the two coexist, and TanStack's one
840
+ * selection map cannot hold both.
841
+ *
842
+ * Not pruned when the row is filtered out, paged away or dropped from `data`,
843
+ * matching how TanStack treats `rowSelection` — nothing there resets it
844
+ * either. The row simply renders unhighlighted, and highlights again if it
845
+ * comes back.
846
+ */
847
+ highlightedRowId: string | null;
848
+ /** The pivot a shift-click extends from. See resolveRowSelectionClick. */
849
+ selectionAnchorRowId: string | null;
850
+ /**
851
+ * The cell the keyboard is on, under `enableCellSelection`. `null` until the
852
+ * grid is first entered — and again whenever a consumer clears it.
853
+ *
854
+ * The state is the source of truth and DOM focus follows it, not the other
855
+ * way around: under virtualization the cell it names is often not mounted,
856
+ * which is exactly what a coordinate has to survive. Held as ids for the
857
+ * same reason — see {@link TMDataGridCellPosition}.
858
+ */
859
+ focusedCell: TMDataGridCellPosition | null;
860
+ /**
861
+ * The selected rectangle, under `cellSelection: "range"`. Held as the two
862
+ * cells that span it — see {@link TMDataGridCellRange}.
863
+ *
864
+ * Always covers the focused cell: every gesture that moves the focus either
865
+ * extends the rectangle or collapses it onto the new cell, so the two never
866
+ * describe different places.
867
+ */
868
+ cellRange: TMDataGridCellRange | null;
386
869
  };
387
870
  type TMDataGridUiActions = {
388
871
  openFilterPanel: (columnId?: string | null) => void;
@@ -391,6 +874,25 @@ type TMDataGridUiActions = {
391
874
  toggleColumnsPanel: () => void;
392
875
  startColumnDrag: (columnId: string) => void;
393
876
  endColumnDrag: () => void;
877
+ /**
878
+ * Moves the active row, or clears it with `null` — which is how a consumer
879
+ * closing its detail panel puts the grid back in step.
880
+ */
881
+ setHighlightedRow: (rowId: string | null) => void;
882
+ setSelectionAnchor: (rowId: string | null) => void;
883
+ /**
884
+ * Moves the focused cell, or clears it with `null`. DOM focus follows while
885
+ * the grid holds it — so this both moves the keyboard and, when the row is
886
+ * off screen, scrolls it into view. Called for every arrow key, and available
887
+ * for a consumer putting the keyboard somewhere itself.
888
+ */
889
+ setFocusedCell: (cell: TMDataGridCellPosition | null) => void;
890
+ /**
891
+ * Sets the selected rectangle, or clears it with `null`. Does not move the
892
+ * focused cell — the two are set together by the gestures that change both,
893
+ * which is what keeps "extend the selection" and "move the cursor" separable.
894
+ */
895
+ setCellRange: (range: TMDataGridCellRange | null) => void;
394
896
  };
395
897
  type TMDataGridUiStore = Store<TMDataGridUiState, TMDataGridUiActions>;
396
898
  /** What `useTMDataGrid` returns — spread straight onto `<TMDataGrid />`. */
@@ -399,6 +901,14 @@ type TMDataGridApi<TData extends RowData> = {
399
901
  ui: TMDataGridUiStore;
400
902
  /** Table-level feature switches, re-read from options on every render. */
401
903
  features: TMDataGridFeatureFlags;
904
+ /** Every string the chrome renders, `labels` merged over the English defaults. */
905
+ labels: TMDataGridLabels;
906
+ /** The detail renderer, when row details are on. See `renderDetails`. */
907
+ renderDetails?: TMDataGridDetailsRenderer<TData>;
908
+ /** Detail estimate in px: the option, or {@link DEFAULT_DETAILS_EST_HEIGHT}. */
909
+ renderDetailsEstHeight: number;
910
+ /** Virtualizer overscan: the option, or {@link DEFAULT_OVERSCAN}. */
911
+ overscan: number;
402
912
  };
403
913
  type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridFeatures, TData>, "features"> & {
404
914
  /**
@@ -409,6 +919,20 @@ type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridF
409
919
  * dependency of the subscription that writes back.
410
920
  */
411
921
  persist?: TMDataGridPersistence;
922
+ /**
923
+ * Overrides for the grid's strings — menu items, panels, the pager, and
924
+ * every `aria-label`. Any subset, merged over the English defaults; a full
925
+ * Swedish dictionary ships as `TMDATAGRID_LABELS_SV`.
926
+ *
927
+ * ```tsx
928
+ * useTMDataGrid({ data, columns, labels: TMDATAGRID_LABELS_SV });
929
+ * useTMDataGrid({ data, columns, labels: { noResults: "Inga rader" } });
930
+ * ```
931
+ *
932
+ * Keep the object referentially stable (module scope or `useMemo`) — the
933
+ * chrome re-renders when its identity changes.
934
+ */
935
+ labels?: TMDataGridLabelsOverride;
412
936
  /**
413
937
  * Header drag-and-drop and the move items in the column menu. Defaults to
414
938
  * `true`.
@@ -431,18 +955,29 @@ type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridF
431
955
  /**
432
956
  * How rows are selected. Defaults to `"checkbox"`.
433
957
  *
434
- * - `"checkbox"` — the generated checkbox column selects; clicking a row
435
- * elsewhere does not.
436
- * - `"row"` — no checkbox column; clicking a row toggles it. Other rows keep
437
- * their state, so a click never clears the rest of the selection.
958
+ * | Mode | Checkbox column | Row click |
959
+ * | ---- | --------------- | --------- |
960
+ * | `"checkbox"` | yes, multi-select | nothing |
961
+ * | `"row"` | no | multi-selects, Ctrl/Shift modifiers |
962
+ * | `"checkboxAndHighlight"` | yes, multi-select | highlights one row |
963
+ * | `"highlight"` | no | highlights one row, no selection at all |
964
+ *
965
+ * One option rather than two, so the combination that cannot work — a click
966
+ * that both toggles a multi-selection and moves the highlight — is not
967
+ * expressible.
438
968
  *
439
- * Ignored when `enableRowSelection` is `false`. Both modes write to the same
440
- * `rowSelection` state.
969
+ * The first two write to TanStack's `rowSelection`. The highlight is separate
970
+ * state, which is what lets `"checkboxAndHighlight"` run both at once: tick
971
+ * rows for a bulk action, click one to open its detail panel. See
972
+ * `defaultHighlightedRowId` / `onHighlightedRowChange`.
973
+ *
974
+ * `enableRowSelection` still gates the selection half, predicate form
975
+ * included; under `"highlight"` there is nothing for it to gate.
441
976
  */
442
- rowSelectionMode?: TMDataGridRowSelectionMode;
977
+ selectionMode?: TMDataGridSelectionMode;
443
978
  /**
444
979
  * Give selected rows the highlight background. Defaults to `true` under
445
- * `rowSelectionMode: "row"`, where the highlight is the only feedback a click
980
+ * `selectionMode: "row"`, where the highlight is the only feedback a click
446
981
  * gives, and `false` under `"checkbox"`, where the box already shows it.
447
982
  *
448
983
  * The colour is the `--dg-row-selected-bg` CSS variable, so it can be changed
@@ -455,7 +990,138 @@ type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridF
455
990
  * />
456
991
  * ```
457
992
  */
458
- highlightSelectedRows?: boolean;
993
+ showSelectedBackground?: boolean;
994
+ /**
995
+ * The row that starts out highlighted, under a `selectionMode` that has a
996
+ * highlight. Read once on mount, like `initialState`.
997
+ *
998
+ * The grid never persists the highlighted row. Pair this with
999
+ * {@link onHighlightedRowChange} and keep it wherever it belongs — for a
1000
+ * detail panel that is usually the route, which gets you a shareable link and
1001
+ * a working back button as well as surviving a reload:
1002
+ *
1003
+ * ```tsx
1004
+ * const { rowId } = useParams();
1005
+ * useTMDataGrid({
1006
+ * selectionMode: "highlight",
1007
+ * defaultHighlightedRowId: rowId,
1008
+ * onHighlightedRowChange: (id) => navigate(id ? `/employees/${id}` : "/employees"),
1009
+ * });
1010
+ * ```
1011
+ */
1012
+ defaultHighlightedRowId?: string | null;
1013
+ /**
1014
+ * Called with the newly highlighted row id, or `null` when it is cleared.
1015
+ * Fires for `ui.actions.setHighlightedRow` too, not only for clicks.
1016
+ */
1017
+ onHighlightedRowChange?: (rowId: string | null) => void;
1018
+ /**
1019
+ * How cells are selected. Defaults to `"none"`.
1020
+ *
1021
+ * | Mode | What it gives |
1022
+ * | ---- | ------------- |
1023
+ * | `"none"` | nothing; the body's tab stop stays on the row |
1024
+ * | `"single"` | one focused cell, moved with the arrow keys |
1025
+ * | `"range"` | as `"single"`, plus a rectangle of cells |
1026
+ *
1027
+ * Under either live mode:
1028
+ *
1029
+ * | Key | Moves to |
1030
+ * | --- | --- |
1031
+ * | Arrows | the neighbouring cell, clamped at the edges |
1032
+ * | PageUp / PageDown | one viewport of rows |
1033
+ * | Home / End | first / last cell of the row |
1034
+ * | Ctrl+Home / Ctrl+End | first / last cell of the grid |
1035
+ * | Enter or F2 | into the cell — the checkbox, link or button it holds |
1036
+ * | Escape | back out to the cell |
1037
+ * | Space | selects the row, as it does in row-selection mode |
1038
+ *
1039
+ * And under `"range"`, additionally:
1040
+ *
1041
+ * | Gesture | Does |
1042
+ * | ------- | ---- |
1043
+ * | Drag across cells | selects the rectangle they span |
1044
+ * | Shift+click, Shift+arrows | extends the rectangle from its anchor |
1045
+ * | Ctrl+C | copies it as tab-separated text — paste lands in Excel's cells |
1046
+ * | Right-click inside it | offers the CSV export, headers optional |
1047
+ *
1048
+ * Off, nothing about the body changes. On, three things do: the body's tab
1049
+ * stop moves from the row to a cell, so the whole grid is one Tab stop; the
1050
+ * grid reports itself as a `grid` of `gridcell`s rather than a `table` of
1051
+ * `cell`s, which is what tells a screen reader the arrow keys are live; and
1052
+ * the cells take `data-focused` / `data-selected` for the ring and the tint.
1053
+ *
1054
+ * The state is `ui.state.focusedCell` and `ui.state.cellRange`, and moving it
1055
+ * is `ui.actions.setFocusedCell` / `setCellRange` — so a consumer can put the
1056
+ * keyboard on a cell, or follow it:
1057
+ *
1058
+ * ```tsx
1059
+ * const grid = useTMDataGrid({
1060
+ * data,
1061
+ * columns,
1062
+ * cellSelection: "range",
1063
+ * onFocusedCellChange: (cell) => setStatus(cell?.columnId ?? ""),
1064
+ * });
1065
+ * ```
1066
+ *
1067
+ * Ids rather than a row/column index pair, so sorting, filtering and column
1068
+ * reordering move the selection with the cells instead of leaving it over
1069
+ * whatever slid into those positions.
1070
+ */
1071
+ cellSelection?: TMDataGridCellSelectionMode;
1072
+ /**
1073
+ * Called with the newly focused cell, or `null` when it is cleared. Fires for
1074
+ * `ui.actions.setFocusedCell` too, not only for keys and clicks.
1075
+ */
1076
+ onFocusedCellChange?: (cell: TMDataGridCellPosition | null) => void;
1077
+ /**
1078
+ * Renders a panel underneath an expanded row, spanning every column. Setting
1079
+ * it is what turns row details on.
1080
+ *
1081
+ * Which rows are open is TanStack's own `expanded` state, so opening one is
1082
+ * `row.toggleExpanded()` from wherever suits — a chevron in a cell, a button
1083
+ * in the context menu, a double-click:
1084
+ *
1085
+ * ```tsx
1086
+ * const grid = useTMDataGrid({
1087
+ * data,
1088
+ * columns,
1089
+ * renderDetails: ({ row }) => <EmployeeCard employee={row.original} />,
1090
+ * });
1091
+ * ```
1092
+ *
1093
+ * The panel is as tall as what it renders — see {@link renderDetailsEstHeight}
1094
+ * for what the virtualizer assumes before it has measured one.
1095
+ *
1096
+ * Group rows are left out: expanding one opens its children, and a panel there
1097
+ * would be about an arbitrary one of them. The same reason they sit out
1098
+ * `onRowClick`.
1099
+ *
1100
+ * Row details and `selectionMode: "highlight"` are two answers to the same
1101
+ * question. Details keep the record in place and in context, which suits a few
1102
+ * fields or an action strip; a highlight-driven side panel has room for more
1103
+ * and survives scrolling. Nothing stops a grid from doing both.
1104
+ */
1105
+ renderDetails?: TMDataGridDetailsRenderer<TData>;
1106
+ /**
1107
+ * What the virtualizer assumes an unmeasured detail panel is worth, in px.
1108
+ * Defaults to 160.
1109
+ *
1110
+ * An estimate, not a height: every mounted row is measured, so the real one
1111
+ * takes over as soon as the panel is on screen. It keeps the scrollbar honest
1112
+ * for panels that open off screen — restored `expanded` state, say — and being
1113
+ * roughly right is enough.
1114
+ */
1115
+ renderDetailsEstHeight?: number;
1116
+ /**
1117
+ * Rows the virtualizer keeps mounted above and below the viewport. Defaults
1118
+ * to 6.
1119
+ *
1120
+ * Raise it to trade memory for a scroll that stays painted — fast wheel or
1121
+ * touch flings can outrun the virtualizer and flash blank rows, and a larger
1122
+ * buffer covers the gap. Lower it when rows are expensive to render.
1123
+ */
1124
+ overscan?: number;
459
1125
  };
460
1126
  /**
461
1127
  * Builds a TMDataGrid table plus its chrome store.
@@ -468,13 +1134,50 @@ type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridF
468
1134
  * flag on, so `<TMDataGrid.Footer />` renders its pager without further
469
1135
  * options.
470
1136
  */
471
- declare function useTMDataGrid<TData extends RowData>({ persist, enableColumnOrdering, enablePagination, rowSelectionMode, highlightSelectedRows, ...options }: UseTMDataGridOptions<TData>): TMDataGridApi<TData>;
1137
+ declare function useTMDataGrid<TData extends RowData>({ persist, labels: labelsOverride, enableColumnOrdering, enablePagination, selectionMode, showSelectedBackground, defaultHighlightedRowId, onHighlightedRowChange, cellSelection, onFocusedCellChange, renderDetails, renderDetailsEstHeight, overscan, ...options }: UseTMDataGridOptions<TData>): TMDataGridApi<TData>;
472
1138
  /**
473
1139
  * Opens the filter panel for a column, seeding an empty filter row when the
474
1140
  * column has none yet — mirrors "Filter" in the column header menu.
475
1141
  */
476
1142
  declare function openColumnFilter<TData extends RowData>(api: TMDataGridApi<TData>, columnId: string): void;
477
1143
  //#endregion
1144
+ //#region .types-tmp/components/TMDataGridFilterPills.d.ts
1145
+ type TMDataGridFilterPillsProps<TData extends RowData> = {
1146
+ /** The object returned by `useTMDataGrid`. */
1147
+ api: TMDataGridApi<TData>;
1148
+ /** Mantine size of the pills. Defaults to `"sm"`. */
1149
+ size?: TMDataGridSize;
1150
+ /** "Clear all" button, shown once two filters are active. Defaults to `true`. */
1151
+ showClearAll?: boolean;
1152
+ /**
1153
+ * Replaces what a click on a pill's label does. The default opens the grid's
1154
+ * filter panel on that column.
1155
+ */
1156
+ onPillClick?: (columnId: string) => void;
1157
+ className?: string;
1158
+ };
1159
+ /**
1160
+ * One pill per active filter — `First name: Sofia ✕` — with the ✕ clearing that
1161
+ * filter and a click on the label opening the filter panel on its column.
1162
+ *
1163
+ * The one grid component that takes the api as a prop instead of reading
1164
+ * context, so it can live anywhere: a page header, a card title, a breadcrumb
1165
+ * row. Renders nothing while no filter is active.
1166
+ *
1167
+ * ```tsx
1168
+ * const grid = useTMDataGrid({ data, columns });
1169
+ *
1170
+ * <Group>
1171
+ * <Title order={3}>Employees</Title>
1172
+ * <TMDataGridFilterPills api={grid} />
1173
+ * </Group>
1174
+ * ```
1175
+ *
1176
+ * Half-typed filters are left out: a filter that is not narrowing the rows yet
1177
+ * has nothing to report, which is the same rule the funnel indicator uses.
1178
+ */
1179
+ declare function TMDataGridFilterPills<TData extends RowData>({ api, size, showClearAll, onPillClick, className }: TMDataGridFilterPillsProps<TData>): import("react").JSX.Element | null;
1180
+ //#endregion
478
1181
  //#region .types-tmp/components/TMDataGridFooter.d.ts
479
1182
  /** Distilled pagination state and actions for building a custom pager. */
480
1183
  type TMDataGridPaginationApi = {
@@ -515,6 +1218,171 @@ type TMDataGridFooterProps = {
515
1218
  */
516
1219
  declare function TMDataGridFooter({ pageSizeOptions, pagination }: TMDataGridFooterProps): import("react").JSX.Element | null;
517
1220
  //#endregion
1221
+ //#region .types-tmp/components/TMDataGridSearch.d.ts
1222
+ type TMDataGridSearchProps = {
1223
+ /** Defaults to `labels.searchPlaceholder`. */
1224
+ placeholder?: string;
1225
+ /**
1226
+ * How long typing pauses before the filter is applied, in ms. Defaults to
1227
+ * 250. `0` writes on every keystroke — what the tests use, and fine for
1228
+ * small client-side data sets.
1229
+ */
1230
+ debounce?: number;
1231
+ /** Width of the input. Defaults to 220. */
1232
+ w?: number | string;
1233
+ };
1234
+ /**
1235
+ * Quick search over every column — a debounced input writing the table's
1236
+ * `globalFilter` state through the `"includesString"` filter the grid
1237
+ * configures by default.
1238
+ *
1239
+ * ```tsx
1240
+ * <TMDataGrid.Toolbar>
1241
+ * <TMDataGrid.Search />
1242
+ * <TMDataGrid.Spacer />
1243
+ * <TMDataGrid.FilterButton />
1244
+ * </TMDataGrid.Toolbar>
1245
+ * ```
1246
+ *
1247
+ * Renders nothing under `enableGlobalFilter: false`. Columns opt out with
1248
+ * their own `enableGlobalFilter: false` — the generated lanes already do.
1249
+ *
1250
+ * The state is TanStack's `globalFilter`, so everything around it comes free:
1251
+ * `manualFiltering` grids forward it to the server, and it is one of the
1252
+ * persisted `data` slices. A grid that wants its own input entirely writes
1253
+ * `table.setGlobalFilter` itself — this component is only the built-in one.
1254
+ */
1255
+ declare function TMDataGridSearch({ placeholder, debounce, w }: TMDataGridSearchProps): import("react").JSX.Element | null;
1256
+ //#endregion
1257
+ //#region .types-tmp/core/cellExport.d.ts
1258
+ /** The selected block, flattened to text. One inner array per row. */
1259
+ type TMDataGridCellMatrix = Array<Array<string>>;
1260
+ /**
1261
+ * How values are written out.
1262
+ *
1263
+ * The defaults are the Nordic ones, because they are the ones that need
1264
+ * choosing: an Excel running a Swedish, Norwegian, Danish or Finnish locale
1265
+ * reads `;` as its list separator and `,` as its decimal mark, and a file
1266
+ * written the other way opens as one column of text. Both are settable for a
1267
+ * grid whose users run something else.
1268
+ */
1269
+ type TMDataGridCellExportOptions = {
1270
+ /** CSV field separator. Defaults to `";"`. */
1271
+ separator?: string;
1272
+ /** Write numbers as `1,5` rather than `1.5`. Defaults to `true`. */
1273
+ decimalComma?: boolean;
1274
+ /** Column labels as the first row. Defaults to `true`. */
1275
+ includeHeaders?: boolean;
1276
+ /** Without extension. Defaults to `"export"`. */
1277
+ fileName?: string;
1278
+ };
1279
+ type ResolvedExportOptions = Required<TMDataGridCellExportOptions>;
1280
+ declare const DEFAULT_CELL_EXPORT_OPTIONS: ResolvedExportOptions;
1281
+ /**
1282
+ * One value as text.
1283
+ *
1284
+ * Deliberately not the rendered cell: what a cell renders is React, and often a
1285
+ * badge, a link or an icon rather than the value. The value is what a
1286
+ * spreadsheet wants, and it is the one thing every column is guaranteed to
1287
+ * have.
1288
+ */
1289
+ declare function formatExportValue(value: unknown, { decimalComma }: {
1290
+ decimalComma: boolean;
1291
+ }): string;
1292
+ type BuildCellMatrixArgs = {
1293
+ rows: ReadonlyArray<Row<TMDataGridFeatures, TMDataGridRowData>>;
1294
+ /** Every visible column, in render order — the same list the bounds index into. */
1295
+ columns: ReadonlyArray<Column<TMDataGridFeatures, TMDataGridRowData, unknown>>;
1296
+ bounds: TMDataGridRangeBounds;
1297
+ includeHeaders: boolean;
1298
+ decimalComma: boolean;
1299
+ };
1300
+ /**
1301
+ * The selected rectangle as rows of text.
1302
+ *
1303
+ * The generated lanes — the checkbox, the tree chevron, the details chevron —
1304
+ * are dropped even when the rectangle covers them. They hold controls rather
1305
+ * than data, so a column of empty strings is all they could contribute, and
1306
+ * pasting one into a spreadsheet only shifts everything to its right.
1307
+ */
1308
+ declare function buildCellMatrix({ rows, columns, bounds, includeHeaders, decimalComma }: BuildCellMatrixArgs): TMDataGridCellMatrix;
1309
+ /**
1310
+ * The whole grid as rows of text: every filtered and sorted data row — all
1311
+ * pages, not the one on screen — by every visible non-control column, in
1312
+ * render order.
1313
+ *
1314
+ * The values are the same ones a cell-range export writes; only the bounds
1315
+ * differ. Group rows are left out (their records are the rows themselves),
1316
+ * and hidden columns are not exported — what you see is what you get, minus
1317
+ * paging.
1318
+ */
1319
+ declare function buildGridCellMatrix<TData extends RowData>({ table, includeHeaders, decimalComma }: {
1320
+ table: TMDataGridTable<TData>;
1321
+ includeHeaders?: boolean;
1322
+ decimalComma?: boolean;
1323
+ }): TMDataGridCellMatrix;
1324
+ /**
1325
+ * Downloads the whole grid as a CSV for Excel — {@link buildGridCellMatrix}
1326
+ * through {@link toExcelCsv}, with the same Nordic defaults and overrides as
1327
+ * the cell-range export.
1328
+ *
1329
+ * No built-in button: wire it to your own toolbar.
1330
+ *
1331
+ * ```tsx
1332
+ * <Button onClick={() => exportGridToCsv({ table: grid.table })}>Export</Button>
1333
+ * ```
1334
+ */
1335
+ declare function exportGridToCsv<TData extends RowData>({ table, options }: {
1336
+ table: TMDataGridTable<TData>;
1337
+ options?: TMDataGridCellExportOptions;
1338
+ }): void;
1339
+ /**
1340
+ * The clipboard format spreadsheets read: tab between cells, CRLF between rows.
1341
+ *
1342
+ * Tabs rather than commas because that is what Excel, Sheets and Numbers all
1343
+ * put on the clipboard themselves — paste it and the cells land in cells. A
1344
+ * comma-separated string pastes into a single column, which is the thing this
1345
+ * exists to avoid.
1346
+ */
1347
+ declare function toClipboardText(matrix: TMDataGridCellMatrix): string;
1348
+ /**
1349
+ * A CSV that opens straight into columns in Excel.
1350
+ *
1351
+ * Three things make that true, and all three are needed:
1352
+ *
1353
+ * | Part | Why |
1354
+ * | ---- | --- |
1355
+ * | `sep=;` first line | Excel's own directive — it stops guessing and uses this |
1356
+ * | UTF-8 BOM | without it Excel reads the file as ANSI, and å ä ö arrive broken |
1357
+ * | CRLF line endings | what Excel writes, and what its importer is happiest with |
1358
+ *
1359
+ * The `sep=` line is Excel's alone; other readers show it as a first row. That
1360
+ * is the trade this makes — the file is for Excel, and "it just opens" is worth
1361
+ * more than being a well-behaved CSV nobody was going to feed to a parser.
1362
+ */
1363
+ declare function toExcelCsv(matrix: TMDataGridCellMatrix, { separator }: {
1364
+ separator: string;
1365
+ }): string;
1366
+ /**
1367
+ * Puts text on the clipboard, reporting whether it landed.
1368
+ *
1369
+ * The async clipboard API only resolves for a document that has the focus and a
1370
+ * user gesture behind it — both true when this runs off Ctrl+C or a menu item.
1371
+ * It is still allowed to reject (a permissions policy, a page that lost focus
1372
+ * mid-copy), so the result is a boolean rather than a promise nobody checks.
1373
+ */
1374
+ declare function writeClipboardText(text: string): Promise<boolean>;
1375
+ /**
1376
+ * Downloads text as a file, through the one mechanism a library can use: an
1377
+ * anchor with an object URL behind it, clicked. Revoked on the next frame —
1378
+ * immediately would race the browser's own read of it.
1379
+ */
1380
+ declare function downloadTextFile({ fileName, text, mimeType }: {
1381
+ fileName: string;
1382
+ text: string;
1383
+ mimeType?: string;
1384
+ }): void;
1385
+ //#endregion
518
1386
  //#region .types-tmp/components/TMDataGridTable.d.ts
519
1387
  /** Where a column sits relative to the pinned regions, resolved once per render. */
520
1388
  type TMDataGridColumnLayout = {
@@ -524,12 +1392,117 @@ type TMDataGridColumnLayout = {
524
1392
  /** Last left-pinned / first right-pinned column — the one that casts the edge. */
525
1393
  isBoundary: boolean;
526
1394
  };
1395
+ /**
1396
+ * What a cell needs to take part in cell selection, or `undefined` while the
1397
+ * feature is off — which is what keeps a plain grid's cells exactly as they
1398
+ * were: no tab stop, no `gridcell` role, no coordinates in the DOM.
1399
+ *
1400
+ * The coordinates are there for the delegated key handler, which reads them off
1401
+ * `event.target` rather than closing over per-cell state, and for the effect
1402
+ * that puts DOM focus where {@link TMDataGridUiState.focusedCell} says.
1403
+ */
1404
+ type TMDataGridCellNav = {
1405
+ rowId: string;
1406
+ /** 1-based, for `aria-colindex`. */
1407
+ columnIndex: number;
1408
+ focused: boolean;
1409
+ /** The roving tab stop: `0` on exactly one mounted cell, `-1` on the rest. */
1410
+ tabIndex: 0 | -1;
1411
+ /** Inside the selected rectangle. Always `false` under `"single"`. */
1412
+ selected: boolean;
1413
+ /**
1414
+ * Which sides of the rectangle this cell is on, or `null` when it is not in
1415
+ * one. The outline is drawn per cell — see {@link boundsEdges}.
1416
+ */
1417
+ edges: {
1418
+ top: boolean;
1419
+ bottom: boolean;
1420
+ left: boolean;
1421
+ right: boolean;
1422
+ } | null;
1423
+ };
1424
+ /** What a `rowContextMenu` render prop is handed for the right-clicked row. */
1425
+ type TMDataGridRowContextMenuArgs<TData extends RowData> = {
1426
+ table: Table<TMDataGridFeatures, TData>;
1427
+ row: Row<TMDataGridFeatures, TData>;
1428
+ /**
1429
+ * The cell under the pointer. `null` only when the right-click landed on the
1430
+ * row but on no cell — which a custom cell renderer that stops propagation
1431
+ * can cause.
1432
+ */
1433
+ cell: Cell<TMDataGridFeatures, TData, unknown> | null;
1434
+ /**
1435
+ * Closes the menu. `Menu.Item` already closes on click (Mantine's
1436
+ * `closeOnItemClick`), so this is for content that isn't a menu item.
1437
+ */
1438
+ close: () => void;
1439
+ };
1440
+ /**
1441
+ * Builds the contents of a row's context menu — `Menu.Item`, `Menu.Label`,
1442
+ * `Menu.Divider`, `Menu.Sub`, or any other node. The grid owns the `Menu` and
1443
+ * its `Menu.Dropdown`; this fills the dropdown.
1444
+ */
1445
+ type TMDataGridRowContextMenu<TData extends RowData> = (args: TMDataGridRowContextMenuArgs<TData>) => ReactNode;
527
1446
  type TMDataGridTableProps<TData extends RowData> = {
528
1447
  /**
529
1448
  * Called when a body row is clicked. Runs in addition to row selection under
530
- * `rowSelectionMode: "row"`, not instead of it.
1449
+ * `selectionMode: "row"`, not instead of it.
531
1450
  */
532
1451
  onRowClick?: (row: Row<TMDataGridFeatures, TData>) => void;
1452
+ /**
1453
+ * Contents of the menu a right-click on a row opens, at the pointer. Return
1454
+ * `null` to leave a row without one — the browser's own menu stays suppressed
1455
+ * either way.
1456
+ *
1457
+ * ```tsx
1458
+ * <TMDataGrid.Table<Employee>
1459
+ * rowContextMenu={({ row, close }) => (
1460
+ * <>
1461
+ * <Menu.Label>{row.original.firstName}</Menu.Label>
1462
+ * <Menu.Item onClick={() => open(row.original.id)}>Open</Menu.Item>
1463
+ * <Menu.Divider />
1464
+ * <Menu.Item color="red" onClick={() => remove(row.original.id)}>
1465
+ * Delete
1466
+ * </Menu.Item>
1467
+ * </>
1468
+ * )}
1469
+ * />
1470
+ * ```
1471
+ *
1472
+ * Called during render, and only for the row whose menu is open — so it stays
1473
+ * a pure function of the row, and cost per row does not matter.
1474
+ */
1475
+ rowContextMenu?: TMDataGridRowContextMenu<TData>;
1476
+ /**
1477
+ * Passed to the Mantine `Menu` the grid wraps the row in — `width`, `shadow`,
1478
+ * `position`, `transitionProps` and the rest. Its open state is the grid's.
1479
+ */
1480
+ rowContextMenuProps?: Omit<MenuProps, "opened" | "onChange" | "children">;
1481
+ /**
1482
+ * How Ctrl+C and the export item write values, under
1483
+ * `cellSelection: "range"`. Defaults to the Nordic Excel conventions — see
1484
+ * {@link TMDataGridCellExportOptions}.
1485
+ */
1486
+ cellExport?: TMDataGridCellExportOptions;
1487
+ /**
1488
+ * Called when the scroll approaches the last row — the infinite-scroll
1489
+ * hook-in. Append the next page to `data` and the virtualizer keeps its
1490
+ * position; fires once per row count, so a pending fetch is not asked
1491
+ * again until it lands.
1492
+ *
1493
+ * ```tsx
1494
+ * <TMDataGrid.Table onReachEnd={() => query.fetchNextPage()} />
1495
+ * ```
1496
+ *
1497
+ * Sorting and filtering must be server-side (`manual*`) on a grid that
1498
+ * loads this way — the client only ever holds a prefix of the data. Not
1499
+ * compatible with `enablePagination`, which slices the same scroll.
1500
+ */
1501
+ onReachEnd?: () => void;
1502
+ /**
1503
+ * How many rows before the end {@link onReachEnd} fires at. Defaults to 10.
1504
+ */
1505
+ reachEndThreshold?: number;
533
1506
  };
534
1507
  /**
535
1508
  * The scrollable grid surface. Always virtualized: only the rows inside the
@@ -537,7 +1510,7 @@ type TMDataGridTableProps<TData extends RowData> = {
537
1510
  * no-pagination mode viable at any row count. Pagination is opt-in via
538
1511
  * `enablePagination` (or implied by `manualPagination`).
539
1512
  */
540
- declare function TMDataGridTable$1<TData extends RowData = TMDataGridRowData>({ onRowClick }: TMDataGridTableProps<TData>): import("react").JSX.Element;
1513
+ declare function TMDataGridTable$1<TData extends RowData = TMDataGridRowData>({ onRowClick, rowContextMenu, rowContextMenuProps, cellExport, onReachEnd, reachEndThreshold }: TMDataGridTableProps<TData>): import("react").JSX.Element;
541
1514
  //#endregion
542
1515
  //#region .types-tmp/components/TMDataGridToolbar.d.ts
543
1516
  /** Row above the grid. Compose it from the pieces below, or anything else. */
@@ -546,6 +1519,24 @@ declare function TMDataGridToolbar({ children }: {
546
1519
  }): import("react").JSX.Element;
547
1520
  /** Pushes the following toolbar items to the right. */
548
1521
  declare function TMDataGridToolbarSpacer(): import("react").JSX.Element;
1522
+ /**
1523
+ * A small spinner shown while `meta.loading` is true, and nothing otherwise.
1524
+ *
1525
+ * The body only shows its loading state while the grid is *empty* — a
1526
+ * server-driven grid refetching with rows on screen keeps showing them, which
1527
+ * is right, but leaves nothing saying a fetch is running. This is that signal,
1528
+ * and the consumer decides where it sits by placing it in the toolbar:
1529
+ *
1530
+ * ```tsx
1531
+ * <TMDataGrid.Toolbar>
1532
+ * <TMDataGrid.SummaryCount />
1533
+ * <TMDataGrid.Spacer />
1534
+ * <TMDataGrid.LoadingIndicator />
1535
+ * <TMDataGrid.FilterButton />
1536
+ * </TMDataGrid.Toolbar>
1537
+ * ```
1538
+ */
1539
+ declare function TMDataGridLoadingIndicator(): import("react").JSX.Element | null;
549
1540
  /**
550
1541
  * Visible rows over total rows. On a server-driven grid, set
551
1542
  * `meta.totalRowCount` for the denominator — the client never sees every row.
@@ -598,17 +1589,24 @@ type TMDataGridProps<TData extends RowData> = TMDataGridApi<TData> & {
598
1589
  * </TMDataGrid>
599
1590
  * ```
600
1591
  */
601
- declare function TMDataGridRoot<TData extends RowData>({ table, ui, features, size, children, className, style }: TMDataGridProps<TData>): import("react").JSX.Element;
1592
+ declare function TMDataGridRoot<TData extends RowData>({ table, ui, features, labels, renderDetails, renderDetailsEstHeight, overscan, size, children, className, style }: TMDataGridProps<TData>): import("react").JSX.Element;
602
1593
  declare const TMDataGrid: typeof TMDataGridRoot & {
603
1594
  Toolbar: typeof TMDataGridToolbar;
604
1595
  Spacer: typeof TMDataGridToolbarSpacer;
605
1596
  SummaryCount: typeof TMDataGridSummaryCount;
1597
+ LoadingIndicator: typeof TMDataGridLoadingIndicator;
1598
+ Search: typeof TMDataGridSearch;
606
1599
  ColumnsButton: typeof TMDataGridColumnsButton;
607
1600
  FilterButton: typeof TMDataGridFilterButton;
608
1601
  Table: typeof TMDataGridTable$1;
609
1602
  Footer: typeof TMDataGridFooter;
610
1603
  /** Rendered by `TMDataGrid.Table`; exported for custom layouts. */
611
1604
  FilterPanel: typeof TMDataGridFilterPanel;
1605
+ /**
1606
+ * Takes the grid as an `api` prop rather than from context, so it can be
1607
+ * rendered outside `<TMDataGrid>` — a page header, for instance.
1608
+ */
1609
+ FilterPills: typeof TMDataGridFilterPills;
612
1610
  /** Rendered by `TMDataGrid.ColumnsButton`; exported for custom layouts. */
613
1611
  ColumnsPanel: typeof TMDataGridColumnsPanel;
614
1612
  };
@@ -616,6 +1614,33 @@ declare const TMDataGrid: typeof TMDataGridRoot & {
616
1614
  //#region .types-tmp/components/TMDataGridSelectColumn.d.ts
617
1615
  declare const SELECT_COLUMN_ID = "__select__";
618
1616
  //#endregion
1617
+ //#region .types-tmp/components/TMDataGridDetailsColumn.d.ts
1618
+ declare const DETAILS_COLUMN_ID = "__details__";
1619
+ //#endregion
1620
+ //#region .types-tmp/components/TMDataGridGroupColumn.d.ts
1621
+ declare const GROUP_COLUMN_ID = "__group__";
1622
+ /**
1623
+ * How a grouping value is written into the tree cell.
1624
+ *
1625
+ * Deliberately not the grouped column's own `cell` renderer: that renderer is
1626
+ * written for a data row and is free to reach into `row.original`, which on a
1627
+ * group row is the first leaf's record rather than anything about the group.
1628
+ */
1629
+ declare function formatGroupValue(value: unknown, blankLabel?: string): string;
1630
+ //#endregion
1631
+ //#region .types-tmp/core/labelsSv.d.ts
1632
+ /**
1633
+ * The complete Swedish dictionary. Typed as {@link TMDataGridLabels} rather
1634
+ * than as an override, so a label added to the grid without a Swedish
1635
+ * translation is a compile error here instead of English quietly leaking
1636
+ * through.
1637
+ *
1638
+ * ```tsx
1639
+ * useTMDataGrid({ data, columns, labels: TMDATAGRID_LABELS_SV });
1640
+ * ```
1641
+ */
1642
+ declare const TMDATAGRID_LABELS_SV: TMDataGridLabels;
1643
+ //#endregion
619
1644
  //#region .types-tmp/core/columnUtils.d.ts
620
1645
  /**
621
1646
  * Structural shape of the column bits the chrome reads. Kept minimal so these
@@ -634,6 +1659,19 @@ type ColumnLike = {
634
1659
  /** Menu- and panel-facing column name. */
635
1660
  declare function getColumnLabel(column: ColumnLike): string;
636
1661
  declare function getColumnType(column: ColumnLike): TMDataGridColumnType;
1662
+ /**
1663
+ * A generated lane holding one control at a fixed width — the checkbox and the
1664
+ * details chevron.
1665
+ *
1666
+ * They are laid out differently from every other column: cell padding is sized
1667
+ * for text and grows with the scale, which at `xl` squeezed a 16px checkbox out
1668
+ * of its track, so these lanes centre their control in an unpadded cell.
1669
+ * Their headers are controls too, and carry no column menu.
1670
+ *
1671
+ * The tree column is deliberately not one of them: it holds a label as well as a
1672
+ * chevron, and wants the padding.
1673
+ */
1674
+ declare function isControlColumn(columnId: string): boolean;
637
1675
  /**
638
1676
  * Whether a column may be moved. Ordering is the one column feature TanStack
639
1677
  * has no column option for, so the switch lives in `meta.enableOrdering`.
@@ -644,6 +1682,116 @@ declare function getColumnType(column: ColumnLike): TMDataGridColumnType;
644
1682
  */
645
1683
  declare function isColumnReorderable(column: ColumnLike): boolean;
646
1684
  //#endregion
1685
+ //#region .types-tmp/core/grouping.d.ts
1686
+ /**
1687
+ * The data rows under a group row, at any depth.
1688
+ *
1689
+ * Not `row.getLeafRows()`, despite the name: that flattens the whole subtree
1690
+ * and keeps the branches, so a group nested two deep reports its sub-groups
1691
+ * alongside the records. Grouping `city` then `name` would have Stockholm
1692
+ * counting four rows and three names as seven, and one tick on it selecting
1693
+ * ids that hold no record.
1694
+ *
1695
+ * A row with no subRows is a data row, which also makes this the identity on an
1696
+ * ungrouped grid.
1697
+ */
1698
+ declare function getGroupDataRows<TData extends RowData>(row: Row<TMDataGridFeatures, TData>): Array<Row<TMDataGridFeatures, TData>>;
1699
+ //#endregion
1700
+ //#region .types-tmp/core/summary.d.ts
1701
+ /** The registered aggregation names — the same set `aggregationFn` accepts. */
1702
+ type TMDataGridAggregationName = keyof typeof aggregationFns;
1703
+ /**
1704
+ * One column aggregated over every filtered row — the number a summary-row
1705
+ * `footer` wants:
1706
+ *
1707
+ * ```tsx
1708
+ * columnHelper.accessor("salary", {
1709
+ * footer: ({ table }) => sek(Number(aggregateColumn({ table, columnId: "salary" }))),
1710
+ * });
1711
+ * ```
1712
+ *
1713
+ * Filtered rather than paginated rows, so the total covers everything the
1714
+ * filters left — all pages — and follows the filters as they change. Reuses
1715
+ * TanStack's registered aggregation functions; `fn` defaults to `"sum"`.
1716
+ */
1717
+ declare function aggregateColumn<TData extends RowData>({ table, columnId, fn }: {
1718
+ table: TMDataGridTable<TData>;
1719
+ columnId: string;
1720
+ fn?: TMDataGridAggregationName;
1721
+ }): unknown;
1722
+ //#endregion
1723
+ //#region .types-tmp/core/autosize.d.ts
1724
+ /**
1725
+ * Widest rendered content of one column, in px, measured from the DOM.
1726
+ *
1727
+ * Mounted cells only: under virtualization the unmounted rows do not exist to
1728
+ * be measured, so this reads the visible window plus overscan — the same
1729
+ * trade AG Grid's autosize makes by default.
1730
+ */
1731
+ declare function measureColumnContentWidth({ container, columnId }: {
1732
+ /** The grid's scroll container — anything enclosing the column's cells. */
1733
+ container: HTMLElement;
1734
+ columnId: string;
1735
+ }): number;
1736
+ /**
1737
+ * Sizes a column to its widest mounted content — what double-clicking the
1738
+ * resize divider does, exported so a menu item or consumer code can trigger
1739
+ * the same thing.
1740
+ *
1741
+ * The width lands in `columnSizing`, so it persists with the other widths and
1742
+ * a later resize drag takes over from it. Clamped to the column's
1743
+ * `minSize`/`maxSize`; a no-op (returning `false`) for a column that cannot
1744
+ * be resized or has nothing mounted to measure.
1745
+ */
1746
+ declare function autosizeColumn<TData extends RowData>({ table, columnId, container }: {
1747
+ table: TMDataGridTable<TData>;
1748
+ columnId: string;
1749
+ container: HTMLElement;
1750
+ }): boolean;
1751
+ //#endregion
1752
+ //#region .types-tmp/core/expanding.d.ts
1753
+ /**
1754
+ * Which rows an expand-all control is about.
1755
+ *
1756
+ * TanStack keeps one `expanded` state, and the grid opens two unrelated things
1757
+ * out of it: a group row opens into its children, a data row opens into its
1758
+ * detail panel. So `toggleAllRowsExpanded` — which writes the state's
1759
+ * whole-table form — is the wrong verb for either control. "Expand all groups"
1760
+ * in the tree menu would open every panel in the grid, and the details lane's
1761
+ * chevron would unfold the whole tree.
1762
+ *
1763
+ * These helpers narrow both to the rows their control is for, and leave the
1764
+ * other kind exactly as it was.
1765
+ */
1766
+ type TMDataGridExpandTarget = "groups" | "details";
1767
+ type TMDataGridExpandAllArgs<TData extends RowData> = {
1768
+ /**
1769
+ * Every row in the model, groups and records alike — `flatRows` off any of
1770
+ * them. A grouped model lists its leaves both under their group and in the
1771
+ * flat list, so this may repeat rows; both helpers are written so that a
1772
+ * repeat costs nothing.
1773
+ */
1774
+ rows: ReadonlyArray<Row<TMDataGridFeatures, TData>>;
1775
+ expanded: ExpandedState;
1776
+ target: TMDataGridExpandTarget;
1777
+ };
1778
+ /**
1779
+ * Whether every row of this kind is open — what the control shows, and what a
1780
+ * bare toggle inverts.
1781
+ *
1782
+ * `false` when there are none of them, matching TanStack's own
1783
+ * `getIsAllRowsExpanded()` on an empty state: an empty set is nothing to
1784
+ * collapse.
1785
+ */
1786
+ declare function areAllRowsExpanded<TData extends RowData>({ rows, expanded, target }: TMDataGridExpandAllArgs<TData>): boolean;
1787
+ /**
1788
+ * The next `expanded` state after an expand-all or collapse-all on one kind of
1789
+ * row. Rows of the other kind keep whatever they had.
1790
+ */
1791
+ declare function resolveExpandAll<TData extends RowData>({ rows, expanded, target, expand }: TMDataGridExpandAllArgs<TData> & {
1792
+ expand: boolean;
1793
+ }): ExpandedState;
1794
+ //#endregion
647
1795
  //#region .types-tmp/core/columnOrdering.d.ts
648
1796
  type GridColumn = Column<TMDataGridFeatures, TMDataGridRowData, unknown>;
649
1797
  type GridTable = TMDataGridTable<TMDataGridRowData>;
@@ -694,4 +1842,99 @@ declare function getStepTargetColumn({ table, columnId, direction }: ColumnStepA
694
1842
  /** Moves a column one position within its lane. Hidden columns are stepped over. */
695
1843
  declare function moveColumnByStep({ table, columnId, direction }: ColumnStepArgs): void;
696
1844
  //#endregion
697
- export { type ColumnStepArgs, DATA_STATE_SLICES, DEFAULT_TMDATAGRID_SIZE, FILTER_OPERATOR_LABELS, type MoveColumnArgs, SELECT_COLUMN_ID, SETTINGS_STATE_SLICES, SIZE_CONTROL_SIZE, SIZE_ROW_HEIGHT, TMDataGrid, type TMDataGridApi, type TMDataGridCapabilities, type TMDataGridColumnCapabilities, type TMDataGridColumnLayout, type TMDataGridColumnMeta, type TMDataGridColumnRegion, type TMDataGridColumnType, type TMDataGridContextValue, type TMDataGridDataSlice, type TMDataGridDropSide, type TMDataGridFeatureFlags, type TMDataGridFeatures, type TMDataGridFilterOperator, type TMDataGridFilterValue, type TMDataGridFooterProps, type TMDataGridPaginationApi, type TMDataGridPersistKey, type TMDataGridPersistence, type TMDataGridProps, type TMDataGridRowData, type TMDataGridRowSelectionMode, type TMDataGridSettingsSlice, type TMDataGridSize, type TMDataGridStorageMode, type TMDataGridTable, type TMDataGridTableMeta, type TMDataGridUiActions, type TMDataGridUiState, type TMDataGridUiStore, type UseTMDataGridOptions, createTMDataGridColumnHelper, getColumnCapabilities, getColumnLabel, getColumnRegion, getColumnType, getGridCapabilities, getStepTargetColumn, getTMDataGridPaginationApi, isColumnReorderable, isFilterActive, moveColumn, moveColumnByStep, openColumnFilter, readFeatureFlags, tmDataGridFeatures, useTMDataGrid, useTMDataGridContext };
1845
+ //#region .types-tmp/core/rowSelection.d.ts
1846
+ /**
1847
+ * Rows in the order they are displayed, which is the order a shift-click range
1848
+ * is measured over — so a range follows the active sort and skips filtered-out
1849
+ * rows. Under pagination it is the current page, so a range cannot cross a page
1850
+ * boundary.
1851
+ *
1852
+ * Once a column is grouped this includes the group rows, and only the leaves of
1853
+ * groups that are open — and paging is suspended, so it is the whole tree. That
1854
+ * is the right list for a range: it is what the user can see, and a range that
1855
+ * swept collapsed rows would select things off screen. What a group row in the
1856
+ * range contributes is decided by {@link getSelectableRowIds}.
1857
+ */
1858
+ declare function getDisplayedRows<TData extends RowData>(table: TMDataGridTable<TData>, features: TMDataGridFeatureFlags): Array<Row<TMDataGridFeatures, TData>>;
1859
+ /**
1860
+ * Whether the built-in pager is actually slicing anything.
1861
+ *
1862
+ * Grouping suspends it. A page can only count one kind of thing, and once the
1863
+ * rows are a tree neither answer works: counting every row splits a group
1864
+ * across a page boundary and strands the rest of the tree on pages the user has
1865
+ * to go looking for, and counting only the top-level rows quietly redefines
1866
+ * "rows per page" as groups per page, so a page of 25 can hold thousands of
1867
+ * rows. Rather than pick, the grid renders the whole tree and leans on the
1868
+ * virtualizer — which is its default mode anyway, pagination being opt-in.
1869
+ *
1870
+ * `TMDataGrid.Footer` reads this too, and greys the pager out rather than
1871
+ * hiding it, so the pager going quiet is visible instead of mysterious.
1872
+ */
1873
+ declare function isPagingActive<TData extends RowData>(table: TMDataGridTable<TData>, features: TMDataGridFeatureFlags): boolean;
1874
+ /**
1875
+ * Which modifiers were held. Named for what they mean rather than for the keys,
1876
+ * because the keys differ per platform — `toggle` is Ctrl on Windows/Linux and
1877
+ * Cmd on macOS.
1878
+ */
1879
+ type TMDataGridRowClickModifiers = {
1880
+ toggle: boolean;
1881
+ extend: boolean;
1882
+ };
1883
+ type ResolveRowSelectionClickArgs<TData extends RowData> = {
1884
+ /** Displayed order — see {@link getDisplayedRows}. */
1885
+ rows: ReadonlyArray<Row<TMDataGridFeatures, TData>>;
1886
+ rowId: string;
1887
+ /** The pivot a shift-click extends from. */
1888
+ anchorRowId: string | null;
1889
+ modifiers: TMDataGridRowClickModifiers;
1890
+ selection: RowSelectionState;
1891
+ /**
1892
+ * Whether this gesture is allowed to clear rows it did not touch.
1893
+ *
1894
+ * `true` for a bare row click, where replacing is the whole point. `false` for
1895
+ * a checkbox, which is only ever additive — ticking one box has never cleared
1896
+ * the others, and shift-clicking one adds the range rather than becoming it.
1897
+ */
1898
+ canReplaceSelection: boolean;
1899
+ };
1900
+ type ResolvedRowSelection = {
1901
+ selection: RowSelectionState;
1902
+ anchorRowId: string | null;
1903
+ };
1904
+ /**
1905
+ * The row ids one gesture on this row selects.
1906
+ *
1907
+ * A group row is never selected itself: it holds no record, and TanStack
1908
+ * derives its checked state from its descendants. So ticking a group means
1909
+ * ticking every selectable leaf under it, which is also what makes the group's
1910
+ * own box light up.
1911
+ *
1912
+ * Leaves rather than direct children, so one click on a top-level group takes
1913
+ * the whole subtree however deeply it nests.
1914
+ */
1915
+ declare function getSelectableRowIds<TData extends RowData>(row: Row<TMDataGridFeatures, TData>): Array<string>;
1916
+ /**
1917
+ * Turns one click into the next selection, following the convention every
1918
+ * desktop list uses:
1919
+ *
1920
+ * | Gesture | Effect |
1921
+ * | ------- | ------ |
1922
+ * | Click | selection becomes only this row |
1923
+ * | Ctrl/Cmd + click | toggle this row, leave the rest |
1924
+ * | Shift + click | selection becomes the range anchor → this row |
1925
+ * | Ctrl/Cmd + Shift + click | add that range to the selection |
1926
+ *
1927
+ * The anchor is a *pivot*, not "the last row touched": only a plain or
1928
+ * Ctrl-click moves it, which is what lets a run of shift-clicks grow and shrink
1929
+ * the same range from a fixed point.
1930
+ *
1931
+ * Selection state is rebuilt here and handed to `setRowSelection` wholesale
1932
+ * rather than going through `row.toggleSelected()` per row, which would publish
1933
+ * one state update each. That skips TanStack's sub-row cascade, so the cascade
1934
+ * is done here instead: every row in the gesture is expanded through
1935
+ * {@link getSelectableRowIds} before it reaches the map. Under grouping that is
1936
+ * what makes one tick on a group select all of it.
1937
+ */
1938
+ declare function resolveRowSelectionClick<TData extends RowData>({ rows, rowId, anchorRowId, modifiers, selection, canReplaceSelection }: ResolveRowSelectionClickArgs<TData>): ResolvedRowSelection;
1939
+ //#endregion
1940
+ export { type BuildCellMatrixArgs, type ColumnStepArgs, DATA_STATE_SLICES, DEFAULT_CELL_EXPORT_OPTIONS, DEFAULT_TMDATAGRID_SIZE, DETAILS_COLUMN_ID, FILTER_OPERATOR_LABELS, GROUP_COLUMN_ID, type MoveColumnArgs, type ResolveCellMoveArgs, type ResolveRangeBoundsArgs, type ResolveRowSelectionClickArgs, type ResolvedRowSelection, SELECT_COLUMN_ID, SETTINGS_STATE_SLICES, SIZE_CONTROL_SIZE, SIZE_ROW_HEIGHT, TMDATAGRID_LABELS_EN, TMDATAGRID_LABELS_SV, TMDataGrid, type TMDataGridAggregationName, type TMDataGridApi, type TMDataGridCapabilities, type TMDataGridCellCoords, type TMDataGridCellExportOptions, type TMDataGridCellMatrix, type TMDataGridCellNav, type TMDataGridCellPosition, type TMDataGridCellRange, type TMDataGridCellSelectionMode, type TMDataGridColumnCapabilities, type TMDataGridColumnLayout, type TMDataGridColumnMeta, type TMDataGridColumnRegion, type TMDataGridColumnType, type TMDataGridContextValue, type TMDataGridDataSlice, type TMDataGridDetailsArgs, type TMDataGridDetailsRenderer, type TMDataGridDropSide, type TMDataGridExpandAllArgs, type TMDataGridExpandTarget, type TMDataGridFeatureFlags, type TMDataGridFeatures, type TMDataGridFilterOperator, TMDataGridFilterPills, type TMDataGridFilterPillsProps, type TMDataGridFilterValue, type TMDataGridFooterProps, type TMDataGridLabels, type TMDataGridLabelsOverride, type TMDataGridOption, type TMDataGridOptionsArgs, type TMDataGridOptionsSource, type TMDataGridPaginationApi, type TMDataGridPersistKey, type TMDataGridPersistence, type TMDataGridProps, type TMDataGridRangeBounds, type TMDataGridRowClickModifiers, type TMDataGridRowContextMenu, type TMDataGridRowContextMenuArgs, type TMDataGridRowData, TMDataGridSearch, type TMDataGridSearchProps, type TMDataGridSelectionMode, type TMDataGridSettingsSlice, type TMDataGridSize, type TMDataGridStorageMode, type TMDataGridTable, type TMDataGridTableMeta, type TMDataGridTableProps, type TMDataGridUiActions, type TMDataGridUiState, type TMDataGridUiStore, type UseTMDataGridOptions, aggregateColumn, areAllRowsExpanded, autosizeColumn, boundsCellCount, boundsEdges, buildCellMatrix, buildGridCellMatrix, createTMDataGridColumnHelper, downloadTextFile, exportGridToCsv, formatExportValue, formatFilterLabel, formatGroupValue, getColumnCapabilities, getColumnLabel, getColumnRegion, getColumnType, getDefaultOperator, getDisplayedRows, getGridCapabilities, getGroupDataRows, getOperatorsForType, getSelectableRowIds, getStepTargetColumn, getTMDataGridPaginationApi, isColumnReorderable, isControlColumn, isFilterActive, isPagingActive, isSameCell, isWithinBounds, measureColumnContentWidth, mergeLabels, moveColumn, moveColumnByStep, openColumnFilter, operatorNeedsValue, operatorTakesArrayValue, optionsToComboboxData, readFeatureFlags, resolveCellMove, resolveColumnOptions, resolveExpandAll, resolveRangeBounds, resolveRowSelectionClick, tmDataGridFeatures, toClipboardText, toExcelCsv, useCellControlTabIndex, useTMDataGrid, useTMDataGridContext, writeClipboardText };