@proyecto-viviana/solid-stately 0.2.7 → 0.4.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.
- package/README.md +30 -283
- package/dist/autocomplete/createAutocompleteState.d.ts +2 -2
- package/dist/autocomplete/index.d.ts +1 -1
- package/dist/calendar/IncompleteDate.d.ts +61 -0
- package/dist/calendar/createCalendarState.d.ts +41 -16
- package/dist/calendar/createDateFieldState.d.ts +39 -9
- package/dist/calendar/createDatePickerState.d.ts +60 -0
- package/dist/calendar/createRangeCalendarState.d.ts +37 -10
- package/dist/calendar/createTimeFieldState.d.ts +34 -7
- package/dist/calendar/index.d.ts +7 -6
- package/dist/checkbox/createCheckboxGroupState.d.ts +6 -6
- package/dist/checkbox/index.d.ts +1 -1
- package/dist/collections/ListCollection.d.ts +1 -1
- package/dist/collections/createListState.d.ts +11 -8
- package/dist/collections/createMenuState.d.ts +7 -7
- package/dist/collections/createSelectionState.d.ts +22 -10
- package/dist/collections/getChildNodes.d.ts +11 -0
- package/dist/collections/index.d.ts +6 -5
- package/dist/collections/types.d.ts +12 -12
- package/dist/color/Color.d.ts +1 -1
- package/dist/color/createColorAreaState.d.ts +4 -2
- package/dist/color/createColorFieldState.d.ts +38 -12
- package/dist/color/createColorSliderState.d.ts +9 -2
- package/dist/color/createColorWheelState.d.ts +13 -2
- package/dist/color/getColorChannels.d.ts +1 -1
- package/dist/color/index.d.ts +6 -6
- package/dist/color/types.d.ts +4 -4
- package/dist/combobox/createComboBoxState.d.ts +34 -13
- package/dist/combobox/index.d.ts +1 -1
- package/dist/data/createAsyncList.d.ts +4 -4
- package/dist/data/createListData.d.ts +2 -2
- package/dist/data/createTreeData.d.ts +6 -2
- package/dist/data/index.d.ts +3 -3
- package/dist/datepicker/index.d.ts +2 -4
- package/dist/disclosure/createDisclosureState.d.ts +2 -2
- package/dist/disclosure/index.d.ts +1 -1
- package/dist/dnd/createDragState.d.ts +2 -2
- package/dist/dnd/createDraggableCollectionState.d.ts +2 -2
- package/dist/dnd/createDropState.d.ts +2 -2
- package/dist/dnd/createDroppableCollectionState.d.ts +3 -3
- package/dist/dnd/index.d.ts +5 -5
- package/dist/dnd/types.d.ts +19 -17
- package/dist/form/createFormValidationState.d.ts +3 -3
- package/dist/form/index.d.ts +1 -1
- package/dist/grid/createGridState.d.ts +2 -2
- package/dist/grid/index.d.ts +2 -2
- package/dist/grid/types.d.ts +27 -11
- package/dist/index.d.ts +31 -30
- package/dist/index.js +9077 -7246
- package/dist/index.js.map +1 -1
- package/dist/menu/index.d.ts +2 -2
- package/dist/numberfield/createNumberFieldState.d.ts +2 -2
- package/dist/numberfield/index.d.ts +1 -1
- package/dist/overlays/createOverlayTriggerState.d.ts +2 -2
- package/dist/overlays/index.d.ts +1 -1
- package/dist/radio/createRadioGroupState.d.ts +7 -7
- package/dist/radio/index.d.ts +1 -1
- package/dist/searchfield/createSearchFieldState.d.ts +2 -2
- package/dist/searchfield/index.d.ts +2 -2
- package/dist/select/createSelectState.d.ts +14 -8
- package/dist/select/index.d.ts +1 -1
- package/dist/selection/Selection.d.ts +16 -0
- package/dist/selection/SelectionManager.d.ts +110 -0
- package/dist/selection/createMultipleSelectionState.d.ts +59 -0
- package/dist/selection/index.d.ts +6 -5
- package/dist/slider/createSliderState.d.ts +3 -3
- package/dist/slider/index.d.ts +2 -2
- package/dist/steplist/createStepListState.d.ts +48 -0
- package/dist/steplist/index.d.ts +1 -0
- package/dist/table/TableCollection.d.ts +33 -3
- package/dist/table/createTableColumnResizeState.d.ts +54 -0
- package/dist/table/createTableState.d.ts +2 -2
- package/dist/table/createTreeGridState.d.ts +15 -0
- package/dist/table/index.d.ts +6 -3
- package/dist/table/types.d.ts +68 -10
- package/dist/tabs/createTabListState.d.ts +5 -5
- package/dist/tabs/index.d.ts +1 -1
- package/dist/textfield/createTextFieldState.d.ts +2 -2
- package/dist/textfield/index.d.ts +1 -1
- package/dist/toast/createToastState.d.ts +24 -2
- package/dist/toast/index.d.ts +1 -1
- package/dist/toggle/createToggleGroupState.d.ts +4 -4
- package/dist/toggle/createToggleState.d.ts +2 -2
- package/dist/toggle/index.d.ts +2 -2
- package/dist/tooltip/createTooltipTriggerState.d.ts +2 -2
- package/dist/tooltip/index.d.ts +1 -1
- package/dist/tree/TreeCollection.d.ts +2 -2
- package/dist/tree/createTreeState.d.ts +2 -2
- package/dist/tree/index.d.ts +3 -3
- package/dist/tree/types.d.ts +27 -13
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/reactivity.d.ts +1 -1
- package/package.json +29 -30
- package/src/autocomplete/createAutocompleteState.d.ts +19 -17
- package/src/autocomplete/createAutocompleteState.ts +24 -30
- package/src/autocomplete/index.d.ts +6 -2
- package/src/autocomplete/index.ts +1 -1
- package/src/calendar/IncompleteDate.ts +430 -0
- package/src/calendar/createCalendarState.d.ts +139 -117
- package/src/calendar/createCalendarState.ts +308 -94
- package/src/calendar/createDateFieldState.d.ts +130 -95
- package/src/calendar/createDateFieldState.ts +447 -334
- package/src/calendar/createDatePickerState.ts +347 -0
- package/src/calendar/createRangeCalendarState.d.ts +154 -129
- package/src/calendar/createRangeCalendarState.ts +411 -85
- package/src/calendar/createTimeFieldState.d.ts +81 -79
- package/src/calendar/createTimeFieldState.ts +187 -108
- package/src/calendar/index.d.ts +80 -7
- package/src/calendar/index.ts +23 -12
- package/src/checkbox/createCheckboxGroupState.d.ts +57 -55
- package/src/checkbox/createCheckboxGroupState.ts +20 -29
- package/src/checkbox/index.d.ts +6 -2
- package/src/checkbox/index.ts +1 -1
- package/src/collections/ListCollection.d.ts +25 -22
- package/src/collections/ListCollection.ts +6 -6
- package/src/collections/createListState.d.ts +73 -58
- package/src/collections/createListState.ts +67 -35
- package/src/collections/createMenuState.d.ts +36 -31
- package/src/collections/createMenuState.ts +21 -12
- package/src/collections/createSelectionState.d.ts +78 -65
- package/src/collections/createSelectionState.ts +66 -52
- package/src/collections/getChildNodes.ts +98 -0
- package/src/collections/index.d.ts +38 -6
- package/src/collections/index.ts +14 -10
- package/src/collections/types.d.ts +101 -101
- package/src/collections/types.ts +12 -12
- package/src/color/Color.d.ts +20 -5
- package/src/color/Color.ts +357 -254
- package/src/color/createColorAreaState.d.ts +67 -65
- package/src/color/createColorAreaState.ts +21 -13
- package/src/color/createColorFieldState.d.ts +46 -44
- package/src/color/createColorFieldState.ts +285 -149
- package/src/color/createColorSliderState.d.ts +58 -56
- package/src/color/createColorSliderState.ts +45 -14
- package/src/color/createColorWheelState.d.ts +42 -40
- package/src/color/createColorWheelState.ts +101 -64
- package/src/color/getColorChannels.ts +7 -5
- package/src/color/index.d.ts +36 -7
- package/src/color/index.ts +6 -9
- package/src/color/types.d.ts +68 -63
- package/src/color/types.ts +11 -19
- package/src/combobox/createComboBoxState.d.ts +107 -105
- package/src/combobox/createComboBoxState.ts +184 -89
- package/src/combobox/index.d.ts +10 -2
- package/src/combobox/index.ts +1 -1
- package/src/data/createAsyncList.ts +89 -63
- package/src/data/createListData.ts +67 -67
- package/src/data/createTreeData.ts +304 -91
- package/src/data/index.ts +3 -3
- package/src/datepicker/index.ts +6 -10
- package/src/disclosure/createDisclosureState.d.ts +47 -43
- package/src/disclosure/createDisclosureState.ts +7 -21
- package/src/disclosure/index.d.ts +10 -2
- package/src/disclosure/index.ts +1 -1
- package/src/dnd/createDragState.d.ts +51 -42
- package/src/dnd/createDragState.ts +12 -14
- package/src/dnd/createDraggableCollectionState.d.ts +52 -41
- package/src/dnd/createDraggableCollectionState.ts +14 -21
- package/src/dnd/createDropState.d.ts +64 -45
- package/src/dnd/createDropState.ts +22 -32
- package/src/dnd/createDroppableCollectionState.d.ts +88 -59
- package/src/dnd/createDroppableCollectionState.ts +40 -43
- package/src/dnd/index.d.ts +55 -6
- package/src/dnd/index.ts +6 -18
- package/src/dnd/types.d.ts +170 -157
- package/src/dnd/types.ts +24 -22
- package/src/form/createFormValidationState.d.ts +47 -45
- package/src/form/createFormValidationState.ts +30 -63
- package/src/form/index.d.ts +16 -2
- package/src/form/index.ts +1 -1
- package/src/grid/createGridState.d.ts +7 -4
- package/src/grid/createGridState.ts +78 -51
- package/src/grid/index.d.ts +3 -3
- package/src/grid/index.ts +2 -8
- package/src/grid/types.d.ts +136 -129
- package/src/grid/types.ts +34 -18
- package/src/index.d.ts +311 -26
- package/src/index.ts +59 -89
- package/src/menu/index.ts +2 -4
- package/src/numberfield/createNumberFieldState.d.ts +56 -54
- package/src/numberfield/createNumberFieldState.ts +26 -31
- package/src/numberfield/index.d.ts +6 -2
- package/src/numberfield/index.ts +1 -1
- package/src/overlays/createOverlayTriggerState.d.ts +22 -20
- package/src/overlays/createOverlayTriggerState.ts +3 -4
- package/src/overlays/index.d.ts +6 -2
- package/src/overlays/index.ts +1 -1
- package/src/radio/createRadioGroupState.d.ts +54 -52
- package/src/radio/createRadioGroupState.ts +27 -29
- package/src/radio/index.d.ts +7 -2
- package/src/radio/index.ts +1 -1
- package/src/searchfield/createSearchFieldState.d.ts +16 -14
- package/src/searchfield/createSearchFieldState.ts +5 -11
- package/src/searchfield/index.d.ts +3 -3
- package/src/searchfield/index.ts +2 -5
- package/src/select/createSelectState.d.ts +63 -61
- package/src/select/createSelectState.ts +42 -29
- package/src/select/index.d.ts +2 -2
- package/src/select/index.ts +1 -5
- package/src/selection/Selection.ts +28 -0
- package/src/selection/SelectionManager.ts +526 -0
- package/src/selection/createMultipleSelectionState.ts +247 -0
- package/src/selection/index.ts +12 -7
- package/src/slider/createSliderState.d.ts +60 -60
- package/src/slider/createSliderState.ts +55 -33
- package/src/slider/index.d.ts +3 -3
- package/src/slider/index.ts +2 -6
- package/src/ssr/index.d.ts +1 -1
- package/src/ssr/index.ts +2 -2
- package/src/steplist/createStepListState.ts +191 -0
- package/src/steplist/index.ts +5 -0
- package/src/table/TableCollection.d.ts +42 -40
- package/src/table/TableCollection.ts +266 -99
- package/src/table/createTableColumnResizeState.ts +242 -0
- package/src/table/createTableState.d.ts +7 -4
- package/src/table/createTableState.ts +30 -7
- package/src/table/createTreeGridState.ts +146 -0
- package/src/table/index.d.ts +14 -4
- package/src/table/index.ts +13 -3
- package/src/table/types.d.ts +98 -92
- package/src/table/types.ts +83 -13
- package/src/tabs/createTabListState.d.ts +59 -57
- package/src/tabs/createTabListState.ts +34 -39
- package/src/tabs/index.d.ts +8 -2
- package/src/tabs/index.ts +1 -1
- package/src/textfield/createTextFieldState.d.ts +16 -14
- package/src/textfield/createTextFieldState.ts +7 -18
- package/src/textfield/index.d.ts +6 -2
- package/src/textfield/index.ts +1 -1
- package/src/toast/createToastState.d.ts +92 -86
- package/src/toast/createToastState.ts +90 -52
- package/src/toast/index.d.ts +12 -2
- package/src/toast/index.ts +2 -1
- package/src/toggle/createToggleGroupState.ts +11 -21
- package/src/toggle/createToggleState.d.ts +19 -19
- package/src/toggle/createToggleState.ts +2 -16
- package/src/toggle/index.d.ts +2 -2
- package/src/toggle/index.ts +2 -6
- package/src/tooltip/createTooltipTriggerState.d.ts +17 -17
- package/src/tooltip/createTooltipTriggerState.ts +12 -11
- package/src/tooltip/index.d.ts +7 -2
- package/src/tooltip/index.ts +1 -1
- package/src/tree/TreeCollection.d.ts +26 -23
- package/src/tree/TreeCollection.ts +29 -22
- package/src/tree/createTreeState.d.ts +7 -4
- package/src/tree/createTreeState.ts +70 -41
- package/src/tree/index.d.ts +10 -4
- package/src/tree/index.ts +3 -3
- package/src/tree/types.d.ts +131 -126
- package/src/tree/types.ts +30 -13
- package/src/utils/index.d.ts +2 -2
- package/src/utils/index.ts +1 -1
- package/src/utils/reactivity.d.ts +2 -2
- package/src/utils/reactivity.ts +3 -3
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TableCollection - A collection class for table data.
|
|
3
3
|
* Based on @react-stately/table/TableCollection.
|
|
4
|
+
*
|
|
5
|
+
* Supports a plain (flat) table and, when an `expandedKeys` option is supplied, a
|
|
6
|
+
* tree grid: `childRows` are walked recursively, each parent row keeps its full
|
|
7
|
+
* structure (cells followed by every child row), and only rows whose ancestors are
|
|
8
|
+
* all expanded are flattened into the navigable body. Mirrors the structure produced
|
|
9
|
+
* by `@react-stately/table`'s `generateTreeGridCollection`.
|
|
4
10
|
*/
|
|
5
11
|
|
|
6
|
-
import type { Key } from
|
|
7
|
-
import type { GridNode, GridNodeType } from
|
|
12
|
+
import type { Key } from "../collections/types";
|
|
13
|
+
import type { GridNode, GridNodeType } from "../grid/types";
|
|
8
14
|
import type {
|
|
9
15
|
TableCollection as ITableCollection,
|
|
10
16
|
TableCollectionOptions,
|
|
11
17
|
ColumnDefinition,
|
|
12
18
|
RowDefinition,
|
|
13
|
-
} from
|
|
19
|
+
} from "./types";
|
|
14
20
|
|
|
15
21
|
/**
|
|
16
22
|
* Creates a table collection from column and row definitions.
|
|
@@ -24,6 +30,10 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
24
30
|
private _keyMap: Map<Key, GridNode<T>> = new Map();
|
|
25
31
|
private _rowHeaderColumnKeys: Set<Key>;
|
|
26
32
|
private _size: number = 0;
|
|
33
|
+
/** Visible rows in DFS order. Drives size, navigation, iteration and the `rows` list. */
|
|
34
|
+
private _flattenedRows: GridNode<T>[] = [];
|
|
35
|
+
private _treeColumn: Key | null = null;
|
|
36
|
+
private _userColumnCount: number = 0;
|
|
27
37
|
|
|
28
38
|
constructor(options: TableCollectionOptions<T>) {
|
|
29
39
|
const {
|
|
@@ -33,79 +43,95 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
33
43
|
getTextValue,
|
|
34
44
|
showSelectionCheckboxes = false,
|
|
35
45
|
rowHeaderColumnKeys,
|
|
46
|
+
expandedKeys,
|
|
36
47
|
} = options;
|
|
37
48
|
|
|
38
|
-
//
|
|
49
|
+
// Passing `expandedKeys` (even an empty set) selects tree-grid mode.
|
|
50
|
+
const isTreeGrid = expandedKeys !== undefined;
|
|
51
|
+
|
|
39
52
|
this._columns = this.buildColumns(columns, showSelectionCheckboxes);
|
|
40
53
|
|
|
41
|
-
// Determine row header column keys
|
|
42
54
|
this._rowHeaderColumnKeys = rowHeaderColumnKeys ?? this.getDefaultRowHeaderColumnKeys();
|
|
43
55
|
|
|
44
|
-
// Build header rows
|
|
45
56
|
this._headerRows = this.buildHeaderRows();
|
|
46
57
|
|
|
47
|
-
// Build head node
|
|
48
58
|
if (this._headerRows.length > 0) {
|
|
49
59
|
this._head = {
|
|
50
|
-
type:
|
|
51
|
-
key:
|
|
60
|
+
type: "headerrow" as GridNodeType,
|
|
61
|
+
key: "header",
|
|
52
62
|
index: 0,
|
|
53
63
|
level: 0,
|
|
54
64
|
hasChildNodes: true,
|
|
55
65
|
childNodes: this._headerRows,
|
|
56
66
|
value: null,
|
|
57
|
-
textValue:
|
|
67
|
+
textValue: "",
|
|
58
68
|
};
|
|
59
|
-
this._keyMap.set(
|
|
69
|
+
this._keyMap.set("header", this._head);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let bodyChildren: GridNode<T>[];
|
|
73
|
+
if (isTreeGrid) {
|
|
74
|
+
const built = this.buildTreeRows(rows, expandedKeys, getKey, getTextValue);
|
|
75
|
+
bodyChildren = built.topLevelRows;
|
|
76
|
+
this._flattenedRows = built.flattenedRows;
|
|
77
|
+
this._userColumnCount = this.countLeafColumns();
|
|
78
|
+
this._treeColumn =
|
|
79
|
+
options.treeColumn !== undefined
|
|
80
|
+
? options.treeColumn
|
|
81
|
+
: (this._rowHeaderColumnKeys.values().next().value ?? null);
|
|
82
|
+
} else {
|
|
83
|
+
const bodyRows = this.buildRows(rows, getKey, getTextValue);
|
|
84
|
+
bodyChildren = bodyRows;
|
|
85
|
+
this._flattenedRows = bodyRows;
|
|
86
|
+
this._userColumnCount = this.countLeafColumns();
|
|
87
|
+
this._treeColumn = null;
|
|
60
88
|
}
|
|
61
89
|
|
|
62
|
-
|
|
63
|
-
const bodyRows = this.buildRows(rows, getKey, getTextValue);
|
|
64
|
-
this._size = bodyRows.length;
|
|
90
|
+
this._size = this._flattenedRows.length;
|
|
65
91
|
|
|
66
|
-
// Build body node
|
|
67
92
|
this._body = {
|
|
68
|
-
type:
|
|
69
|
-
key:
|
|
93
|
+
type: "item" as GridNodeType,
|
|
94
|
+
key: "body",
|
|
70
95
|
index: this._headerRows.length,
|
|
71
96
|
level: 0,
|
|
72
97
|
hasChildNodes: true,
|
|
73
|
-
|
|
98
|
+
// The body's children retain the full tree structure (top-level rows with their
|
|
99
|
+
// child rows nested inside) so sibling-based aria-posinset/aria-setsize work; the
|
|
100
|
+
// flattened visible list lives in `_flattenedRows`. For a flat table these are the
|
|
101
|
+
// same array.
|
|
102
|
+
childNodes: bodyChildren,
|
|
74
103
|
value: null,
|
|
75
|
-
textValue:
|
|
104
|
+
textValue: "",
|
|
76
105
|
};
|
|
77
|
-
this._keyMap.set(
|
|
106
|
+
this._keyMap.set("body", this._body);
|
|
78
107
|
|
|
79
|
-
|
|
80
|
-
this._rows = [...this._headerRows, ...bodyRows];
|
|
108
|
+
this._rows = [...this._headerRows, ...this._flattenedRows];
|
|
81
109
|
}
|
|
82
110
|
|
|
83
111
|
private buildColumns(
|
|
84
112
|
columns: ColumnDefinition<T>[],
|
|
85
|
-
showSelectionCheckboxes: boolean
|
|
113
|
+
showSelectionCheckboxes: boolean,
|
|
86
114
|
): GridNode<T>[] {
|
|
87
115
|
const result: GridNode<T>[] = [];
|
|
88
116
|
let colIndex = 0;
|
|
89
117
|
|
|
90
|
-
// Add selection column if needed
|
|
91
118
|
if (showSelectionCheckboxes) {
|
|
92
119
|
const selectionColumn: GridNode<T> = {
|
|
93
|
-
type:
|
|
94
|
-
key:
|
|
120
|
+
type: "column" as GridNodeType,
|
|
121
|
+
key: "__selection__",
|
|
95
122
|
index: colIndex,
|
|
96
123
|
column: 0,
|
|
97
124
|
level: 0,
|
|
98
125
|
hasChildNodes: false,
|
|
99
126
|
childNodes: [],
|
|
100
127
|
value: null,
|
|
101
|
-
textValue:
|
|
128
|
+
textValue: "Selection",
|
|
102
129
|
};
|
|
103
130
|
result.push(selectionColumn);
|
|
104
131
|
this._keyMap.set(selectionColumn.key, selectionColumn);
|
|
105
132
|
colIndex++;
|
|
106
133
|
}
|
|
107
134
|
|
|
108
|
-
// Build user columns
|
|
109
135
|
for (const col of columns) {
|
|
110
136
|
const node = this.buildColumnNode(col, colIndex);
|
|
111
137
|
result.push(node);
|
|
@@ -116,24 +142,25 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
116
142
|
}
|
|
117
143
|
|
|
118
144
|
private buildColumnNode(col: ColumnDefinition<T>, index: number): GridNode<T> {
|
|
145
|
+
const key = col.key ?? (col as ColumnDefinition<T> & { id?: Key }).id ?? index;
|
|
119
146
|
const node: GridNode<T> = {
|
|
120
|
-
type:
|
|
121
|
-
key
|
|
147
|
+
type: "column" as GridNodeType,
|
|
148
|
+
key,
|
|
122
149
|
index,
|
|
123
150
|
column: index,
|
|
124
151
|
level: 0,
|
|
125
152
|
hasChildNodes: (col.children?.length ?? 0) > 0,
|
|
126
153
|
childNodes: [],
|
|
127
154
|
value: null,
|
|
128
|
-
|
|
155
|
+
props: { columnDefinition: { ...col, key } },
|
|
156
|
+
textValue: col.textValue ?? col.name ?? String(key),
|
|
129
157
|
};
|
|
130
158
|
|
|
131
|
-
// Build child columns if present (for column groups)
|
|
132
159
|
if (col.children && col.children.length > 0) {
|
|
133
160
|
let childIndex = 0;
|
|
134
161
|
for (const child of col.children) {
|
|
135
162
|
const childNode = this.buildColumnNode(child, childIndex);
|
|
136
|
-
childNode.parentKey =
|
|
163
|
+
childNode.parentKey = key;
|
|
137
164
|
childNode.level = 1;
|
|
138
165
|
node.childNodes.push(childNode);
|
|
139
166
|
childIndex++;
|
|
@@ -145,23 +172,51 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
145
172
|
}
|
|
146
173
|
|
|
147
174
|
private getDefaultRowHeaderColumnKeys(): Set<Key> {
|
|
148
|
-
|
|
175
|
+
const explicitRowHeaderKeys = this._columns
|
|
176
|
+
.filter((col) => col.key !== "__selection__")
|
|
177
|
+
.filter((col) => {
|
|
178
|
+
const definition = col.props?.columnDefinition as ColumnDefinition<T> | undefined;
|
|
179
|
+
return !!definition?.isRowHeader;
|
|
180
|
+
})
|
|
181
|
+
.map((col) => col.key);
|
|
182
|
+
|
|
183
|
+
if (explicitRowHeaderKeys.length > 0) {
|
|
184
|
+
return new Set(explicitRowHeaderKeys);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Default to first non-selection column as row header.
|
|
149
188
|
for (const col of this._columns) {
|
|
150
|
-
if (col.key !==
|
|
189
|
+
if (col.key !== "__selection__") {
|
|
151
190
|
return new Set([col.key]);
|
|
152
191
|
}
|
|
153
192
|
}
|
|
154
193
|
return new Set();
|
|
155
194
|
}
|
|
156
195
|
|
|
196
|
+
/** Counts the leaf columns supplied by the user (excludes the selection column). */
|
|
197
|
+
private countLeafColumns(): number {
|
|
198
|
+
let count = 0;
|
|
199
|
+
const visit = (col: GridNode<T>) => {
|
|
200
|
+
if (col.key === "__selection__") {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (col.childNodes.length > 0) {
|
|
204
|
+
col.childNodes.forEach(visit);
|
|
205
|
+
} else {
|
|
206
|
+
count++;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
this._columns.forEach(visit);
|
|
210
|
+
return count;
|
|
211
|
+
}
|
|
212
|
+
|
|
157
213
|
private buildHeaderRows(): GridNode<T>[] {
|
|
158
214
|
if (this._columns.length === 0) {
|
|
159
215
|
return [];
|
|
160
216
|
}
|
|
161
217
|
|
|
162
|
-
// Build a single header row containing all columns
|
|
163
218
|
const headerCells: GridNode<T>[] = this._columns.map((col, index) => ({
|
|
164
|
-
type:
|
|
219
|
+
type: "column" as GridNodeType,
|
|
165
220
|
key: `header-${col.key}`,
|
|
166
221
|
index,
|
|
167
222
|
column: index,
|
|
@@ -170,19 +225,19 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
170
225
|
childNodes: [],
|
|
171
226
|
value: null,
|
|
172
227
|
textValue: col.textValue,
|
|
173
|
-
parentKey:
|
|
228
|
+
parentKey: "headerrow-0",
|
|
174
229
|
}));
|
|
175
230
|
|
|
176
231
|
const headerRow: GridNode<T> = {
|
|
177
|
-
type:
|
|
178
|
-
key:
|
|
232
|
+
type: "headerrow" as GridNodeType,
|
|
233
|
+
key: "headerrow-0",
|
|
179
234
|
index: 0,
|
|
180
235
|
rowIndex: 0,
|
|
181
236
|
level: 0,
|
|
182
237
|
hasChildNodes: true,
|
|
183
238
|
childNodes: headerCells,
|
|
184
239
|
value: null,
|
|
185
|
-
textValue:
|
|
240
|
+
textValue: "",
|
|
186
241
|
};
|
|
187
242
|
|
|
188
243
|
this._keyMap.set(headerRow.key, headerRow);
|
|
@@ -191,10 +246,51 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
191
246
|
return [headerRow];
|
|
192
247
|
}
|
|
193
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Builds the cell nodes for one row. Does not register the cells in the key map;
|
|
251
|
+
* the caller registers cells once the owning row is known to be present.
|
|
252
|
+
*/
|
|
253
|
+
private buildCells(
|
|
254
|
+
rowKey: Key,
|
|
255
|
+
value: T,
|
|
256
|
+
rowLevel: number,
|
|
257
|
+
getTextValue?: (item: T, column: ColumnDefinition<T>) => string,
|
|
258
|
+
): GridNode<T>[] {
|
|
259
|
+
return this._columns.map((col, colIndex) => {
|
|
260
|
+
const cellKey = `${rowKey}-${col.key}`;
|
|
261
|
+
const columnDefinition =
|
|
262
|
+
(col.props?.columnDefinition as ColumnDefinition<T> | undefined) ??
|
|
263
|
+
({ key: col.key } as ColumnDefinition<T>);
|
|
264
|
+
const cellTextValue =
|
|
265
|
+
col.key === "__selection__"
|
|
266
|
+
? "Selection"
|
|
267
|
+
: getTextValue
|
|
268
|
+
? getTextValue(value, columnDefinition)
|
|
269
|
+
: String((value as Record<string, unknown>)?.[String(col.key)] ?? "");
|
|
270
|
+
|
|
271
|
+
const cell: GridNode<T> = {
|
|
272
|
+
type: this._rowHeaderColumnKeys.has(col.key)
|
|
273
|
+
? ("rowheader" as GridNodeType)
|
|
274
|
+
: ("cell" as GridNodeType),
|
|
275
|
+
key: cellKey,
|
|
276
|
+
index: colIndex,
|
|
277
|
+
column: colIndex,
|
|
278
|
+
level: rowLevel + 1,
|
|
279
|
+
hasChildNodes: false,
|
|
280
|
+
childNodes: [],
|
|
281
|
+
value,
|
|
282
|
+
textValue: cellTextValue,
|
|
283
|
+
parentKey: rowKey,
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
return cell;
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
194
290
|
private buildRows(
|
|
195
291
|
rows: RowDefinition<T>[] | T[],
|
|
196
292
|
getKey?: (item: T) => Key,
|
|
197
|
-
getTextValue?: (item: T, column: ColumnDefinition<T>) => string
|
|
293
|
+
getTextValue?: (item: T, column: ColumnDefinition<T>) => string,
|
|
198
294
|
): GridNode<T>[] {
|
|
199
295
|
const result: GridNode<T>[] = [];
|
|
200
296
|
const rowIndexOffset = this._headerRows.length;
|
|
@@ -203,41 +299,19 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
203
299
|
const row = rows[i];
|
|
204
300
|
const isRowDef = this.isRowDefinition(row);
|
|
205
301
|
|
|
206
|
-
const key = isRowDef ? row.key : getKey?.(row as T) ?? i;
|
|
302
|
+
const key = isRowDef ? row.key : (getKey?.(row as T) ?? i);
|
|
207
303
|
const value = isRowDef ? row.value : (row as T);
|
|
208
|
-
const textValue = isRowDef
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
: getTextValue
|
|
217
|
-
? getTextValue(value, { key: col.key } as ColumnDefinition<T>)
|
|
218
|
-
: String((value as Record<string, unknown>)?.[String(col.key)] ?? '');
|
|
219
|
-
|
|
220
|
-
const cell: GridNode<T> = {
|
|
221
|
-
type: this._rowHeaderColumnKeys.has(col.key)
|
|
222
|
-
? ('rowheader' as GridNodeType)
|
|
223
|
-
: ('cell' as GridNodeType),
|
|
224
|
-
key: cellKey,
|
|
225
|
-
index: colIndex,
|
|
226
|
-
column: colIndex,
|
|
227
|
-
level: 1,
|
|
228
|
-
hasChildNodes: false,
|
|
229
|
-
childNodes: [],
|
|
230
|
-
value,
|
|
231
|
-
textValue: cellTextValue,
|
|
232
|
-
parentKey: key,
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
this._keyMap.set(cellKey, cell);
|
|
236
|
-
return cell;
|
|
237
|
-
});
|
|
304
|
+
const textValue = isRowDef
|
|
305
|
+
? row.textValue
|
|
306
|
+
: typeof (row as Record<string, unknown>)?.textValue === "string"
|
|
307
|
+
? ((row as Record<string, unknown>).textValue as string)
|
|
308
|
+
: undefined;
|
|
309
|
+
|
|
310
|
+
const cells = this.buildCells(key, value as T, 0, getTextValue);
|
|
311
|
+
cells.forEach((cell) => this._keyMap.set(cell.key, cell));
|
|
238
312
|
|
|
239
313
|
const rowNode: GridNode<T> = {
|
|
240
|
-
type:
|
|
314
|
+
type: "item" as GridNodeType,
|
|
241
315
|
key,
|
|
242
316
|
index: i,
|
|
243
317
|
rowIndex: rowIndexOffset + i,
|
|
@@ -245,7 +319,7 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
245
319
|
hasChildNodes: true,
|
|
246
320
|
childNodes: cells,
|
|
247
321
|
value,
|
|
248
|
-
textValue: textValue ?? cells.map((c) => c.textValue).join(
|
|
322
|
+
textValue: textValue ?? cells.map((c) => c.textValue).join(" "),
|
|
249
323
|
};
|
|
250
324
|
|
|
251
325
|
this._keyMap.set(key, rowNode);
|
|
@@ -255,16 +329,101 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
255
329
|
return result;
|
|
256
330
|
}
|
|
257
331
|
|
|
332
|
+
/**
|
|
333
|
+
* Builds the tree-grid rows: every row keeps its full structure (cells then all child
|
|
334
|
+
* rows, expanded or not) while only the rows whose ancestors are all expanded are
|
|
335
|
+
* registered in the key map and pushed into the flattened body. Mirrors
|
|
336
|
+
* `generateTreeGridCollection` upstream.
|
|
337
|
+
*/
|
|
338
|
+
private buildTreeRows(
|
|
339
|
+
rows: RowDefinition<T>[] | T[],
|
|
340
|
+
expandedKeys: "all" | Set<Key>,
|
|
341
|
+
getKey?: (item: T) => Key,
|
|
342
|
+
getTextValue?: (item: T, column: ColumnDefinition<T>) => string,
|
|
343
|
+
): { topLevelRows: GridNode<T>[]; flattenedRows: GridNode<T>[] } {
|
|
344
|
+
const isExpanded = (key: Key): boolean => expandedKeys === "all" || expandedKeys.has(key);
|
|
345
|
+
|
|
346
|
+
// Build the full tree structure without touching the key map. `index` is the row's
|
|
347
|
+
// position among its same-level siblings, so aria-posinset/aria-setsize read directly.
|
|
348
|
+
const buildRowNode = (
|
|
349
|
+
row: RowDefinition<T> | T,
|
|
350
|
+
level: number,
|
|
351
|
+
parentKey: Key | null,
|
|
352
|
+
indexAmongSiblings: number,
|
|
353
|
+
): GridNode<T> => {
|
|
354
|
+
const isRowDef = this.isRowDefinition(row);
|
|
355
|
+
const key = isRowDef ? row.key : (getKey?.(row as T) ?? indexAmongSiblings);
|
|
356
|
+
const value = (isRowDef ? row.value : (row as T)) as T;
|
|
357
|
+
const textValue = isRowDef
|
|
358
|
+
? row.textValue
|
|
359
|
+
: typeof (row as Record<string, unknown>)?.textValue === "string"
|
|
360
|
+
? ((row as Record<string, unknown>).textValue as string)
|
|
361
|
+
: undefined;
|
|
362
|
+
|
|
363
|
+
const cells = this.buildCells(key, value, level, getTextValue);
|
|
364
|
+
|
|
365
|
+
const childRowDefs = isRowDef ? (row.childRows ?? []) : [];
|
|
366
|
+
const hasChildRows = childRowDefs.length > 0 || (isRowDef && !!row.hasChildRows);
|
|
367
|
+
|
|
368
|
+
const childRowNodes = childRowDefs.map((child, childIdx) =>
|
|
369
|
+
buildRowNode(child, level + 1, key, childIdx),
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
const childNodes = [...cells, ...childRowNodes];
|
|
373
|
+
const rowNode: GridNode<T> = {
|
|
374
|
+
type: "item" as GridNodeType,
|
|
375
|
+
key,
|
|
376
|
+
index: indexAmongSiblings,
|
|
377
|
+
level,
|
|
378
|
+
parentKey,
|
|
379
|
+
hasChildNodes: true,
|
|
380
|
+
childNodes,
|
|
381
|
+
value,
|
|
382
|
+
textValue: textValue ?? cells.map((c) => c.textValue).join(" "),
|
|
383
|
+
isExpandable: hasChildRows,
|
|
384
|
+
isExpanded: hasChildRows && isExpanded(key),
|
|
385
|
+
firstChildKey: childNodes[0]?.key ?? null,
|
|
386
|
+
lastChildKey: childNodes[childNodes.length - 1]?.key ?? null,
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
return rowNode;
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
const topLevelRows = rows.map((row, i) => buildRowNode(row, 0, "body", i));
|
|
393
|
+
|
|
394
|
+
// Flatten the visible rows (DFS). A row is visited iff every ancestor is expanded;
|
|
395
|
+
// visiting a row registers it and its cells, then descends into its child rows only
|
|
396
|
+
// when the row itself is expanded.
|
|
397
|
+
const flattenedRows: GridNode<T>[] = [];
|
|
398
|
+
const rowIndexOffset = this._headerRows.length;
|
|
399
|
+
const visit = (node: GridNode<T>) => {
|
|
400
|
+
node.rowIndex = rowIndexOffset + flattenedRows.length;
|
|
401
|
+
flattenedRows.push(node);
|
|
402
|
+
this._keyMap.set(node.key, node);
|
|
403
|
+
for (const child of node.childNodes) {
|
|
404
|
+
if (child.type !== "item") {
|
|
405
|
+
this._keyMap.set(child.key, child);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (isExpanded(node.key)) {
|
|
409
|
+
for (const child of node.childNodes) {
|
|
410
|
+
if (child.type === "item") {
|
|
411
|
+
visit(child);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
for (const node of topLevelRows) {
|
|
417
|
+
visit(node);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return { topLevelRows, flattenedRows };
|
|
421
|
+
}
|
|
422
|
+
|
|
258
423
|
private isRowDefinition(row: unknown): row is RowDefinition<T> {
|
|
259
|
-
return
|
|
260
|
-
typeof row === 'object' &&
|
|
261
|
-
row !== null &&
|
|
262
|
-
'key' in row &&
|
|
263
|
-
'value' in row
|
|
264
|
-
);
|
|
424
|
+
return typeof row === "object" && row !== null && "key" in row && "value" in row;
|
|
265
425
|
}
|
|
266
426
|
|
|
267
|
-
// Collection interface implementation
|
|
268
427
|
get size(): number {
|
|
269
428
|
return this._size;
|
|
270
429
|
}
|
|
@@ -301,6 +460,21 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
301
460
|
return this._rowHeaderColumnKeys;
|
|
302
461
|
}
|
|
303
462
|
|
|
463
|
+
/** The key of the column that renders the tree-grid affordance, or `null` for a flat table. */
|
|
464
|
+
get treeColumn(): Key | null {
|
|
465
|
+
return this._treeColumn;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/** The number of leaf columns provided by the user (excludes the selection column). */
|
|
469
|
+
get userColumnCount(): number {
|
|
470
|
+
return this._userColumnCount;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/** The key map of all present nodes (visible rows, their cells, columns and the body). */
|
|
474
|
+
get keyMap(): Map<Key, GridNode<T>> {
|
|
475
|
+
return this._keyMap;
|
|
476
|
+
}
|
|
477
|
+
|
|
304
478
|
getKeys(): Iterable<Key> {
|
|
305
479
|
return this._keyMap.keys();
|
|
306
480
|
}
|
|
@@ -310,11 +484,10 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
310
484
|
}
|
|
311
485
|
|
|
312
486
|
at(index: number): GridNode<T> | null {
|
|
313
|
-
|
|
314
|
-
if (index < 0 || index >= bodyRows.length) {
|
|
487
|
+
if (index < 0 || index >= this._flattenedRows.length) {
|
|
315
488
|
return null;
|
|
316
489
|
}
|
|
317
|
-
return
|
|
490
|
+
return this._flattenedRows[index];
|
|
318
491
|
}
|
|
319
492
|
|
|
320
493
|
getChildren(key: Key): Iterable<GridNode<T>> {
|
|
@@ -324,7 +497,7 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
324
497
|
|
|
325
498
|
getTextValue(key: Key): string {
|
|
326
499
|
const node = this._keyMap.get(key);
|
|
327
|
-
return node?.textValue ??
|
|
500
|
+
return node?.textValue ?? "";
|
|
328
501
|
}
|
|
329
502
|
|
|
330
503
|
getCell(rowKey: Key, columnKey: Key): GridNode<T> | null {
|
|
@@ -333,14 +506,12 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
333
506
|
}
|
|
334
507
|
|
|
335
508
|
getFirstKey(): Key | null {
|
|
336
|
-
|
|
337
|
-
const bodyRows = this._body.childNodes;
|
|
509
|
+
const bodyRows = this._flattenedRows;
|
|
338
510
|
return bodyRows.length > 0 ? bodyRows[0].key : null;
|
|
339
511
|
}
|
|
340
512
|
|
|
341
513
|
getLastKey(): Key | null {
|
|
342
|
-
|
|
343
|
-
const bodyRows = this._body.childNodes;
|
|
514
|
+
const bodyRows = this._flattenedRows;
|
|
344
515
|
return bodyRows.length > 0 ? bodyRows[bodyRows.length - 1].key : null;
|
|
345
516
|
}
|
|
346
517
|
|
|
@@ -348,8 +519,7 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
348
519
|
const node = this._keyMap.get(key);
|
|
349
520
|
if (!node) return null;
|
|
350
521
|
|
|
351
|
-
|
|
352
|
-
const bodyRows = this._body.childNodes;
|
|
522
|
+
const bodyRows = this._flattenedRows;
|
|
353
523
|
const index = bodyRows.findIndex((r) => r.key === key);
|
|
354
524
|
if (index > 0) {
|
|
355
525
|
return bodyRows[index - 1].key;
|
|
@@ -361,8 +531,7 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
361
531
|
const node = this._keyMap.get(key);
|
|
362
532
|
if (!node) return null;
|
|
363
533
|
|
|
364
|
-
|
|
365
|
-
const bodyRows = this._body.childNodes;
|
|
534
|
+
const bodyRows = this._flattenedRows;
|
|
366
535
|
const index = bodyRows.findIndex((r) => r.key === key);
|
|
367
536
|
if (index >= 0 && index < bodyRows.length - 1) {
|
|
368
537
|
return bodyRows[index + 1].key;
|
|
@@ -371,8 +540,8 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
371
540
|
}
|
|
372
541
|
|
|
373
542
|
*[Symbol.iterator](): Iterator<GridNode<T>> {
|
|
374
|
-
// Only iterate body rows, not header rows
|
|
375
|
-
for (const row of this.
|
|
543
|
+
// Only iterate visible body rows, not header rows.
|
|
544
|
+
for (const row of this._flattenedRows) {
|
|
376
545
|
yield row;
|
|
377
546
|
}
|
|
378
547
|
}
|
|
@@ -381,8 +550,6 @@ export class TableCollection<T = unknown> implements ITableCollection<T> {
|
|
|
381
550
|
/**
|
|
382
551
|
* Creates a table collection from options.
|
|
383
552
|
*/
|
|
384
|
-
export function createTableCollection<T>(
|
|
385
|
-
options: TableCollectionOptions<T>
|
|
386
|
-
): TableCollection<T> {
|
|
553
|
+
export function createTableCollection<T>(options: TableCollectionOptions<T>): TableCollection<T> {
|
|
387
554
|
return new TableCollection(options);
|
|
388
555
|
}
|