@jielga/tmdatagrid 0.2.0 → 0.3.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 (35) hide show
  1. package/dist/index.d.ts +397 -37
  2. package/dist/index.js +1550 -978
  3. package/dist/index.js.map +1 -1
  4. package/dist/styles.css +1 -1
  5. package/package.json +1 -1
  6. package/skills/columns/SKILL.md +1 -1
  7. package/skills/features/SKILL.md +1 -1
  8. package/skills/getting-started/SKILL.md +41 -6
  9. package/skills/options/SKILL.md +1 -1
  10. package/skills/server-side/SKILL.md +1 -1
  11. package/src/tmdatagrid/components/TMDataGrid.module.css +11 -1
  12. package/src/tmdatagrid/components/TMDataGrid.tsx +6 -0
  13. package/src/tmdatagrid/components/TMDataGridColumnsPanel.tsx +7 -1
  14. package/src/tmdatagrid/components/TMDataGridFilterPanel.module.css +15 -0
  15. package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +87 -10
  16. package/src/tmdatagrid/components/TMDataGridFilterPills.module.css +35 -0
  17. package/src/tmdatagrid/components/TMDataGridFilterPills.tsx +135 -0
  18. package/src/tmdatagrid/components/TMDataGridFooter.module.css +8 -0
  19. package/src/tmdatagrid/components/TMDataGridFooter.tsx +70 -42
  20. package/src/tmdatagrid/components/TMDataGridGroupColumn.module.css +48 -0
  21. package/src/tmdatagrid/components/TMDataGridGroupColumn.tsx +147 -0
  22. package/src/tmdatagrid/components/TMDataGridHeaderCell.module.css +6 -0
  23. package/src/tmdatagrid/components/TMDataGridHeaderCell.tsx +77 -1
  24. package/src/tmdatagrid/components/TMDataGridSelectColumn.tsx +83 -6
  25. package/src/tmdatagrid/components/TMDataGridTable.module.css +38 -4
  26. package/src/tmdatagrid/components/TMDataGridTable.tsx +396 -32
  27. package/src/tmdatagrid/components/TMDataGridToolbar.tsx +3 -0
  28. package/src/tmdatagrid/components/icons.ts +5 -0
  29. package/src/tmdatagrid/core/capabilities.ts +81 -11
  30. package/src/tmdatagrid/core/filterOperators.ts +25 -0
  31. package/src/tmdatagrid/core/grouping.ts +21 -0
  32. package/src/tmdatagrid/core/persistence.ts +12 -0
  33. package/src/tmdatagrid/core/rowSelection.ts +202 -0
  34. package/src/tmdatagrid/index.ts +26 -2
  35. package/src/tmdatagrid/useTMDataGrid.tsx +240 -35
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, Row, RowData, RowSelectionState, Table, TableFeatures, TableOptions, TableState } 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,20 @@ 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
22
36
  //#region .types-tmp/core/filterOperators.d.ts
23
37
  /**
24
38
  * The value shape stored in `columnFilters` for every TMDataGrid column.
@@ -41,6 +55,18 @@ declare const FILTER_OPERATOR_LABELS: Record<TMDataGridFilterOperator, string>;
41
55
  * are treated as inactive for the funnel indicator and for row matching.
42
56
  */
43
57
  declare function isFilterActive(value: unknown): boolean;
58
+ /**
59
+ * One-line description of a single filter, as shown on a filter pill.
60
+ *
61
+ * The type's default operator is left implicit — "First name: Sofia" reads the
62
+ * way a person would say it — while any other operator is spelled out, since
63
+ * that is the part a reader cannot guess.
64
+ */
65
+ declare function formatFilterLabel({ label, type, filter }: {
66
+ label: string;
67
+ type: TMDataGridColumnType;
68
+ filter: TMDataGridFilterValue;
69
+ }): string;
44
70
  /**
45
71
  * The single filter function every TMDataGrid column uses. It dispatches on the
46
72
  * operator carried by the filter value, which is what lets one column offer
@@ -69,12 +95,12 @@ type GridState = TableState<TMDataGridFeatures>;
69
95
  * State slices describing what the user is looking at. Derived from the data,
70
96
  * so they can go stale as it changes.
71
97
  */
72
- declare const DATA_STATE_SLICES: readonly ["columnFilters", "globalFilter", "sorting", "pagination"];
98
+ declare const DATA_STATE_SLICES: readonly ["columnFilters", "globalFilter", "sorting", "pagination", "expanded"];
73
99
  /**
74
100
  * State slices describing how the user configured the grid. Independent of the
75
101
  * data, and the ones users notice losing.
76
102
  */
77
- declare const SETTINGS_STATE_SLICES: readonly ["columnVisibility", "columnSizing", "columnOrder", "columnPinning"];
103
+ declare const SETTINGS_STATE_SLICES: readonly ["columnVisibility", "columnSizing", "columnOrder", "columnPinning", "grouping"];
78
104
  type TMDataGridDataSlice = (typeof DATA_STATE_SLICES)[number];
79
105
  type TMDataGridSettingsSlice = (typeof SETTINGS_STATE_SLICES)[number];
80
106
  /**
@@ -99,20 +125,6 @@ type TMDataGridPersistence = {
99
125
  deserialize?: (value: string) => unknown;
100
126
  };
101
127
  //#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
128
  //#region .types-tmp/TMDataGridContext.d.ts
117
129
  /**
118
130
  * Row shape the chrome components work against. They only ever touch columns,
@@ -143,9 +155,23 @@ declare function useTMDataGridContext(): TMDataGridContextValue;
143
155
  * what applies the per-column overrides.
144
156
  */
145
157
  /**
146
- * How rows are selected — see `rowSelectionMode` on {@link UseTMDataGridOptions}.
158
+ * How rows are selected — see `selectionMode` on {@link UseTMDataGridOptions}.
159
+ *
160
+ * One axis, because the two things a config could set independently — which
161
+ * chrome selects, and what a bare row click does — cannot both be free: a click
162
+ * can either toggle a multi-selection or move the highlight, never both. Folding
163
+ * them into one value makes that conflict unrepresentable rather than something
164
+ * to warn about.
147
165
  */
148
- type TMDataGridRowSelectionMode = "checkbox" | "row";
166
+ type TMDataGridSelectionMode =
167
+ /** Checkbox column, multi-select. Clicking a row elsewhere does nothing. */
168
+ "checkbox" |
169
+ /** No checkbox column; row click multi-selects, with Ctrl/Shift modifiers. */
170
+ "row" |
171
+ /** Checkbox column multi-selects, and a row click highlights one row. */
172
+ "checkboxAndHighlight" |
173
+ /** No selection at all — a row click only highlights. Master-detail. */
174
+ "highlight";
149
175
  type TMDataGridFeatureFlags = {
150
176
  sorting: boolean;
151
177
  filtering: boolean;
@@ -153,19 +179,51 @@ type TMDataGridFeatureFlags = {
153
179
  pinning: boolean;
154
180
  resizing: boolean;
155
181
  ordering: boolean;
182
+ /** Whether any row selection is possible. Off outright under `"highlight"`. */
156
183
  rowSelection: boolean;
157
- /** Only meaningful while `rowSelection` is on. Defaults to `"checkbox"`. */
158
- rowSelectionMode: TMDataGridRowSelectionMode;
184
+ /** Defaults to `"checkbox"`. */
185
+ selectionMode: TMDataGridSelectionMode;
186
+ /** Whether the generated checkbox column is prepended. */
187
+ selectColumn: boolean;
188
+ /** Whether a bare row click toggles the selection. Only under `"row"`. */
189
+ rowClickSelects: boolean;
190
+ /**
191
+ * Whether more than one row can be selected at once — TanStack's
192
+ * `enableMultiRowSelection`. Off, the grid drops the select-all header
193
+ * checkbox: TanStack's `toggleAllRowsSelected` only consults `getCanSelect`,
194
+ * so that control would select every row and walk straight past the limit.
195
+ *
196
+ * A per-row predicate counts as on, since some rows may still multi-select.
197
+ */
198
+ multiRowSelection: boolean;
159
199
  /** Whether a selected row takes the highlight colour. Follows the mode. */
160
- highlightSelectedRows: boolean;
200
+ showSelectedBackground: boolean;
201
+ /**
202
+ * The single highlighted row — clicking a row highlights it, for a detail
203
+ * panel to follow. State of its own, not a slice of `rowSelection`, which is
204
+ * what lets it coexist with a checkbox multi-selection.
205
+ */
206
+ highlightRow: boolean;
161
207
  /**
162
208
  * The one default-off flag: pagination must be asked for, either with the
163
209
  * grid's `enablePagination` or implicitly by declaring `manualPagination`.
164
210
  * Off, the grid renders every filtered row and relies on virtualization.
165
211
  */
166
212
  pagination: boolean;
213
+ /**
214
+ * Row grouping: the "Group by" items in the header menu and the generated
215
+ * tree column. On unless `enableGrouping: false`, since an ungrouped grid
216
+ * looks and behaves exactly as it did before — `grouping` starts empty, and
217
+ * an empty grouping state passes straight through the row model.
218
+ *
219
+ * The exception is `manualPagination`, where the client holds one page rather
220
+ * than the whole set: grouping that page would build groups out of an
221
+ * arbitrary slice and quietly show wrong counts. A server-side grid that does
222
+ * its own grouping can still say `enableGrouping: true` to override.
223
+ */
224
+ grouping: boolean;
167
225
  };
168
- declare function readFeatureFlags<TData extends RowData>(options: Pick<UseTMDataGridOptions<TData>, "enableSorting" | "enableColumnFilters" | "enableHiding" | "enableColumnPinning" | "enableColumnResizing" | "enableColumnOrdering" | "enableRowSelection" | "rowSelectionMode" | "highlightSelectedRows" | "enablePagination" | "manualPagination">): TMDataGridFeatureFlags;
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;
169
227
  /**
170
228
  * What one column's header may offer.
171
229
  *
@@ -177,6 +235,7 @@ declare function readFeatureFlags<TData extends RowData>(options: Pick<UseTMData
177
235
  * | Pin to left / right | `enableColumnPinning` / `enablePinning` |
178
236
  * | Resize dragging | `enableColumnResizing` / `enableResizing` |
179
237
  * | Header dragging, Move left / right | `enableColumnOrdering` / `meta.enableOrdering` |
238
+ * | Group by / Ungroup | `enableGrouping` (table or column) |
180
239
  */
181
240
  type TMDataGridColumnCapabilities = {
182
241
  canSort: boolean;
@@ -185,6 +244,7 @@ type TMDataGridColumnCapabilities = {
185
244
  canPin: boolean;
186
245
  canResize: boolean;
187
246
  canReorder: boolean;
247
+ canGroup: boolean;
188
248
  };
189
249
  declare function getColumnCapabilities(column: Column<TMDataGridFeatures, TMDataGridRowData, unknown>, features: TMDataGridFeatureFlags): TMDataGridColumnCapabilities;
190
250
  /** The same questions, asked of the whole grid — used to hide toolbar buttons. */
@@ -194,6 +254,7 @@ type TMDataGridCapabilities = {
194
254
  canHideAny: boolean;
195
255
  canPinAny: boolean;
196
256
  canReorderAny: boolean;
257
+ canGroupAny: boolean;
197
258
  canSelectRows: boolean;
198
259
  canPaginate: boolean;
199
260
  };
@@ -244,8 +305,12 @@ declare const tmDataGridFeatures: {
244
305
  columnSizingFeature: import("@tanstack/table-core").TableFeature;
245
306
  columnResizingFeature: import("@tanstack/table-core").TableFeature;
246
307
  columnFacetingFeature: import("@tanstack/table-core").TableFeature;
308
+ columnGroupingFeature: import("@tanstack/table-core").TableFeature;
309
+ rowExpandingFeature: import("@tanstack/table-core").TableFeature;
247
310
  filteredRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
311
+ groupedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
248
312
  sortedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
313
+ expandedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
249
314
  paginatedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
250
315
  facetedRowModel: (table: Table<any, any>, columnId: string) => () => import("@tanstack/table-core").RowModel<any, any>;
251
316
  facetedMinMaxValues: (table: Table<import("@tanstack/table-core").TableFeatures, any>, columnId: string) => () => undefined | [number, number];
@@ -296,6 +361,17 @@ declare const tmDataGridFeatures: {
296
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;
297
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;
298
363
  };
364
+ aggregationFns: {
365
+ sum: typeof import("@tanstack/table-core").aggregationFn_sum;
366
+ min: typeof import("@tanstack/table-core").aggregationFn_min;
367
+ max: typeof import("@tanstack/table-core").aggregationFn_max;
368
+ extent: typeof import("@tanstack/table-core").aggregationFn_extent;
369
+ mean: typeof import("@tanstack/table-core").aggregationFn_mean;
370
+ median: typeof import("@tanstack/table-core").aggregationFn_median;
371
+ unique: typeof import("@tanstack/table-core").aggregationFn_unique;
372
+ uniqueCount: typeof import("@tanstack/table-core").aggregationFn_uniqueCount;
373
+ count: typeof import("@tanstack/table-core").aggregationFn_count;
374
+ };
299
375
  tableMeta: TMDataGridTableMeta;
300
376
  columnMeta: TMDataGridColumnMeta;
301
377
  };
@@ -313,8 +389,12 @@ declare function createTMDataGridColumnHelper<TData extends RowData>(): import("
313
389
  columnSizingFeature: import("@tanstack/table-core").TableFeature;
314
390
  columnResizingFeature: import("@tanstack/table-core").TableFeature;
315
391
  columnFacetingFeature: import("@tanstack/table-core").TableFeature;
392
+ columnGroupingFeature: import("@tanstack/table-core").TableFeature;
393
+ rowExpandingFeature: import("@tanstack/table-core").TableFeature;
316
394
  filteredRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
395
+ groupedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
317
396
  sortedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
397
+ expandedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
318
398
  paginatedRowModel: (table: Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
319
399
  facetedRowModel: (table: Table<any, any>, columnId: string) => () => import("@tanstack/table-core").RowModel<any, any>;
320
400
  facetedMinMaxValues: (table: Table<import("@tanstack/table-core").TableFeatures, any>, columnId: string) => () => undefined | [number, number];
@@ -365,6 +445,17 @@ declare function createTMDataGridColumnHelper<TData extends RowData>(): import("
365
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;
366
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;
367
447
  };
448
+ aggregationFns: {
449
+ sum: typeof import("@tanstack/table-core").aggregationFn_sum;
450
+ min: typeof import("@tanstack/table-core").aggregationFn_min;
451
+ max: typeof import("@tanstack/table-core").aggregationFn_max;
452
+ extent: typeof import("@tanstack/table-core").aggregationFn_extent;
453
+ mean: typeof import("@tanstack/table-core").aggregationFn_mean;
454
+ median: typeof import("@tanstack/table-core").aggregationFn_median;
455
+ unique: typeof import("@tanstack/table-core").aggregationFn_unique;
456
+ uniqueCount: typeof import("@tanstack/table-core").aggregationFn_uniqueCount;
457
+ count: typeof import("@tanstack/table-core").aggregationFn_count;
458
+ };
368
459
  tableMeta: TMDataGridTableMeta;
369
460
  columnMeta: TMDataGridColumnMeta;
370
461
  }, TData>;
@@ -383,6 +474,20 @@ type TMDataGridUiState = {
383
474
  * `dataTransfer`, which browsers keep unreadable until the drop.
384
475
  */
385
476
  draggedColumnId: string | null;
477
+ /**
478
+ * The single highlighted row — the one a detail panel would be showing. Its
479
+ * own concept, not a slice of `rowSelection`: under
480
+ * `selectionMode: "checkboxAndHighlight"` the two coexist, and TanStack's one
481
+ * selection map cannot hold both.
482
+ *
483
+ * Not pruned when the row is filtered out, paged away or dropped from `data`,
484
+ * matching how TanStack treats `rowSelection` — nothing there resets it
485
+ * either. The row simply renders unhighlighted, and highlights again if it
486
+ * comes back.
487
+ */
488
+ highlightedRowId: string | null;
489
+ /** The pivot a shift-click extends from. See resolveRowSelectionClick. */
490
+ selectionAnchorRowId: string | null;
386
491
  };
387
492
  type TMDataGridUiActions = {
388
493
  openFilterPanel: (columnId?: string | null) => void;
@@ -391,6 +496,12 @@ type TMDataGridUiActions = {
391
496
  toggleColumnsPanel: () => void;
392
497
  startColumnDrag: (columnId: string) => void;
393
498
  endColumnDrag: () => void;
499
+ /**
500
+ * Moves the active row, or clears it with `null` — which is how a consumer
501
+ * closing its detail panel puts the grid back in step.
502
+ */
503
+ setHighlightedRow: (rowId: string | null) => void;
504
+ setSelectionAnchor: (rowId: string | null) => void;
394
505
  };
395
506
  type TMDataGridUiStore = Store<TMDataGridUiState, TMDataGridUiActions>;
396
507
  /** What `useTMDataGrid` returns — spread straight onto `<TMDataGrid />`. */
@@ -431,18 +542,29 @@ type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridF
431
542
  /**
432
543
  * How rows are selected. Defaults to `"checkbox"`.
433
544
  *
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.
545
+ * | Mode | Checkbox column | Row click |
546
+ * | ---- | --------------- | --------- |
547
+ * | `"checkbox"` | yes, multi-select | nothing |
548
+ * | `"row"` | no | multi-selects, Ctrl/Shift modifiers |
549
+ * | `"checkboxAndHighlight"` | yes, multi-select | highlights one row |
550
+ * | `"highlight"` | no | highlights one row, no selection at all |
438
551
  *
439
- * Ignored when `enableRowSelection` is `false`. Both modes write to the same
440
- * `rowSelection` state.
552
+ * One option rather than two, so the combination that cannot work — a click
553
+ * that both toggles a multi-selection and moves the highlight — is not
554
+ * expressible.
555
+ *
556
+ * The first two write to TanStack's `rowSelection`. The highlight is separate
557
+ * state, which is what lets `"checkboxAndHighlight"` run both at once: tick
558
+ * rows for a bulk action, click one to open its detail panel. See
559
+ * `defaultHighlightedRowId` / `onHighlightedRowChange`.
560
+ *
561
+ * `enableRowSelection` still gates the selection half, predicate form
562
+ * included; under `"highlight"` there is nothing for it to gate.
441
563
  */
442
- rowSelectionMode?: TMDataGridRowSelectionMode;
564
+ selectionMode?: TMDataGridSelectionMode;
443
565
  /**
444
566
  * Give selected rows the highlight background. Defaults to `true` under
445
- * `rowSelectionMode: "row"`, where the highlight is the only feedback a click
567
+ * `selectionMode: "row"`, where the highlight is the only feedback a click
446
568
  * gives, and `false` under `"checkbox"`, where the box already shows it.
447
569
  *
448
570
  * The colour is the `--dg-row-selected-bg` CSS variable, so it can be changed
@@ -455,7 +577,31 @@ type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridF
455
577
  * />
456
578
  * ```
457
579
  */
458
- highlightSelectedRows?: boolean;
580
+ showSelectedBackground?: boolean;
581
+ /**
582
+ * The row that starts out highlighted, under a `selectionMode` that has a
583
+ * highlight. Read once on mount, like `initialState`.
584
+ *
585
+ * The grid never persists the highlighted row. Pair this with
586
+ * {@link onHighlightedRowChange} and keep it wherever it belongs — for a
587
+ * detail panel that is usually the route, which gets you a shareable link and
588
+ * a working back button as well as surviving a reload:
589
+ *
590
+ * ```tsx
591
+ * const { rowId } = useParams();
592
+ * useTMDataGrid({
593
+ * selectionMode: "highlight",
594
+ * defaultHighlightedRowId: rowId,
595
+ * onHighlightedRowChange: (id) => navigate(id ? `/employees/${id}` : "/employees"),
596
+ * });
597
+ * ```
598
+ */
599
+ defaultHighlightedRowId?: string | null;
600
+ /**
601
+ * Called with the newly highlighted row id, or `null` when it is cleared.
602
+ * Fires for `ui.actions.setHighlightedRow` too, not only for clicks.
603
+ */
604
+ onHighlightedRowChange?: (rowId: string | null) => void;
459
605
  };
460
606
  /**
461
607
  * Builds a TMDataGrid table plus its chrome store.
@@ -468,13 +614,50 @@ type UseTMDataGridOptions<TData extends RowData> = Omit<TableOptions<TMDataGridF
468
614
  * flag on, so `<TMDataGrid.Footer />` renders its pager without further
469
615
  * options.
470
616
  */
471
- declare function useTMDataGrid<TData extends RowData>({ persist, enableColumnOrdering, enablePagination, rowSelectionMode, highlightSelectedRows, ...options }: UseTMDataGridOptions<TData>): TMDataGridApi<TData>;
617
+ declare function useTMDataGrid<TData extends RowData>({ persist, enableColumnOrdering, enablePagination, selectionMode, showSelectedBackground, defaultHighlightedRowId, onHighlightedRowChange, ...options }: UseTMDataGridOptions<TData>): TMDataGridApi<TData>;
472
618
  /**
473
619
  * Opens the filter panel for a column, seeding an empty filter row when the
474
620
  * column has none yet — mirrors "Filter" in the column header menu.
475
621
  */
476
622
  declare function openColumnFilter<TData extends RowData>(api: TMDataGridApi<TData>, columnId: string): void;
477
623
  //#endregion
624
+ //#region .types-tmp/components/TMDataGridFilterPills.d.ts
625
+ type TMDataGridFilterPillsProps<TData extends RowData> = {
626
+ /** The object returned by `useTMDataGrid`. */
627
+ api: TMDataGridApi<TData>;
628
+ /** Mantine size of the pills. Defaults to `"sm"`. */
629
+ size?: TMDataGridSize;
630
+ /** "Clear all" button, shown once two filters are active. Defaults to `true`. */
631
+ showClearAll?: boolean;
632
+ /**
633
+ * Replaces what a click on a pill's label does. The default opens the grid's
634
+ * filter panel on that column.
635
+ */
636
+ onPillClick?: (columnId: string) => void;
637
+ className?: string;
638
+ };
639
+ /**
640
+ * One pill per active filter — `First name: Sofia ✕` — with the ✕ clearing that
641
+ * filter and a click on the label opening the filter panel on its column.
642
+ *
643
+ * The one grid component that takes the api as a prop instead of reading
644
+ * context, so it can live anywhere: a page header, a card title, a breadcrumb
645
+ * row. Renders nothing while no filter is active.
646
+ *
647
+ * ```tsx
648
+ * const grid = useTMDataGrid({ data, columns });
649
+ *
650
+ * <Group>
651
+ * <Title order={3}>Employees</Title>
652
+ * <TMDataGridFilterPills api={grid} />
653
+ * </Group>
654
+ * ```
655
+ *
656
+ * Half-typed filters are left out: a filter that is not narrowing the rows yet
657
+ * has nothing to report, which is the same rule the funnel indicator uses.
658
+ */
659
+ declare function TMDataGridFilterPills<TData extends RowData>({ api, size, showClearAll, onPillClick, className }: TMDataGridFilterPillsProps<TData>): import("react").JSX.Element | null;
660
+ //#endregion
478
661
  //#region .types-tmp/components/TMDataGridFooter.d.ts
479
662
  /** Distilled pagination state and actions for building a custom pager. */
480
663
  type TMDataGridPaginationApi = {
@@ -524,12 +707,63 @@ type TMDataGridColumnLayout = {
524
707
  /** Last left-pinned / first right-pinned column — the one that casts the edge. */
525
708
  isBoundary: boolean;
526
709
  };
710
+ /** What a `rowContextMenu` render prop is handed for the right-clicked row. */
711
+ type TMDataGridRowContextMenuArgs<TData extends RowData> = {
712
+ table: Table<TMDataGridFeatures, TData>;
713
+ row: Row<TMDataGridFeatures, TData>;
714
+ /**
715
+ * The cell under the pointer. `null` only when the right-click landed on the
716
+ * row but on no cell — which a custom cell renderer that stops propagation
717
+ * can cause.
718
+ */
719
+ cell: Cell<TMDataGridFeatures, TData, unknown> | null;
720
+ /**
721
+ * Closes the menu. `Menu.Item` already closes on click (Mantine's
722
+ * `closeOnItemClick`), so this is for content that isn't a menu item.
723
+ */
724
+ close: () => void;
725
+ };
726
+ /**
727
+ * Builds the contents of a row's context menu — `Menu.Item`, `Menu.Label`,
728
+ * `Menu.Divider`, `Menu.Sub`, or any other node. The grid owns the `Menu` and
729
+ * its `Menu.Dropdown`; this fills the dropdown.
730
+ */
731
+ type TMDataGridRowContextMenu<TData extends RowData> = (args: TMDataGridRowContextMenuArgs<TData>) => ReactNode;
527
732
  type TMDataGridTableProps<TData extends RowData> = {
528
733
  /**
529
734
  * Called when a body row is clicked. Runs in addition to row selection under
530
- * `rowSelectionMode: "row"`, not instead of it.
735
+ * `selectionMode: "row"`, not instead of it.
531
736
  */
532
737
  onRowClick?: (row: Row<TMDataGridFeatures, TData>) => void;
738
+ /**
739
+ * Contents of the menu a right-click on a row opens, at the pointer. Return
740
+ * `null` to leave a row without one — the browser's own menu stays suppressed
741
+ * either way.
742
+ *
743
+ * ```tsx
744
+ * <TMDataGrid.Table<Employee>
745
+ * rowContextMenu={({ row, close }) => (
746
+ * <>
747
+ * <Menu.Label>{row.original.firstName}</Menu.Label>
748
+ * <Menu.Item onClick={() => open(row.original.id)}>Open</Menu.Item>
749
+ * <Menu.Divider />
750
+ * <Menu.Item color="red" onClick={() => remove(row.original.id)}>
751
+ * Delete
752
+ * </Menu.Item>
753
+ * </>
754
+ * )}
755
+ * />
756
+ * ```
757
+ *
758
+ * Called during render, and only for the row whose menu is open — so it stays
759
+ * a pure function of the row, and cost per row does not matter.
760
+ */
761
+ rowContextMenu?: TMDataGridRowContextMenu<TData>;
762
+ /**
763
+ * Passed to the Mantine `Menu` the grid wraps the row in — `width`, `shadow`,
764
+ * `position`, `transitionProps` and the rest. Its open state is the grid's.
765
+ */
766
+ rowContextMenuProps?: Omit<MenuProps, "opened" | "onChange" | "children">;
533
767
  };
534
768
  /**
535
769
  * The scrollable grid surface. Always virtualized: only the rows inside the
@@ -537,7 +771,7 @@ type TMDataGridTableProps<TData extends RowData> = {
537
771
  * no-pagination mode viable at any row count. Pagination is opt-in via
538
772
  * `enablePagination` (or implied by `manualPagination`).
539
773
  */
540
- declare function TMDataGridTable$1<TData extends RowData = TMDataGridRowData>({ onRowClick }: TMDataGridTableProps<TData>): import("react").JSX.Element;
774
+ declare function TMDataGridTable$1<TData extends RowData = TMDataGridRowData>({ onRowClick, rowContextMenu, rowContextMenuProps }: TMDataGridTableProps<TData>): import("react").JSX.Element;
541
775
  //#endregion
542
776
  //#region .types-tmp/components/TMDataGridToolbar.d.ts
543
777
  /** Row above the grid. Compose it from the pieces below, or anything else. */
@@ -609,6 +843,11 @@ declare const TMDataGrid: typeof TMDataGridRoot & {
609
843
  Footer: typeof TMDataGridFooter;
610
844
  /** Rendered by `TMDataGrid.Table`; exported for custom layouts. */
611
845
  FilterPanel: typeof TMDataGridFilterPanel;
846
+ /**
847
+ * Takes the grid as an `api` prop rather than from context, so it can be
848
+ * rendered outside `<TMDataGrid>` — a page header, for instance.
849
+ */
850
+ FilterPills: typeof TMDataGridFilterPills;
612
851
  /** Rendered by `TMDataGrid.ColumnsButton`; exported for custom layouts. */
613
852
  ColumnsPanel: typeof TMDataGridColumnsPanel;
614
853
  };
@@ -616,6 +855,17 @@ declare const TMDataGrid: typeof TMDataGridRoot & {
616
855
  //#region .types-tmp/components/TMDataGridSelectColumn.d.ts
617
856
  declare const SELECT_COLUMN_ID = "__select__";
618
857
  //#endregion
858
+ //#region .types-tmp/components/TMDataGridGroupColumn.d.ts
859
+ declare const GROUP_COLUMN_ID = "__group__";
860
+ /**
861
+ * How a grouping value is written into the tree cell.
862
+ *
863
+ * Deliberately not the grouped column's own `cell` renderer: that renderer is
864
+ * written for a data row and is free to reach into `row.original`, which on a
865
+ * group row is the first leaf's record rather than anything about the group.
866
+ */
867
+ declare function formatGroupValue(value: unknown): string;
868
+ //#endregion
619
869
  //#region .types-tmp/core/columnUtils.d.ts
620
870
  /**
621
871
  * Structural shape of the column bits the chrome reads. Kept minimal so these
@@ -644,6 +894,21 @@ declare function getColumnType(column: ColumnLike): TMDataGridColumnType;
644
894
  */
645
895
  declare function isColumnReorderable(column: ColumnLike): boolean;
646
896
  //#endregion
897
+ //#region .types-tmp/core/grouping.d.ts
898
+ /**
899
+ * The data rows under a group row, at any depth.
900
+ *
901
+ * Not `row.getLeafRows()`, despite the name: that flattens the whole subtree
902
+ * and keeps the branches, so a group nested two deep reports its sub-groups
903
+ * alongside the records. Grouping `city` then `name` would have Stockholm
904
+ * counting four rows and three names as seven, and one tick on it selecting
905
+ * ids that hold no record.
906
+ *
907
+ * A row with no subRows is a data row, which also makes this the identity on an
908
+ * ungrouped grid.
909
+ */
910
+ declare function getGroupDataRows<TData extends RowData>(row: Row<TMDataGridFeatures, TData>): Array<Row<TMDataGridFeatures, TData>>;
911
+ //#endregion
647
912
  //#region .types-tmp/core/columnOrdering.d.ts
648
913
  type GridColumn = Column<TMDataGridFeatures, TMDataGridRowData, unknown>;
649
914
  type GridTable = TMDataGridTable<TMDataGridRowData>;
@@ -694,4 +959,99 @@ declare function getStepTargetColumn({ table, columnId, direction }: ColumnStepA
694
959
  /** Moves a column one position within its lane. Hidden columns are stepped over. */
695
960
  declare function moveColumnByStep({ table, columnId, direction }: ColumnStepArgs): void;
696
961
  //#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 };
962
+ //#region .types-tmp/core/rowSelection.d.ts
963
+ /**
964
+ * Rows in the order they are displayed, which is the order a shift-click range
965
+ * is measured over — so a range follows the active sort and skips filtered-out
966
+ * rows. Under pagination it is the current page, so a range cannot cross a page
967
+ * boundary.
968
+ *
969
+ * Once a column is grouped this includes the group rows, and only the leaves of
970
+ * groups that are open — and paging is suspended, so it is the whole tree. That
971
+ * is the right list for a range: it is what the user can see, and a range that
972
+ * swept collapsed rows would select things off screen. What a group row in the
973
+ * range contributes is decided by {@link getSelectableRowIds}.
974
+ */
975
+ declare function getDisplayedRows<TData extends RowData>(table: TMDataGridTable<TData>, features: TMDataGridFeatureFlags): Array<Row<TMDataGridFeatures, TData>>;
976
+ /**
977
+ * Whether the built-in pager is actually slicing anything.
978
+ *
979
+ * Grouping suspends it. A page can only count one kind of thing, and once the
980
+ * rows are a tree neither answer works: counting every row splits a group
981
+ * across a page boundary and strands the rest of the tree on pages the user has
982
+ * to go looking for, and counting only the top-level rows quietly redefines
983
+ * "rows per page" as groups per page, so a page of 25 can hold thousands of
984
+ * rows. Rather than pick, the grid renders the whole tree and leans on the
985
+ * virtualizer — which is its default mode anyway, pagination being opt-in.
986
+ *
987
+ * `TMDataGrid.Footer` reads this too, and greys the pager out rather than
988
+ * hiding it, so the pager going quiet is visible instead of mysterious.
989
+ */
990
+ declare function isPagingActive<TData extends RowData>(table: TMDataGridTable<TData>, features: TMDataGridFeatureFlags): boolean;
991
+ /**
992
+ * Which modifiers were held. Named for what they mean rather than for the keys,
993
+ * because the keys differ per platform — `toggle` is Ctrl on Windows/Linux and
994
+ * Cmd on macOS.
995
+ */
996
+ type TMDataGridRowClickModifiers = {
997
+ toggle: boolean;
998
+ extend: boolean;
999
+ };
1000
+ type ResolveRowSelectionClickArgs<TData extends RowData> = {
1001
+ /** Displayed order — see {@link getDisplayedRows}. */
1002
+ rows: ReadonlyArray<Row<TMDataGridFeatures, TData>>;
1003
+ rowId: string;
1004
+ /** The pivot a shift-click extends from. */
1005
+ anchorRowId: string | null;
1006
+ modifiers: TMDataGridRowClickModifiers;
1007
+ selection: RowSelectionState;
1008
+ /**
1009
+ * Whether this gesture is allowed to clear rows it did not touch.
1010
+ *
1011
+ * `true` for a bare row click, where replacing is the whole point. `false` for
1012
+ * a checkbox, which is only ever additive — ticking one box has never cleared
1013
+ * the others, and shift-clicking one adds the range rather than becoming it.
1014
+ */
1015
+ canReplaceSelection: boolean;
1016
+ };
1017
+ type ResolvedRowSelection = {
1018
+ selection: RowSelectionState;
1019
+ anchorRowId: string | null;
1020
+ };
1021
+ /**
1022
+ * The row ids one gesture on this row selects.
1023
+ *
1024
+ * A group row is never selected itself: it holds no record, and TanStack
1025
+ * derives its checked state from its descendants. So ticking a group means
1026
+ * ticking every selectable leaf under it, which is also what makes the group's
1027
+ * own box light up.
1028
+ *
1029
+ * Leaves rather than direct children, so one click on a top-level group takes
1030
+ * the whole subtree however deeply it nests.
1031
+ */
1032
+ declare function getSelectableRowIds<TData extends RowData>(row: Row<TMDataGridFeatures, TData>): Array<string>;
1033
+ /**
1034
+ * Turns one click into the next selection, following the convention every
1035
+ * desktop list uses:
1036
+ *
1037
+ * | Gesture | Effect |
1038
+ * | ------- | ------ |
1039
+ * | Click | selection becomes only this row |
1040
+ * | Ctrl/Cmd + click | toggle this row, leave the rest |
1041
+ * | Shift + click | selection becomes the range anchor → this row |
1042
+ * | Ctrl/Cmd + Shift + click | add that range to the selection |
1043
+ *
1044
+ * The anchor is a *pivot*, not "the last row touched": only a plain or
1045
+ * Ctrl-click moves it, which is what lets a run of shift-clicks grow and shrink
1046
+ * the same range from a fixed point.
1047
+ *
1048
+ * Selection state is rebuilt here and handed to `setRowSelection` wholesale
1049
+ * rather than going through `row.toggleSelected()` per row, which would publish
1050
+ * one state update each. That skips TanStack's sub-row cascade, so the cascade
1051
+ * is done here instead: every row in the gesture is expanded through
1052
+ * {@link getSelectableRowIds} before it reaches the map. Under grouping that is
1053
+ * what makes one tick on a group select all of it.
1054
+ */
1055
+ declare function resolveRowSelectionClick<TData extends RowData>({ rows, rowId, anchorRowId, modifiers, selection, canReplaceSelection }: ResolveRowSelectionClickArgs<TData>): ResolvedRowSelection;
1056
+ //#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 };