@jielga/tmdatagrid 0.3.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 (43) hide show
  1. package/dist/index.d.ts +947 -64
  2. package/dist/index.js +2474 -1423
  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 +1 -1
  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 +10 -0
  13. package/src/tmdatagrid/components/TMDataGrid.tsx +23 -1
  14. package/src/tmdatagrid/components/TMDataGridColumnsPanel.tsx +5 -5
  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.tsx +111 -33
  18. package/src/tmdatagrid/components/TMDataGridFilterPills.tsx +5 -4
  19. package/src/tmdatagrid/components/TMDataGridFooter.tsx +11 -19
  20. package/src/tmdatagrid/components/TMDataGridGroupColumn.tsx +23 -11
  21. package/src/tmdatagrid/components/TMDataGridHeaderCell.module.css +15 -3
  22. package/src/tmdatagrid/components/TMDataGridHeaderCell.tsx +181 -52
  23. package/src/tmdatagrid/components/TMDataGridSearch.tsx +122 -0
  24. package/src/tmdatagrid/components/TMDataGridSelectColumn.tsx +23 -13
  25. package/src/tmdatagrid/components/TMDataGridTable.module.css +127 -6
  26. package/src/tmdatagrid/components/TMDataGridTable.tsx +1003 -30
  27. package/src/tmdatagrid/components/TMDataGridToolbar.tsx +30 -7
  28. package/src/tmdatagrid/components/icons.ts +1 -0
  29. package/src/tmdatagrid/components/sticky.module.css +77 -16
  30. package/src/tmdatagrid/core/autosize.ts +125 -0
  31. package/src/tmdatagrid/core/capabilities.ts +41 -0
  32. package/src/tmdatagrid/core/cellExport.ts +321 -0
  33. package/src/tmdatagrid/core/cellNavigation.ts +103 -0
  34. package/src/tmdatagrid/core/cellRange.ts +118 -0
  35. package/src/tmdatagrid/core/columnOptions.ts +123 -0
  36. package/src/tmdatagrid/core/columnUtils.ts +18 -0
  37. package/src/tmdatagrid/core/expanding.ts +93 -0
  38. package/src/tmdatagrid/core/filterOperators.ts +176 -15
  39. package/src/tmdatagrid/core/labels.ts +211 -0
  40. package/src/tmdatagrid/core/labelsSv.ts +108 -0
  41. package/src/tmdatagrid/core/summary.ts +35 -0
  42. package/src/tmdatagrid/index.ts +70 -0
  43. package/src/tmdatagrid/useTMDataGrid.tsx +328 -12
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Cell, Column, ColumnPinningState, Row, RowData, RowSelectionState, 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
3
  import { MantineSize, MenuProps } from "@mantine/core";
4
4
  import { Store } from "@tanstack/store";
@@ -33,6 +33,107 @@ declare const SIZE_ROW_HEIGHT: Record<TMDataGridSize, number>;
33
33
  /** Size of the Mantine controls rendered inside the grid chrome. */
34
34
  declare const SIZE_CONTROL_SIZE: Record<TMDataGridSize, MantineSize>;
35
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
36
137
  //#region .types-tmp/core/filterOperators.d.ts
37
138
  /**
38
139
  * The value shape stored in `columnFilters` for every TMDataGrid column.
@@ -41,14 +142,23 @@ declare const SIZE_CONTROL_SIZE: Record<TMDataGridSize, MantineSize>;
41
142
  * inside the filter *value* instead. That keeps the whole filter model plain,
42
143
  * serialisable JSON — which is what makes it portable to a server-side
43
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.
44
149
  */
45
150
  type TMDataGridFilterValue = {
46
151
  operator: TMDataGridFilterOperator;
47
- value: string;
152
+ value: string | ReadonlyArray<string>;
48
153
  };
49
- type TMDataGridColumnType = "string" | "number";
50
- 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";
51
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;
52
162
  /**
53
163
  * A filter only narrows the row set once it has something to compare against.
54
164
  * Half-typed filters stay in state (so the panel keeps rendering their row) but
@@ -62,10 +172,12 @@ declare function isFilterActive(value: unknown): boolean;
62
172
  * way a person would say it — while any other operator is spelled out, since
63
173
  * that is the part a reader cannot guess.
64
174
  */
65
- declare function formatFilterLabel({ label, type, filter }: {
175
+ declare function formatFilterLabel({ label, type, filter, operatorLabels }: {
66
176
  label: string;
67
177
  type: TMDataGridColumnType;
68
178
  filter: TMDataGridFilterValue;
179
+ /** Localized operator names — `labels.operators`. Defaults to English. */
180
+ operatorLabels?: Record<TMDataGridFilterOperator, string>;
69
181
  }): string;
70
182
  /**
71
183
  * The single filter function every TMDataGrid column uses. It dispatches on the
@@ -74,6 +186,102 @@ declare function formatFilterLabel({ label, type, filter }: {
74
186
  */
75
187
  declare function tmDataGridFilterFn<TFeatures extends TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, columnId: string, filterValue: unknown): boolean;
76
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
77
285
  //#region .types-tmp/core/persistence.d.ts
78
286
  type GridState = TableState<TMDataGridFeatures>;
79
287
  /**
@@ -125,22 +333,6 @@ type TMDataGridPersistence = {
125
333
  deserialize?: (value: string) => unknown;
126
334
  };
127
335
  //#endregion
128
- //#region .types-tmp/TMDataGridContext.d.ts
129
- /**
130
- * Row shape the chrome components work against. They only ever touch columns,
131
- * rows and cells generically, so the concrete row type is erased at the context
132
- * boundary — the same trick Mantine uses for its compound components.
133
- */
134
- type TMDataGridRowData = Record<string, unknown>;
135
- type TMDataGridContextValue = TMDataGridApi<TMDataGridRowData> & {
136
- size: TMDataGridSize;
137
- /** Row height in px, already resolved from `size` and `meta.rowHeight`. */
138
- rowHeight: number;
139
- /** Mantine control size that pairs with `size`. */
140
- controlSize: TMDataGridSize;
141
- };
142
- declare function useTMDataGridContext(): TMDataGridContextValue;
143
- //#endregion
144
336
  //#region .types-tmp/core/capabilities.d.ts
145
337
  /**
146
338
  * Table-level feature switches, read straight off the options object.
@@ -172,9 +364,26 @@ type TMDataGridSelectionMode =
172
364
  "checkboxAndHighlight" |
173
365
  /** No selection at all — a row click only highlights. Master-detail. */
174
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";
175
382
  type TMDataGridFeatureFlags = {
176
383
  sorting: boolean;
177
384
  filtering: boolean;
385
+ /** Whether the quick search may filter — `enableGlobalFilter`. */
386
+ globalFiltering: boolean;
178
387
  hiding: boolean;
179
388
  pinning: boolean;
180
389
  resizing: boolean;
@@ -204,6 +413,17 @@ type TMDataGridFeatureFlags = {
204
413
  * what lets it coexist with a checkbox multi-selection.
205
414
  */
206
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;
207
427
  /**
208
428
  * The one default-off flag: pagination must be asked for, either with the
209
429
  * grid's `enablePagination` or implicitly by declaring `manualPagination`.
@@ -223,7 +443,7 @@ type TMDataGridFeatureFlags = {
223
443
  */
224
444
  grouping: boolean;
225
445
  };
226
- declare function readFeatureFlags<TData extends RowData>(options: Pick<UseTMDataGridOptions<TData>, "enableSorting" | "enableColumnFilters" | "enableHiding" | "enableColumnPinning" | "enableColumnResizing" | "enableColumnOrdering" | "enableRowSelection" | "enableMultiRowSelection" | "selectionMode" | "showSelectedBackground" | "enablePagination" | "manualPagination" | "enableGrouping">): 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;
227
447
  /**
228
448
  * What one column's header may offer.
229
449
  *
@@ -257,19 +477,151 @@ type TMDataGridCapabilities = {
257
477
  canGroupAny: boolean;
258
478
  canSelectRows: boolean;
259
479
  canPaginate: boolean;
480
+ /** At least one leaf column takes part in the global quick search. */
481
+ canSearch: boolean;
260
482
  };
261
483
  declare function getGridCapabilities(table: TMDataGridTable<TMDataGridRowData>, features: TMDataGridFeatureFlags): TMDataGridCapabilities;
262
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
263
598
  //#region .types-tmp/useTMDataGrid.d.ts
264
599
  /** Per-column configuration the TMDataGrid chrome reads. */
265
600
  type TMDataGridColumnMeta = {
266
601
  /** Name shown in menus and the column manager. Falls back to a string header. */
267
602
  label?: string;
268
- /** 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
+ */
269
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;
270
616
  /** Share of the leftover width this column claims. Defaults to `1`. */
271
617
  flex?: number;
272
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;
273
625
  /**
274
626
  * `false` keeps the column where it is: no header dragging, no move items.
275
627
  * Column ordering is the one feature TanStack defines no column option for,
@@ -316,50 +668,50 @@ declare const tmDataGridFeatures: {
316
668
  facetedMinMaxValues: (table: Table<import("@tanstack/table-core").TableFeatures, any>, columnId: string) => () => undefined | [number, number];
317
669
  facetedUniqueValues: (table: Table<import("@tanstack/table-core").TableFeatures, any>, columnId: string) => () => Map<any, number>;
318
670
  filterFns: {
319
- 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) & {
320
672
  autoRemove: (val: any) => boolean;
321
673
  };
322
- 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) & {
323
675
  autoRemove: (val: any) => boolean;
324
676
  };
325
- 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;
326
- 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) & {
327
679
  autoRemove: (val: any) => boolean;
328
680
  };
329
- 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) & {
330
682
  autoRemove: (val: any) => boolean;
331
683
  };
332
- 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) & {
333
685
  autoRemove: (val: any) => boolean;
334
686
  };
335
- 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) & {
336
688
  autoRemove: (val: any) => boolean;
337
689
  };
338
- 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) & {
339
691
  autoRemove: (val: any) => boolean;
340
692
  };
341
- 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) & {
342
694
  resolveFilterValue: (val: [any, any]) => readonly [number, number];
343
695
  autoRemove: (val: any) => boolean;
344
696
  };
345
- 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) & {
346
698
  autoRemove: (val: any) => boolean;
347
699
  };
348
- 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) & {
349
701
  autoRemove: (val: any) => boolean;
350
702
  };
351
- 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) & {
352
704
  autoRemove: (val: any) => boolean;
353
705
  };
354
706
  tmDataGrid: typeof tmDataGridFilterFn;
355
707
  };
356
708
  sortFns: {
357
- 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;
358
- 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;
359
- 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;
360
- 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;
361
- 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;
362
- 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;
363
715
  };
364
716
  aggregationFns: {
365
717
  sum: typeof import("@tanstack/table-core").aggregationFn_sum;
@@ -400,50 +752,50 @@ declare function createTMDataGridColumnHelper<TData extends RowData>(): import("
400
752
  facetedMinMaxValues: (table: Table<import("@tanstack/table-core").TableFeatures, any>, columnId: string) => () => undefined | [number, number];
401
753
  facetedUniqueValues: (table: Table<import("@tanstack/table-core").TableFeatures, any>, columnId: string) => () => Map<any, number>;
402
754
  filterFns: {
403
- 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) & {
404
756
  autoRemove: (val: any) => boolean;
405
757
  };
406
- 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) & {
407
759
  autoRemove: (val: any) => boolean;
408
760
  };
409
- 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;
410
- 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) & {
411
763
  autoRemove: (val: any) => boolean;
412
764
  };
413
- 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) & {
414
766
  autoRemove: (val: any) => boolean;
415
767
  };
416
- 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) & {
417
769
  autoRemove: (val: any) => boolean;
418
770
  };
419
- 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) & {
420
772
  autoRemove: (val: any) => boolean;
421
773
  };
422
- 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) & {
423
775
  autoRemove: (val: any) => boolean;
424
776
  };
425
- 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) & {
426
778
  resolveFilterValue: (val: [any, any]) => readonly [number, number];
427
779
  autoRemove: (val: any) => boolean;
428
780
  };
429
- 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) & {
430
782
  autoRemove: (val: any) => boolean;
431
783
  };
432
- 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) & {
433
785
  autoRemove: (val: any) => boolean;
434
786
  };
435
- 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) & {
436
788
  autoRemove: (val: any) => boolean;
437
789
  };
438
790
  tmDataGrid: typeof tmDataGridFilterFn;
439
791
  };
440
792
  sortFns: {
441
- 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;
442
- 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;
443
- 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;
444
- 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;
445
- 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;
446
- 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;
447
799
  };
448
800
  aggregationFns: {
449
801
  sum: typeof import("@tanstack/table-core").aggregationFn_sum;
@@ -459,6 +811,13 @@ declare function createTMDataGridColumnHelper<TData extends RowData>(): import("
459
811
  tableMeta: TMDataGridTableMeta;
460
812
  columnMeta: TMDataGridColumnMeta;
461
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;
462
821
  /**
463
822
  * Chrome state that is *not* table state: which panels are open, and which
464
823
  * column opened the filter panel. Kept in a TanStack Store so consumers can
@@ -488,6 +847,25 @@ type TMDataGridUiState = {
488
847
  highlightedRowId: string | null;
489
848
  /** The pivot a shift-click extends from. See resolveRowSelectionClick. */
490
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;
491
869
  };
492
870
  type TMDataGridUiActions = {
493
871
  openFilterPanel: (columnId?: string | null) => void;
@@ -502,6 +880,19 @@ type TMDataGridUiActions = {
502
880
  */
503
881
  setHighlightedRow: (rowId: string | null) => void;
504
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;
505
896
  };
506
897
  type TMDataGridUiStore = Store<TMDataGridUiState, TMDataGridUiActions>;
507
898
  /** What `useTMDataGrid` returns — spread straight onto `<TMDataGrid />`. */
@@ -510,6 +901,14 @@ type TMDataGridApi<TData extends RowData> = {
510
901
  ui: TMDataGridUiStore;
511
902
  /** Table-level feature switches, re-read from options on every render. */
512
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;
513
912
  };
514
913
  type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridFeatures, TData>, "features"> & {
515
914
  /**
@@ -520,6 +919,20 @@ type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridF
520
919
  * dependency of the subscription that writes back.
521
920
  */
522
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;
523
936
  /**
524
937
  * Header drag-and-drop and the move items in the column menu. Defaults to
525
938
  * `true`.
@@ -602,6 +1015,113 @@ type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridF
602
1015
  * Fires for `ui.actions.setHighlightedRow` too, not only for clicks.
603
1016
  */
604
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;
605
1125
  };
606
1126
  /**
607
1127
  * Builds a TMDataGrid table plus its chrome store.
@@ -614,7 +1134,7 @@ type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridF
614
1134
  * flag on, so `<TMDataGrid.Footer />` renders its pager without further
615
1135
  * options.
616
1136
  */
617
- declare function useTMDataGrid<TData extends RowData>({ persist, enableColumnOrdering, enablePagination, selectionMode, showSelectedBackground, defaultHighlightedRowId, onHighlightedRowChange, ...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>;
618
1138
  /**
619
1139
  * Opens the filter panel for a column, seeding an empty filter row when the
620
1140
  * column has none yet — mirrors "Filter" in the column header menu.
@@ -698,6 +1218,171 @@ type TMDataGridFooterProps = {
698
1218
  */
699
1219
  declare function TMDataGridFooter({ pageSizeOptions, pagination }: TMDataGridFooterProps): import("react").JSX.Element | null;
700
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
701
1386
  //#region .types-tmp/components/TMDataGridTable.d.ts
702
1387
  /** Where a column sits relative to the pinned regions, resolved once per render. */
703
1388
  type TMDataGridColumnLayout = {
@@ -707,6 +1392,35 @@ type TMDataGridColumnLayout = {
707
1392
  /** Last left-pinned / first right-pinned column — the one that casts the edge. */
708
1393
  isBoundary: boolean;
709
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
+ };
710
1424
  /** What a `rowContextMenu` render prop is handed for the right-clicked row. */
711
1425
  type TMDataGridRowContextMenuArgs<TData extends RowData> = {
712
1426
  table: Table<TMDataGridFeatures, TData>;
@@ -764,6 +1478,31 @@ type TMDataGridTableProps<TData extends RowData> = {
764
1478
  * `position`, `transitionProps` and the rest. Its open state is the grid's.
765
1479
  */
766
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;
767
1506
  };
768
1507
  /**
769
1508
  * The scrollable grid surface. Always virtualized: only the rows inside the
@@ -771,7 +1510,7 @@ type TMDataGridTableProps<TData extends RowData> = {
771
1510
  * no-pagination mode viable at any row count. Pagination is opt-in via
772
1511
  * `enablePagination` (or implied by `manualPagination`).
773
1512
  */
774
- declare function TMDataGridTable$1<TData extends RowData = TMDataGridRowData>({ onRowClick, rowContextMenu, rowContextMenuProps }: 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;
775
1514
  //#endregion
776
1515
  //#region .types-tmp/components/TMDataGridToolbar.d.ts
777
1516
  /** Row above the grid. Compose it from the pieces below, or anything else. */
@@ -780,6 +1519,24 @@ declare function TMDataGridToolbar({ children }: {
780
1519
  }): import("react").JSX.Element;
781
1520
  /** Pushes the following toolbar items to the right. */
782
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;
783
1540
  /**
784
1541
  * Visible rows over total rows. On a server-driven grid, set
785
1542
  * `meta.totalRowCount` for the denominator — the client never sees every row.
@@ -832,11 +1589,13 @@ type TMDataGridProps<TData extends RowData> = TMDataGridApi<TData> & {
832
1589
  * </TMDataGrid>
833
1590
  * ```
834
1591
  */
835
- 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;
836
1593
  declare const TMDataGrid: typeof TMDataGridRoot & {
837
1594
  Toolbar: typeof TMDataGridToolbar;
838
1595
  Spacer: typeof TMDataGridToolbarSpacer;
839
1596
  SummaryCount: typeof TMDataGridSummaryCount;
1597
+ LoadingIndicator: typeof TMDataGridLoadingIndicator;
1598
+ Search: typeof TMDataGridSearch;
840
1599
  ColumnsButton: typeof TMDataGridColumnsButton;
841
1600
  FilterButton: typeof TMDataGridFilterButton;
842
1601
  Table: typeof TMDataGridTable$1;
@@ -855,6 +1614,9 @@ declare const TMDataGrid: typeof TMDataGridRoot & {
855
1614
  //#region .types-tmp/components/TMDataGridSelectColumn.d.ts
856
1615
  declare const SELECT_COLUMN_ID = "__select__";
857
1616
  //#endregion
1617
+ //#region .types-tmp/components/TMDataGridDetailsColumn.d.ts
1618
+ declare const DETAILS_COLUMN_ID = "__details__";
1619
+ //#endregion
858
1620
  //#region .types-tmp/components/TMDataGridGroupColumn.d.ts
859
1621
  declare const GROUP_COLUMN_ID = "__group__";
860
1622
  /**
@@ -864,7 +1626,20 @@ declare const GROUP_COLUMN_ID = "__group__";
864
1626
  * written for a data row and is free to reach into `row.original`, which on a
865
1627
  * group row is the first leaf's record rather than anything about the group.
866
1628
  */
867
- declare function formatGroupValue(value: unknown): string;
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;
868
1643
  //#endregion
869
1644
  //#region .types-tmp/core/columnUtils.d.ts
870
1645
  /**
@@ -884,6 +1659,19 @@ type ColumnLike = {
884
1659
  /** Menu- and panel-facing column name. */
885
1660
  declare function getColumnLabel(column: ColumnLike): string;
886
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;
887
1675
  /**
888
1676
  * Whether a column may be moved. Ordering is the one column feature TanStack
889
1677
  * has no column option for, so the switch lives in `meta.enableOrdering`.
@@ -909,6 +1697,101 @@ declare function isColumnReorderable(column: ColumnLike): boolean;
909
1697
  */
910
1698
  declare function getGroupDataRows<TData extends RowData>(row: Row<TMDataGridFeatures, TData>): Array<Row<TMDataGridFeatures, TData>>;
911
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
912
1795
  //#region .types-tmp/core/columnOrdering.d.ts
913
1796
  type GridColumn = Column<TMDataGridFeatures, TMDataGridRowData, unknown>;
914
1797
  type GridTable = TMDataGridTable<TMDataGridRowData>;
@@ -1054,4 +1937,4 @@ declare function getSelectableRowIds<TData extends RowData>(row: Row<TMDataGridF
1054
1937
  */
1055
1938
  declare function resolveRowSelectionClick<TData extends RowData>({ rows, rowId, anchorRowId, modifiers, selection, canReplaceSelection }: ResolveRowSelectionClickArgs<TData>): ResolvedRowSelection;
1056
1939
  //#endregion
1057
- export { type ColumnStepArgs, DATA_STATE_SLICES, DEFAULT_TMDATAGRID_SIZE, FILTER_OPERATOR_LABELS, GROUP_COLUMN_ID, type MoveColumnArgs, type ResolveRowSelectionClickArgs, type ResolvedRowSelection, 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, TMDataGridFilterPills, type TMDataGridFilterPillsProps, type TMDataGridFilterValue, type TMDataGridFooterProps, type TMDataGridPaginationApi, type TMDataGridPersistKey, type TMDataGridPersistence, type TMDataGridProps, type TMDataGridRowClickModifiers, type TMDataGridRowContextMenu, type TMDataGridRowContextMenuArgs, type TMDataGridRowData, type TMDataGridSelectionMode, type TMDataGridSettingsSlice, type TMDataGridSize, type TMDataGridStorageMode, type TMDataGridTable, type TMDataGridTableMeta, type TMDataGridTableProps, type TMDataGridUiActions, type TMDataGridUiState, type TMDataGridUiStore, type UseTMDataGridOptions, createTMDataGridColumnHelper, formatFilterLabel, formatGroupValue, getColumnCapabilities, getColumnLabel, getColumnRegion, getColumnType, getDisplayedRows, getGridCapabilities, getGroupDataRows, getSelectableRowIds, getStepTargetColumn, getTMDataGridPaginationApi, isColumnReorderable, isFilterActive, isPagingActive, moveColumn, moveColumnByStep, openColumnFilter, readFeatureFlags, resolveRowSelectionClick, tmDataGridFeatures, useTMDataGrid, useTMDataGridContext };
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 };