@tanstack/table-core 9.0.0-beta.73 → 9.0.0-beta.74
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.
- package/dist/features/row-selection/rowSelectionFeature.js +4 -2
- package/dist/features/row-selection/rowSelectionFeature.types.d.ts +19 -2
- package/dist/features/row-selection/rowSelectionFeature.utils.d.ts +13 -6
- package/dist/features/row-selection/rowSelectionFeature.utils.js +87 -23
- package/package.json +1 -1
- package/skills/aggregation/SKILL.md +1 -1
- package/skills/api-not-found/SKILL.md +1 -1
- package/skills/cell-selection/SKILL.md +1 -1
- package/skills/cell-spanning/SKILL.md +1 -1
- package/skills/client-vs-server/SKILL.md +1 -1
- package/skills/column-faceting/SKILL.md +1 -1
- package/skills/column-filtering/SKILL.md +1 -1
- package/skills/column-ordering/SKILL.md +1 -1
- package/skills/column-pinning/SKILL.md +1 -1
- package/skills/column-resizing/SKILL.md +1 -1
- package/skills/column-sizing/SKILL.md +1 -1
- package/skills/column-visibility/SKILL.md +1 -1
- package/skills/core/SKILL.md +1 -1
- package/skills/custom-features/SKILL.md +1 -1
- package/skills/expanding/SKILL.md +1 -1
- package/skills/global-filtering/SKILL.md +1 -1
- package/skills/grouping/SKILL.md +1 -1
- package/skills/migrate-v8-to-v9/SKILL.md +1 -1
- package/skills/pagination/SKILL.md +1 -1
- package/skills/row-pinning/SKILL.md +1 -1
- package/skills/row-selection/SKILL.md +16 -2
- package/skills/sorting/SKILL.md +1 -1
- package/skills/table-features/SKILL.md +1 -1
- package/skills/typescript/SKILL.md +1 -1
|
@@ -85,7 +85,8 @@ const rowSelectionFeature = {
|
|
|
85
85
|
memoDeps: () => [
|
|
86
86
|
table.atoms.rowSelection?.get(),
|
|
87
87
|
table.getFilteredRowModel(),
|
|
88
|
-
table.options.enableRowSelection
|
|
88
|
+
table.options.enableRowSelection,
|
|
89
|
+
table.options.enableSubRowSelection
|
|
89
90
|
]
|
|
90
91
|
},
|
|
91
92
|
table_getIsAllPageRowsSelected: {
|
|
@@ -93,7 +94,8 @@ const rowSelectionFeature = {
|
|
|
93
94
|
memoDeps: () => [
|
|
94
95
|
table.atoms.rowSelection?.get(),
|
|
95
96
|
table.getPaginatedRowModel(),
|
|
96
|
-
table.options.enableRowSelection
|
|
97
|
+
table.options.enableRowSelection,
|
|
98
|
+
table.options.enableSubRowSelection
|
|
97
99
|
]
|
|
98
100
|
},
|
|
99
101
|
table_getIsSomeRowsSelected: {
|
|
@@ -5,7 +5,7 @@ import { TableFeatures } from "../../types/TableFeatures.js";
|
|
|
5
5
|
//#region src/features/row-selection/rowSelectionFeature.types.d.ts
|
|
6
6
|
type RowSelectionState = Record<string, true>;
|
|
7
7
|
/**
|
|
8
|
-
* Controls how toggling a row affects its descendants.
|
|
8
|
+
* Controls how toggling a row affects its descendants and ancestors.
|
|
9
9
|
*/
|
|
10
10
|
interface ToggleSelectedOptions {
|
|
11
11
|
/**
|
|
@@ -13,6 +13,17 @@ interface ToggleSelectedOptions {
|
|
|
13
13
|
* `true`.
|
|
14
14
|
*/
|
|
15
15
|
selectChildren?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Whether ancestor row ids should be removed from the selection when this
|
|
18
|
+
* row is deselected. Useful after a parent cascade wrote the parent id into
|
|
19
|
+
* state and a child is later deselected. Defaults to `false`.
|
|
20
|
+
*
|
|
21
|
+
* Ancestor ids are removed even when the ancestor itself cannot be selected.
|
|
22
|
+
* Like the other targeted deselection paths, pruning is not gated by
|
|
23
|
+
* `enableRowSelection`; only the bulk select-all paths preserve
|
|
24
|
+
* non-selectable rows.
|
|
25
|
+
*/
|
|
26
|
+
deselectParents?: boolean;
|
|
16
27
|
}
|
|
17
28
|
interface TableState_RowSelection {
|
|
18
29
|
rowSelection: RowSelectionState;
|
|
@@ -39,7 +50,8 @@ interface TableOptions_RowSelection<in out TFeatures extends TableFeatures, in o
|
|
|
39
50
|
* Controls whether selecting a parent row also selects its subRows.
|
|
40
51
|
*
|
|
41
52
|
* Provide a predicate to decide per row. This is most useful with expanding or
|
|
42
|
-
* grouping features and defaults to `true`.
|
|
53
|
+
* grouping features and defaults to `true`. Select-all and the all-selected
|
|
54
|
+
* getters also skip descendants of parents that block sub-row selection.
|
|
43
55
|
*/
|
|
44
56
|
enableSubRowSelection?: boolean | ((row: Row<TFeatures, TData>) => boolean);
|
|
45
57
|
/**
|
|
@@ -115,10 +127,12 @@ interface Table_RowSelection<in out TFeatures extends TableFeatures, in out TDat
|
|
|
115
127
|
getSelectedRowIds: () => Array<string>;
|
|
116
128
|
/**
|
|
117
129
|
* Checks whether every selectable row on the current page is selected.
|
|
130
|
+
* Sub-rows whose ancestors block sub-row selection are ignored.
|
|
118
131
|
*/
|
|
119
132
|
getIsAllPageRowsSelected: () => boolean;
|
|
120
133
|
/**
|
|
121
134
|
* Checks whether every selectable filtered row is selected.
|
|
135
|
+
* Sub-rows whose ancestors block sub-row selection are ignored.
|
|
122
136
|
*/
|
|
123
137
|
getIsAllRowsSelected: () => boolean;
|
|
124
138
|
/**
|
|
@@ -163,6 +177,9 @@ interface Table_RowSelection<in out TFeatures extends TableFeatures, in out TDat
|
|
|
163
177
|
}) => void;
|
|
164
178
|
/**
|
|
165
179
|
* Selects/deselects all rows in the table.
|
|
180
|
+
*
|
|
181
|
+
* Deselecting keeps rows that cannot be selected in the selection map unless
|
|
182
|
+
* `opts.deselectAll` is `true`.
|
|
166
183
|
*/
|
|
167
184
|
toggleAllRowsSelected: (value?: boolean, opts?: {
|
|
168
185
|
deselectAll?: boolean;
|
|
@@ -46,7 +46,10 @@ declare function table_resetRowSelection<TFeatures extends TableFeatures, TData
|
|
|
46
46
|
* Selects or deselects every selectable row before grouping.
|
|
47
47
|
*
|
|
48
48
|
* Omitting `value` toggles based on `table_getIsAllRowsSelected(table)`.
|
|
49
|
-
*
|
|
49
|
+
* Selecting skips sub-rows whose ancestors block descent via
|
|
50
|
+
* `enableSubRowSelection`. Deselecting removes matching selectable ids from the
|
|
51
|
+
* existing selection map; rows that cannot be selected keep their selection
|
|
52
|
+
* unless `opts.deselectAll` is `true`.
|
|
50
53
|
*
|
|
51
54
|
* @example
|
|
52
55
|
* ```ts
|
|
@@ -143,7 +146,8 @@ declare function table_getSelectedRowIds<TFeatures extends TableFeatures, TData
|
|
|
143
146
|
* Checks whether every selectable filtered row is selected.
|
|
144
147
|
*
|
|
145
148
|
* The result is false when there are no filtered rows or when selection state is
|
|
146
|
-
* empty.
|
|
149
|
+
* empty. Sub-rows whose ancestors block descent via `enableSubRowSelection` are
|
|
150
|
+
* ignored, matching the rows that `table_toggleAllRowsSelected` selects.
|
|
147
151
|
*
|
|
148
152
|
* @example
|
|
149
153
|
* ```ts
|
|
@@ -154,7 +158,8 @@ declare function table_getIsAllRowsSelected<TFeatures extends TableFeatures, TDa
|
|
|
154
158
|
/**
|
|
155
159
|
* Checks whether every selectable row on the current page is selected.
|
|
156
160
|
*
|
|
157
|
-
* Non-selectable rows are ignored for this calculation
|
|
161
|
+
* Non-selectable rows are ignored for this calculation, as are sub-rows whose
|
|
162
|
+
* ancestors block descent via `enableSubRowSelection`.
|
|
158
163
|
*
|
|
159
164
|
* @example
|
|
160
165
|
* ```ts
|
|
@@ -211,7 +216,8 @@ declare function table_getToggleAllPageRowsSelectedHandler<TFeatures extends Tab
|
|
|
211
216
|
*
|
|
212
217
|
* Omitting `value` toggles the row. Child rows are selected recursively unless
|
|
213
218
|
* `opts.selectChildren` is `false`, sub-row selection is disabled, or the row
|
|
214
|
-
* only supports single selection.
|
|
219
|
+
* only supports single selection. Pass `deselectParents: true` to also remove
|
|
220
|
+
* ancestor row ids from the selection when this row is deselected.
|
|
215
221
|
*
|
|
216
222
|
* @example
|
|
217
223
|
* ```ts
|
|
@@ -219,7 +225,7 @@ declare function table_getToggleAllPageRowsSelectedHandler<TFeatures extends Tab
|
|
|
219
225
|
* row_toggleSelected(row, true)
|
|
220
226
|
* row_toggleSelected(row, false)
|
|
221
227
|
* row_toggleSelected(row, true, { selectChildren: false })
|
|
222
|
-
* row_toggleSelected(row, false, {
|
|
228
|
+
* row_toggleSelected(row, false, { deselectParents: true })
|
|
223
229
|
* ```
|
|
224
230
|
*/
|
|
225
231
|
declare function row_toggleSelected<TFeatures extends TableFeatures, TData extends RowData>(row: Row<TFeatures, TData>, value?: boolean, opts?: ToggleSelectedOptions): void;
|
|
@@ -299,7 +305,8 @@ declare function row_getCanMultiSelect<TFeatures extends TableFeatures, TData ex
|
|
|
299
305
|
* `event.target.checked`. Shift events select or deselect the inclusive range
|
|
300
306
|
* from the most recent selectable row handled by this table. Pass
|
|
301
307
|
* `selectChildren: false` to limit changes to rows explicitly present in the
|
|
302
|
-
* display-order interval
|
|
308
|
+
* display-order interval, and `deselectParents: true` to remove ancestor row
|
|
309
|
+
* ids from the selection when rows are deselected.
|
|
303
310
|
*
|
|
304
311
|
* @example
|
|
305
312
|
* ```ts
|
|
@@ -49,7 +49,10 @@ function table_resetRowSelection(table, defaultState) {
|
|
|
49
49
|
* Selects or deselects every selectable row before grouping.
|
|
50
50
|
*
|
|
51
51
|
* Omitting `value` toggles based on `table_getIsAllRowsSelected(table)`.
|
|
52
|
-
*
|
|
52
|
+
* Selecting skips sub-rows whose ancestors block descent via
|
|
53
|
+
* `enableSubRowSelection`. Deselecting removes matching selectable ids from the
|
|
54
|
+
* existing selection map; rows that cannot be selected keep their selection
|
|
55
|
+
* unless `opts.deselectAll` is `true`.
|
|
53
56
|
*
|
|
54
57
|
* @example
|
|
55
58
|
* ```ts
|
|
@@ -63,11 +66,13 @@ function table_toggleAllRowsSelected(table, value, opts) {
|
|
|
63
66
|
if (opts?.deselectAll && !value) return makeObjectMap();
|
|
64
67
|
const rowSelection = Object.assign(makeObjectMap(), old);
|
|
65
68
|
const preGroupedFlatRows = table.getPreGroupedRowModel().flatRows;
|
|
66
|
-
if (value)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
if (value) {
|
|
70
|
+
const subtreeCache = /* @__PURE__ */ new Map();
|
|
71
|
+
preGroupedFlatRows.forEach((row) => {
|
|
72
|
+
if (isRowSelectableInSelectAll(row, subtreeCache)) rowSelection[row.id] = true;
|
|
73
|
+
});
|
|
74
|
+
} else preGroupedFlatRows.forEach((row) => {
|
|
75
|
+
if (row_getCanSelect(row)) delete rowSelection[row.id];
|
|
71
76
|
});
|
|
72
77
|
return rowSelection;
|
|
73
78
|
});
|
|
@@ -90,7 +95,7 @@ function table_toggleAllPageRowsSelected(table, value, opts) {
|
|
|
90
95
|
if (opts?.deselectAll && !resolvedValue) return makeObjectMap();
|
|
91
96
|
const rowSelection = Object.assign(makeObjectMap(), old);
|
|
92
97
|
table.getRowModel().rows.forEach((row) => {
|
|
93
|
-
mutateRowIsSelected(rowSelection, row.id, resolvedValue, true, table);
|
|
98
|
+
mutateRowIsSelected(rowSelection, row.id, resolvedValue, true, table, true);
|
|
94
99
|
});
|
|
95
100
|
return rowSelection;
|
|
96
101
|
});
|
|
@@ -184,7 +189,8 @@ function table_getSelectedRowIds(table) {
|
|
|
184
189
|
* Checks whether every selectable filtered row is selected.
|
|
185
190
|
*
|
|
186
191
|
* The result is false when there are no filtered rows or when selection state is
|
|
187
|
-
* empty.
|
|
192
|
+
* empty. Sub-rows whose ancestors block descent via `enableSubRowSelection` are
|
|
193
|
+
* ignored, matching the rows that `table_toggleAllRowsSelected` selects.
|
|
188
194
|
*
|
|
189
195
|
* @example
|
|
190
196
|
* ```ts
|
|
@@ -196,14 +202,16 @@ function table_getIsAllRowsSelected(table) {
|
|
|
196
202
|
const rowSelection = table.atoms.rowSelection?.get() ?? {};
|
|
197
203
|
let isAllRowsSelected = Boolean(preGroupedFlatRows.length && Object.keys(rowSelection).length);
|
|
198
204
|
if (isAllRowsSelected) {
|
|
199
|
-
|
|
205
|
+
const subtreeCache = /* @__PURE__ */ new Map();
|
|
206
|
+
if (preGroupedFlatRows.some((row) => !isRowSelected(row, rowSelection) && isRowSelectableInSelectAll(row, subtreeCache))) isAllRowsSelected = false;
|
|
200
207
|
}
|
|
201
208
|
return isAllRowsSelected;
|
|
202
209
|
}
|
|
203
210
|
/**
|
|
204
211
|
* Checks whether every selectable row on the current page is selected.
|
|
205
212
|
*
|
|
206
|
-
* Non-selectable rows are ignored for this calculation
|
|
213
|
+
* Non-selectable rows are ignored for this calculation, as are sub-rows whose
|
|
214
|
+
* ancestors block descent via `enableSubRowSelection`.
|
|
207
215
|
*
|
|
208
216
|
* @example
|
|
209
217
|
* ```ts
|
|
@@ -211,11 +219,17 @@ function table_getIsAllRowsSelected(table) {
|
|
|
211
219
|
* ```
|
|
212
220
|
*/
|
|
213
221
|
function table_getIsAllPageRowsSelected(table) {
|
|
214
|
-
const paginationFlatRows = table.getPaginatedRowModel().flatRows
|
|
222
|
+
const paginationFlatRows = table.getPaginatedRowModel().flatRows;
|
|
215
223
|
const rowSelection = table.atoms.rowSelection?.get() ?? {};
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
224
|
+
const subtreeCache = /* @__PURE__ */ new Map();
|
|
225
|
+
let sawSelectableRow = false;
|
|
226
|
+
for (let i = 0; i < paginationFlatRows.length; i++) {
|
|
227
|
+
const row = paginationFlatRows[i];
|
|
228
|
+
if (!isRowSelected(row, rowSelection)) {
|
|
229
|
+
if (isRowSelectableInSelectAll(row, subtreeCache)) return false;
|
|
230
|
+
} else if (!sawSelectableRow && isRowSelectableInSelectAll(row, subtreeCache)) sawSelectableRow = true;
|
|
231
|
+
}
|
|
232
|
+
return sawSelectableRow;
|
|
219
233
|
}
|
|
220
234
|
/**
|
|
221
235
|
* Checks whether at least one row id is selected.
|
|
@@ -278,7 +292,8 @@ function table_getToggleAllPageRowsSelectedHandler(table) {
|
|
|
278
292
|
*
|
|
279
293
|
* Omitting `value` toggles the row. Child rows are selected recursively unless
|
|
280
294
|
* `opts.selectChildren` is `false`, sub-row selection is disabled, or the row
|
|
281
|
-
* only supports single selection.
|
|
295
|
+
* only supports single selection. Pass `deselectParents: true` to also remove
|
|
296
|
+
* ancestor row ids from the selection when this row is deselected.
|
|
282
297
|
*
|
|
283
298
|
* @example
|
|
284
299
|
* ```ts
|
|
@@ -286,7 +301,7 @@ function table_getToggleAllPageRowsSelectedHandler(table) {
|
|
|
286
301
|
* row_toggleSelected(row, true)
|
|
287
302
|
* row_toggleSelected(row, false)
|
|
288
303
|
* row_toggleSelected(row, true, { selectChildren: false })
|
|
289
|
-
* row_toggleSelected(row, false, {
|
|
304
|
+
* row_toggleSelected(row, false, { deselectParents: true })
|
|
290
305
|
* ```
|
|
291
306
|
*/
|
|
292
307
|
function row_toggleSelected(row, value, opts) {
|
|
@@ -295,6 +310,7 @@ function row_toggleSelected(row, value, opts) {
|
|
|
295
310
|
value = typeof value !== "undefined" ? value : !isSelected;
|
|
296
311
|
const rowSelection = Object.assign(makeObjectMap(), old);
|
|
297
312
|
mutateRowIsSelected(rowSelection, row.id, value, (opts?.selectChildren ?? true) && row_getCanMultiSelect(row), row.table);
|
|
313
|
+
if (!value && opts?.deselectParents) pruneAncestorRowIds(rowSelection, row);
|
|
298
314
|
return rowSelection;
|
|
299
315
|
});
|
|
300
316
|
}
|
|
@@ -392,7 +408,8 @@ function row_getCanMultiSelect(row) {
|
|
|
392
408
|
* `event.target.checked`. Shift events select or deselect the inclusive range
|
|
393
409
|
* from the most recent selectable row handled by this table. Pass
|
|
394
410
|
* `selectChildren: false` to limit changes to rows explicitly present in the
|
|
395
|
-
* display-order interval
|
|
411
|
+
* display-order interval, and `deselectParents: true` to remove ancestor row
|
|
412
|
+
* ids from the selection when rows are deselected.
|
|
396
413
|
*
|
|
397
414
|
* @example
|
|
398
415
|
* ```ts
|
|
@@ -407,7 +424,7 @@ function row_getToggleSelectedHandler(row, opts) {
|
|
|
407
424
|
const table = row.table;
|
|
408
425
|
const checked = event.target.checked;
|
|
409
426
|
const anchorId = table._lastSelectedRowId;
|
|
410
|
-
if (!(table.options.enableRowRangeSelection !== false && anchorId !== null && row_getCanMultiSelect(row) && (table.options.isRowRangeSelectionEvent?.(e) ?? false)) || !selectRowRange(row, anchorId, checked, opts
|
|
427
|
+
if (!(table.options.enableRowRangeSelection !== false && anchorId !== null && row_getCanMultiSelect(row) && (table.options.isRowRangeSelectionEvent?.(e) ?? false)) || !selectRowRange(row, anchorId, checked, opts)) row_toggleSelected(row, checked, opts);
|
|
411
428
|
table._lastSelectedRowId = row.id;
|
|
412
429
|
};
|
|
413
430
|
}
|
|
@@ -422,7 +439,8 @@ function row_getToggleSelectedHandler(row, opts) {
|
|
|
422
439
|
* selection updater; non-selectable and non-multi-selectable rows are skipped.
|
|
423
440
|
* Returns `false` when the interaction should fall back to an ordinary toggle.
|
|
424
441
|
*/
|
|
425
|
-
function selectRowRange(row, anchorId, value,
|
|
442
|
+
function selectRowRange(row, anchorId, value, opts) {
|
|
443
|
+
const includeChildren = opts?.selectChildren ?? true;
|
|
426
444
|
const table = row.table;
|
|
427
445
|
const rows = table.getRowsInDisplayOrder();
|
|
428
446
|
const anchorRow = table.getPrePaginatedRowModel().rowsById[anchorId] ?? table.getCoreRowModel().rowsById[anchorId];
|
|
@@ -440,19 +458,65 @@ function selectRowRange(row, anchorId, value, includeChildren) {
|
|
|
440
458
|
const rangeRow = rows[index];
|
|
441
459
|
if (!row_getCanSelect(rangeRow) || !row_getCanMultiSelect(rangeRow)) continue;
|
|
442
460
|
mutateRowIsSelected(rowSelection, rangeRow.id, value, includeChildren, table);
|
|
461
|
+
if (!value && opts?.deselectParents) pruneAncestorRowIds(rowSelection, rangeRow);
|
|
443
462
|
}
|
|
444
463
|
return rowSelection;
|
|
445
464
|
});
|
|
446
465
|
return true;
|
|
447
466
|
}
|
|
448
|
-
|
|
467
|
+
function mutateRowIsSelected(rowSelection, rowId, value, includeChildren, table, respectCanSelectOnDeselect) {
|
|
449
468
|
const row = table.getRow(rowId, true);
|
|
450
469
|
if (value) {
|
|
451
470
|
if (!row_getCanMultiSelect(row)) Object.keys(rowSelection).forEach((key) => delete rowSelection[key]);
|
|
452
471
|
if (row_getCanSelect(row)) rowSelection[rowId] = true;
|
|
453
|
-
} else delete rowSelection[rowId];
|
|
454
|
-
if (includeChildren && row.subRows.length && row_getCanSelectSubRows(row)) row.subRows.forEach((r) => mutateRowIsSelected(rowSelection, r.id, value, includeChildren, table));
|
|
455
|
-
}
|
|
472
|
+
} else if (!respectCanSelectOnDeselect || row_getCanSelect(row)) delete rowSelection[rowId];
|
|
473
|
+
if (includeChildren && row.subRows.length && row_getCanSelectSubRows(row)) row.subRows.forEach((r) => mutateRowIsSelected(rowSelection, r.id, value, includeChildren, table, respectCanSelectOnDeselect));
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Returns whether a select-all cascade can reach this row: the row itself is
|
|
477
|
+
* selectable and no ancestor blocks descent via `enableSubRowSelection`.
|
|
478
|
+
*
|
|
479
|
+
* `subtreeCache` memoizes the per-ancestor verdict for one select-all pass, so
|
|
480
|
+
* ancestor chains shared by sibling rows are only walked (and the
|
|
481
|
+
* `enableSubRowSelection` predicate only invoked) once per unique ancestor.
|
|
482
|
+
*/
|
|
483
|
+
function isRowSelectableInSelectAll(row, subtreeCache) {
|
|
484
|
+
if (!row_getCanSelect(row)) return false;
|
|
485
|
+
const table = row.table;
|
|
486
|
+
if (table.options.enableSubRowSelection === true) return true;
|
|
487
|
+
const parentId = row.parentId;
|
|
488
|
+
if (parentId === void 0) return true;
|
|
489
|
+
const cached = subtreeCache.get(parentId);
|
|
490
|
+
if (cached !== void 0) return cached;
|
|
491
|
+
const rowsById = table.getCoreRowModel().rowsById;
|
|
492
|
+
const visited = [];
|
|
493
|
+
let selectable = true;
|
|
494
|
+
let currentId = parentId;
|
|
495
|
+
while (currentId !== void 0) {
|
|
496
|
+
const known = subtreeCache.get(currentId);
|
|
497
|
+
if (known !== void 0) {
|
|
498
|
+
selectable = known;
|
|
499
|
+
break;
|
|
500
|
+
}
|
|
501
|
+
visited.push(currentId);
|
|
502
|
+
const parent = rowsById[currentId] ?? table.getRow(currentId, true);
|
|
503
|
+
if (!row_getCanSelectSubRows(parent)) {
|
|
504
|
+
selectable = false;
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
currentId = parent.parentId;
|
|
508
|
+
}
|
|
509
|
+
visited.forEach((id) => subtreeCache.set(id, selectable));
|
|
510
|
+
return selectable;
|
|
511
|
+
}
|
|
512
|
+
function pruneAncestorRowIds(rowSelection, row) {
|
|
513
|
+
const rowsById = row.table.getCoreRowModel().rowsById;
|
|
514
|
+
let parentId = row.parentId;
|
|
515
|
+
while (parentId !== void 0) {
|
|
516
|
+
delete rowSelection[parentId];
|
|
517
|
+
parentId = (rowsById[parentId] ?? row.table.getRow(parentId, true)).parentId;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
456
520
|
function selectRowsRecursively(rows, rowSelection, selectedFlatRows, selectedRowsById) {
|
|
457
521
|
const result = [];
|
|
458
522
|
for (let i = 0; i < rows.length; i++) {
|
package/package.json
CHANGED
package/skills/core/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ description: >
|
|
|
5
5
|
metadata:
|
|
6
6
|
type: sub-skill
|
|
7
7
|
library: '@tanstack/table-core'
|
|
8
|
-
library_version: '9.0.0-beta.
|
|
8
|
+
library_version: '9.0.0-beta.74'
|
|
9
9
|
requires: ['core', 'table-features', 'typescript']
|
|
10
10
|
sources:
|
|
11
11
|
- 'TanStack/table:docs/framework/react/guide/custom-features.md'
|
package/skills/grouping/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ description: >
|
|
|
5
5
|
metadata:
|
|
6
6
|
type: lifecycle
|
|
7
7
|
library: '@tanstack/table-core'
|
|
8
|
-
library_version: '9.0.0-beta.
|
|
8
|
+
library_version: '9.0.0-beta.74'
|
|
9
9
|
requires: ['core', 'table-features', 'typescript']
|
|
10
10
|
sources:
|
|
11
11
|
- 'TanStack/table:docs/framework/react/guide/migrating.md'
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: row-selection
|
|
3
3
|
description: >
|
|
4
|
-
Maintain rowSelection ID state with stable getRowId, single, multi, subrow, and Shift-range rules, selected row models, handler anchors, and manual-pagination semantics. Load when implementing getToggleSelectedHandler, enableRowRangeSelection, selectChildren, or selected IDs that outlive loaded Row objects.
|
|
4
|
+
Maintain rowSelection ID state with stable getRowId, single, multi, subrow, and Shift-range rules, selected row models, handler anchors, and manual-pagination semantics. Load when implementing getToggleSelectedHandler, enableRowRangeSelection, selectChildren, deselectParents, or selected IDs that outlive loaded Row objects.
|
|
5
5
|
metadata:
|
|
6
6
|
{
|
|
7
7
|
type: sub-skill,
|
|
8
8
|
library: '@tanstack/table-core',
|
|
9
|
-
library_version: '9.0.0-beta.
|
|
9
|
+
library_version: '9.0.0-beta.74',
|
|
10
10
|
}
|
|
11
11
|
requires: ['core', 'table-features']
|
|
12
12
|
sources:
|
|
@@ -65,6 +65,20 @@ export function getDisplayedRowsOnlyHandler(row: Row<typeof features, Person>) {
|
|
|
65
65
|
|
|
66
66
|
The default `selectChildren: true` recursively changes selectable descendants of parents encountered in the range. Set it to `false` when collapsed descendants outside the display-order interval must remain unchanged.
|
|
67
67
|
|
|
68
|
+
### Prune stale parent ids on child deselection
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
export function getPruningHandler(row: Row<typeof features, Person>) {
|
|
72
|
+
return row.getToggleSelectedHandler({ deselectParents: true })
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Selecting a parent cascades its id plus selectable descendant ids into state, but deselecting a child later leaves the parent id behind by default (some tables treat state ids as literal selections, e.g. with `selectChildren: false`). The default `deselectParents: false` preserves that; set it to `true` so deselecting any row also deletes every ancestor id, keeping `row.getIsSelected()` honest for parents. Applies to `toggleSelected` and both plain and Shift-range handler paths.
|
|
77
|
+
|
|
78
|
+
### Select-all honors sub-row selection rules
|
|
79
|
+
|
|
80
|
+
With `enableSubRowSelection: false` (or a per-row predicate), `table.toggleAllRowsSelected()` skips descendants of blocking parents, and `getIsAllRowsSelected()`/`getIsAllPageRowsSelected()` exclude those descendants from the all-selected computation, so the header checkbox still reads checked. Deselect-all skips rows whose `enableRowSelection` resolves false, preserving their selection; use `toggleAllRowsSelected(false, { deselectAll: true })` or `resetRowSelection(true)` to clear everything including disabled and out-of-model ids.
|
|
81
|
+
|
|
68
82
|
## Common Mistakes
|
|
69
83
|
|
|
70
84
|
### [HIGH] Expecting selection to clean itself
|
package/skills/sorting/SKILL.md
CHANGED