@navikt/ds-react 8.10.2 → 8.10.3
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/cjs/data/table/column-header/DataTableColumnHeader.js +3 -1
- package/cjs/data/table/column-header/DataTableColumnHeader.js.map +1 -1
- package/cjs/data/table/column-header/useTableColumnResize.d.ts +24 -2
- package/cjs/data/table/column-header/useTableColumnResize.js +31 -15
- package/cjs/data/table/column-header/useTableColumnResize.js.map +1 -1
- package/cjs/data/table/helpers/collectTableRowEntries.d.ts +10 -2
- package/cjs/data/table/helpers/collectTableRowEntries.js +25 -17
- package/cjs/data/table/helpers/collectTableRowEntries.js.map +1 -1
- package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.d.ts +46 -0
- package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.js +112 -0
- package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.js.map +1 -0
- package/cjs/data/table/helpers/selection/getMultipleSelectProps.d.ts +3 -2
- package/cjs/data/table/helpers/selection/getMultipleSelectProps.js +43 -19
- package/cjs/data/table/helpers/selection/getMultipleSelectProps.js.map +1 -1
- package/cjs/data/table/helpers/selection/selection.types.d.ts +1 -0
- package/cjs/data/table/helpers/table-keyboard.d.ts +1 -2
- package/cjs/data/table/helpers/table-keyboard.js +1 -2
- package/cjs/data/table/helpers/table-keyboard.js.map +1 -1
- package/cjs/data/table/hooks/useTableExpansion.d.ts +1 -3
- package/cjs/data/table/hooks/useTableExpansion.js +7 -1
- package/cjs/data/table/hooks/useTableExpansion.js.map +1 -1
- package/cjs/data/table/hooks/useTableItems.d.ts +7 -3
- package/cjs/data/table/hooks/useTableItems.js +18 -7
- package/cjs/data/table/hooks/useTableItems.js.map +1 -1
- package/cjs/data/table/hooks/useTableSelection.d.ts +3 -2
- package/cjs/data/table/hooks/useTableSelection.js +5 -4
- package/cjs/data/table/hooks/useTableSelection.js.map +1 -1
- package/cjs/data/table/root/DataTable.types.d.ts +5 -4
- package/cjs/data/table/root/DataTableAuto.d.ts +9 -1
- package/cjs/data/table/root/DataTableAuto.js +50 -50
- package/cjs/data/table/root/DataTableAuto.js.map +1 -1
- package/cjs/data/table/root/DataTableRoot.js +2 -3
- package/cjs/data/table/root/DataTableRoot.js.map +1 -1
- package/cjs/form/checkbox/Checkbox.js +1 -0
- package/cjs/form/checkbox/Checkbox.js.map +1 -1
- package/cjs/form/radio/Radio.js +7 -1
- package/cjs/form/radio/Radio.js.map +1 -1
- package/cjs/modal/types.d.ts +8 -4
- package/esm/data/table/column-header/DataTableColumnHeader.js +3 -1
- package/esm/data/table/column-header/DataTableColumnHeader.js.map +1 -1
- package/esm/data/table/column-header/useTableColumnResize.d.ts +24 -2
- package/esm/data/table/column-header/useTableColumnResize.js +32 -16
- package/esm/data/table/column-header/useTableColumnResize.js.map +1 -1
- package/esm/data/table/helpers/collectTableRowEntries.d.ts +10 -2
- package/esm/data/table/helpers/collectTableRowEntries.js +25 -17
- package/esm/data/table/helpers/collectTableRowEntries.js.map +1 -1
- package/esm/data/table/helpers/selection/SelectionSubtreeHelper.d.ts +46 -0
- package/esm/data/table/helpers/selection/SelectionSubtreeHelper.js +109 -0
- package/esm/data/table/helpers/selection/SelectionSubtreeHelper.js.map +1 -0
- package/esm/data/table/helpers/selection/getMultipleSelectProps.d.ts +3 -2
- package/esm/data/table/helpers/selection/getMultipleSelectProps.js +43 -19
- package/esm/data/table/helpers/selection/getMultipleSelectProps.js.map +1 -1
- package/esm/data/table/helpers/selection/selection.types.d.ts +1 -0
- package/esm/data/table/helpers/table-keyboard.d.ts +1 -2
- package/esm/data/table/helpers/table-keyboard.js +1 -2
- package/esm/data/table/helpers/table-keyboard.js.map +1 -1
- package/esm/data/table/hooks/useTableExpansion.d.ts +1 -3
- package/esm/data/table/hooks/useTableExpansion.js +7 -1
- package/esm/data/table/hooks/useTableExpansion.js.map +1 -1
- package/esm/data/table/hooks/useTableItems.d.ts +7 -3
- package/esm/data/table/hooks/useTableItems.js +18 -7
- package/esm/data/table/hooks/useTableItems.js.map +1 -1
- package/esm/data/table/hooks/useTableSelection.d.ts +3 -2
- package/esm/data/table/hooks/useTableSelection.js +5 -4
- package/esm/data/table/hooks/useTableSelection.js.map +1 -1
- package/esm/data/table/root/DataTable.types.d.ts +5 -4
- package/esm/data/table/root/DataTableAuto.d.ts +9 -1
- package/esm/data/table/root/DataTableAuto.js +51 -51
- package/esm/data/table/root/DataTableAuto.js.map +1 -1
- package/esm/data/table/root/DataTableRoot.js +3 -4
- package/esm/data/table/root/DataTableRoot.js.map +1 -1
- package/esm/form/checkbox/Checkbox.js +1 -0
- package/esm/form/checkbox/Checkbox.js.map +1 -1
- package/esm/form/radio/Radio.js +7 -1
- package/esm/form/radio/Radio.js.map +1 -1
- package/esm/modal/types.d.ts +8 -4
- package/package.json +3 -3
- package/src/data/table/column-header/DataTableColumnHeader.tsx +5 -1
- package/src/data/table/column-header/useTableColumnResize.ts +73 -17
- package/src/data/table/helpers/collectTableRowEntries.ts +57 -25
- package/src/data/table/helpers/selection/SelectionSubtreeHelper.test.ts +66 -0
- package/src/data/table/helpers/selection/SelectionSubtreeHelper.ts +162 -0
- package/src/data/table/helpers/selection/getMultipleSelectProps.ts +57 -20
- package/src/data/table/helpers/selection/selection.types.ts +1 -0
- package/src/data/table/helpers/table-keyboard.ts +1 -2
- package/src/data/table/hooks/__tests__/useTableItems.test.ts +14 -0
- package/src/data/table/hooks/__tests__/useTableSelection.test.ts +132 -21
- package/src/data/table/hooks/useTableExpansion.tsx +8 -3
- package/src/data/table/hooks/useTableItems.ts +50 -27
- package/src/data/table/hooks/useTableSelection.ts +10 -6
- package/src/data/table/root/DataTable.types.ts +5 -4
- package/src/data/table/root/DataTableAuto.test.tsx +128 -2
- package/src/data/table/root/DataTableAuto.tsx +144 -135
- package/src/data/table/root/DataTableRoot.tsx +6 -7
- package/src/form/checkbox/Checkbox.tsx +1 -0
- package/src/form/radio/Radio.tsx +7 -1
- package/src/modal/types.ts +8 -4
- package/src/data/table/hooks/__tests__/useTableExpansion.test.tsx +0 -115
|
@@ -12,11 +12,12 @@ type ColumnDefinition<T> = {
|
|
|
12
12
|
minWidth?: number | string;
|
|
13
13
|
maxWidth?: number | string;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Text alignment for cells in this column.
|
|
16
|
+
*
|
|
17
|
+
*
|
|
18
|
+
* @default "left"
|
|
18
19
|
*/
|
|
19
|
-
|
|
20
|
+
align?: "left" | "right" | "center";
|
|
20
21
|
/**
|
|
21
22
|
* Assigned to the cell's `th` element instead of `td` if true.
|
|
22
23
|
*
|
|
@@ -20,6 +20,20 @@ const data: TestRow[] = [
|
|
|
20
20
|
},
|
|
21
21
|
];
|
|
22
22
|
|
|
23
|
+
const deepNestedData: TestRow[] = [
|
|
24
|
+
{
|
|
25
|
+
id: "root",
|
|
26
|
+
name: "Root",
|
|
27
|
+
subRows: [
|
|
28
|
+
{
|
|
29
|
+
id: "child",
|
|
30
|
+
name: "Child",
|
|
31
|
+
subRows: [{ id: "grandchild", name: "Grandchild" }],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
|
|
23
37
|
const fallbackIdData: TestRow[] = [
|
|
24
38
|
{
|
|
25
39
|
id: "unused-root-1",
|
|
@@ -49,7 +63,7 @@ describe("DataTableAuto", () => {
|
|
|
49
63
|
data={data}
|
|
50
64
|
getRowId={(row) => row.id}
|
|
51
65
|
getSubRows={(row) => row.subRows ?? []}
|
|
52
|
-
selectionMode
|
|
66
|
+
selection={{ selectionMode: "multiple" }}
|
|
53
67
|
/>,
|
|
54
68
|
);
|
|
55
69
|
|
|
@@ -78,7 +92,7 @@ describe("DataTableAuto", () => {
|
|
|
78
92
|
data={fallbackIdData}
|
|
79
93
|
getSubRows={(row) => row.subRows ?? []}
|
|
80
94
|
defaultExpandedSubRowIds={[0]}
|
|
81
|
-
selectionMode
|
|
95
|
+
selection={{ selectionMode: "multiple" }}
|
|
82
96
|
/>,
|
|
83
97
|
);
|
|
84
98
|
|
|
@@ -94,6 +108,118 @@ describe("DataTableAuto", () => {
|
|
|
94
108
|
expect(rowCheckboxes.every((checkbox) => checkbox.checked)).toBe(true);
|
|
95
109
|
});
|
|
96
110
|
|
|
111
|
+
test("parent row selection follows visible nested rows", () => {
|
|
112
|
+
render(
|
|
113
|
+
<DataTableAuto
|
|
114
|
+
columnDefinitions={columns}
|
|
115
|
+
data={data}
|
|
116
|
+
getRowId={(row) => row.id}
|
|
117
|
+
getSubRows={(row) => row.subRows ?? []}
|
|
118
|
+
selection={{ selectionMode: "multiple" }}
|
|
119
|
+
/>,
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
fireEvent.click(screen.getByRole("button", { name: "Vis under-rader" }));
|
|
123
|
+
|
|
124
|
+
const getCheckboxes = () =>
|
|
125
|
+
screen.getAllByRole("checkbox") as HTMLInputElement[];
|
|
126
|
+
|
|
127
|
+
fireEvent.click(getCheckboxes()[2]);
|
|
128
|
+
|
|
129
|
+
expect(getCheckboxes()[1].checked).toBe(false);
|
|
130
|
+
expect(getCheckboxes()[1].indeterminate).toBe(true);
|
|
131
|
+
|
|
132
|
+
fireEvent.click(getCheckboxes()[1]);
|
|
133
|
+
|
|
134
|
+
expect(getCheckboxes()[1].checked).toBe(true);
|
|
135
|
+
expect(getCheckboxes()[2].checked).toBe(true);
|
|
136
|
+
|
|
137
|
+
fireEvent.click(getCheckboxes()[1]);
|
|
138
|
+
|
|
139
|
+
expect(getCheckboxes()[1].checked).toBe(false);
|
|
140
|
+
expect(getCheckboxes()[2].checked).toBe(false);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("collapsed parent selection includes hidden descendants and can clear them again", () => {
|
|
144
|
+
render(
|
|
145
|
+
<DataTableAuto
|
|
146
|
+
columnDefinitions={columns}
|
|
147
|
+
data={deepNestedData}
|
|
148
|
+
getRowId={(row) => row.id}
|
|
149
|
+
getSubRows={(row) => row.subRows ?? []}
|
|
150
|
+
selection={{ selectionMode: "multiple" }}
|
|
151
|
+
/>,
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
const getCheckboxes = () =>
|
|
155
|
+
screen.getAllByRole("checkbox") as HTMLInputElement[];
|
|
156
|
+
|
|
157
|
+
fireEvent.click(getCheckboxes()[1]);
|
|
158
|
+
|
|
159
|
+
fireEvent.click(screen.getByRole("button", { name: "Vis under-rader" }));
|
|
160
|
+
|
|
161
|
+
expect(getCheckboxes()[1].checked).toBe(true);
|
|
162
|
+
expect(getCheckboxes()[2].checked).toBe(true);
|
|
163
|
+
|
|
164
|
+
fireEvent.click(screen.getByRole("button", { name: "Vis under-rader" }));
|
|
165
|
+
|
|
166
|
+
expect(getCheckboxes()[3].checked).toBe(true);
|
|
167
|
+
|
|
168
|
+
fireEvent.click(
|
|
169
|
+
screen.getAllByRole("button", { name: "Skjul under-rader" })[0],
|
|
170
|
+
);
|
|
171
|
+
fireEvent.click(getCheckboxes()[1]);
|
|
172
|
+
|
|
173
|
+
fireEvent.click(screen.getByRole("button", { name: "Vis under-rader" }));
|
|
174
|
+
|
|
175
|
+
expect(getCheckboxes()[1].checked).toBe(false);
|
|
176
|
+
expect(getCheckboxes()[2].checked).toBe(false);
|
|
177
|
+
expect(getCheckboxes()[3].checked).toBe(false);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("select-all includes hidden descendants for collapsed parents and clears them again", () => {
|
|
181
|
+
render(
|
|
182
|
+
<DataTableAuto
|
|
183
|
+
columnDefinitions={columns}
|
|
184
|
+
data={deepNestedData}
|
|
185
|
+
getRowId={(row) => row.id}
|
|
186
|
+
getSubRows={(row) => row.subRows ?? []}
|
|
187
|
+
selection={{ selectionMode: "multiple" }}
|
|
188
|
+
/>,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const getCheckboxes = () =>
|
|
192
|
+
screen.getAllByRole("checkbox") as HTMLInputElement[];
|
|
193
|
+
|
|
194
|
+
fireEvent.click(
|
|
195
|
+
screen.getByRole("checkbox", { name: "Velg alle synlige rader" }),
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
fireEvent.click(screen.getByRole("button", { name: "Vis under-rader" }));
|
|
199
|
+
|
|
200
|
+
expect(getCheckboxes()[1].checked).toBe(true);
|
|
201
|
+
expect(getCheckboxes()[2].checked).toBe(true);
|
|
202
|
+
|
|
203
|
+
fireEvent.click(screen.getByRole("button", { name: "Vis under-rader" }));
|
|
204
|
+
|
|
205
|
+
expect(getCheckboxes()[3].checked).toBe(true);
|
|
206
|
+
|
|
207
|
+
fireEvent.click(
|
|
208
|
+
screen.getByRole("checkbox", { name: "Fjern alle synlige valgte rader" }),
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
expect(getCheckboxes()[0].checked).toBe(false);
|
|
212
|
+
|
|
213
|
+
fireEvent.click(
|
|
214
|
+
screen.getAllByRole("button", { name: "Skjul under-rader" })[0],
|
|
215
|
+
);
|
|
216
|
+
fireEvent.click(screen.getByRole("button", { name: "Vis under-rader" }));
|
|
217
|
+
|
|
218
|
+
expect(getCheckboxes()[1].checked).toBe(false);
|
|
219
|
+
expect(getCheckboxes()[2].checked).toBe(false);
|
|
220
|
+
expect(getCheckboxes()[3].checked).toBe(false);
|
|
221
|
+
});
|
|
222
|
+
|
|
97
223
|
test("does not render expansion controls in the manual table variant", () => {
|
|
98
224
|
render(
|
|
99
225
|
<DataTable>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** biome-ignore-all lint/correctness/useHookAtTopLevel: False positive because of the way forwardRef() is added */
|
|
2
|
-
import React, { forwardRef
|
|
2
|
+
import React, { forwardRef } from "react";
|
|
3
3
|
import { ChevronDownIcon, ChevronRightIcon } from "@navikt/aksel-icons";
|
|
4
4
|
import { Button } from "../../../button";
|
|
5
5
|
import { Skeleton } from "../../../skeleton";
|
|
@@ -38,10 +38,7 @@ import {
|
|
|
38
38
|
} from "./DataTableRoot.context";
|
|
39
39
|
|
|
40
40
|
interface DataTableProps<T>
|
|
41
|
-
extends
|
|
42
|
-
React.HTMLAttributes<HTMLTableElement>,
|
|
43
|
-
SelectionProps,
|
|
44
|
-
TableSortOptions {
|
|
41
|
+
extends React.HTMLAttributes<HTMLTableElement>, TableSortOptions {
|
|
45
42
|
children?: never;
|
|
46
43
|
/**
|
|
47
44
|
* Controls vertical cell padding.
|
|
@@ -202,12 +199,20 @@ interface DataTableProps<T>
|
|
|
202
199
|
/**
|
|
203
200
|
* Function to get sub-rows for a given row, used for nested rows.
|
|
204
201
|
* When provided, an expand toggle column is added automatically.
|
|
202
|
+
*
|
|
203
|
+
*
|
|
204
|
+
* TODO:
|
|
205
|
+
* - Table might need to be implemented with role="treegrid" for a11y when having nested rows.
|
|
205
206
|
*/
|
|
206
207
|
getSubRows?: (rowData: T) => T[];
|
|
207
208
|
expandedSubRowIds?: (string | number)[];
|
|
208
209
|
defaultExpandedSubRowIds?: (string | number)[];
|
|
209
210
|
isSubRowExpandable?: (rowData: T) => boolean;
|
|
210
211
|
onExpandedSubRowIdsChange?: (ids: (string | number)[]) => void;
|
|
212
|
+
/**
|
|
213
|
+
* Props for row selection functionality.
|
|
214
|
+
*/
|
|
215
|
+
selection?: SelectionProps;
|
|
211
216
|
}
|
|
212
217
|
|
|
213
218
|
function DataTableAutoInner<T>(
|
|
@@ -220,11 +225,7 @@ function DataTableAutoInner<T>(
|
|
|
220
225
|
truncateContent = true,
|
|
221
226
|
shouldBlockNavigation,
|
|
222
227
|
layout = "fixed",
|
|
223
|
-
|
|
224
|
-
selectedKeys,
|
|
225
|
-
defaultSelectedKeys,
|
|
226
|
-
onSelectionChange,
|
|
227
|
-
disabledSelectionKeys = [],
|
|
228
|
+
selection,
|
|
228
229
|
data,
|
|
229
230
|
columnDefinitions,
|
|
230
231
|
getRowId,
|
|
@@ -239,7 +240,6 @@ function DataTableAutoInner<T>(
|
|
|
239
240
|
loadingState,
|
|
240
241
|
loadingRows,
|
|
241
242
|
loadingLabel = "Laster innhold",
|
|
242
|
-
disableRowSelectionOnClick = false,
|
|
243
243
|
getDetailsPanelContent,
|
|
244
244
|
isDetailsPanelExpandable,
|
|
245
245
|
getDetailsPanelHeight,
|
|
@@ -279,15 +279,14 @@ function DataTableAutoInner<T>(
|
|
|
279
279
|
onExpandedSubRowIdsChange,
|
|
280
280
|
});
|
|
281
281
|
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}, [tableItems.itemDetails]);
|
|
282
|
+
const {
|
|
283
|
+
selectionMode: selectionModeProp = "none",
|
|
284
|
+
selectedKeys,
|
|
285
|
+
defaultSelectedKeys,
|
|
286
|
+
onSelectionChange,
|
|
287
|
+
disabledSelectionKeys = [],
|
|
288
|
+
disableRowSelectionOnClick = false,
|
|
289
|
+
} = selection || {};
|
|
291
290
|
|
|
292
291
|
const tableSelectionState = useTableSelection({
|
|
293
292
|
selectionMode: selectionModeProp,
|
|
@@ -295,7 +294,8 @@ function DataTableAutoInner<T>(
|
|
|
295
294
|
defaultSelectedKeys,
|
|
296
295
|
onSelectionChange,
|
|
297
296
|
disabledSelectionKeys,
|
|
298
|
-
|
|
297
|
+
visibleRowIds: tableItems.visibleRowIds,
|
|
298
|
+
childRowIdsById: tableItems.childRowIdsById,
|
|
299
299
|
});
|
|
300
300
|
|
|
301
301
|
const { columns, stickySelection } = useColumnOptions<T>(columnDefinitions, {
|
|
@@ -326,62 +326,62 @@ function DataTableAutoInner<T>(
|
|
|
326
326
|
showLoadingOverlay={isLoading && !loadingState && !loadingRows}
|
|
327
327
|
columns={columns}
|
|
328
328
|
>
|
|
329
|
-
<
|
|
330
|
-
detailsPanelRowIds={detailsPanelRowIds}
|
|
331
|
-
defaultDetailsPanelRowIds={defaultDetailsPanelRowIds}
|
|
332
|
-
onDetailsPanelChange={onDetailsPanelChange}
|
|
329
|
+
<TableItemsProvider
|
|
333
330
|
itemDetails={tableItems.itemDetails}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
showExpandAll={showExpandAll}
|
|
331
|
+
items={tableItems.items}
|
|
332
|
+
onExpandedSubRowIdsChange={tableItems.onExpandedSubRowIdsChange}
|
|
333
|
+
isSubRowExpanded={tableItems.isSubRowExpanded}
|
|
338
334
|
>
|
|
339
|
-
<
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
<DataTableColumnHeader
|
|
362
|
-
maxWidth={colDef.maxWidth}
|
|
363
|
-
minWidth={colDef.minWidth}
|
|
364
|
-
width={colDef.width}
|
|
365
|
-
defaultWidth={colDef.defaultWidth ?? "100%"}
|
|
366
|
-
textAlign={colDef.type === "number" ? "right" : "left"}
|
|
367
|
-
key={colDef.id}
|
|
368
|
-
isSticky={isSticky}
|
|
369
|
-
sortable={colDef.sortable}
|
|
370
|
-
sortDirection={sortDirection}
|
|
371
|
-
onSortClick={(event) => onSortClick(colDef.id, event)}
|
|
372
|
-
>
|
|
373
|
-
{colDef.header}
|
|
374
|
-
</DataTableColumnHeader>
|
|
375
|
-
);
|
|
376
|
-
})}
|
|
377
|
-
</DataTableTr>
|
|
378
|
-
</DataTableThead>
|
|
379
|
-
<TableItemsProvider
|
|
380
|
-
itemDetails={tableItems.itemDetails}
|
|
381
|
-
items={tableItems.items}
|
|
382
|
-
onExpandedSubRowIdsChange={tableItems.onExpandedSubRowIdsChange}
|
|
383
|
-
isSubRowExpanded={tableItems.isSubRowExpanded}
|
|
335
|
+
<DataTableExpansionProvider
|
|
336
|
+
detailsPanelRowIds={detailsPanelRowIds}
|
|
337
|
+
defaultDetailsPanelRowIds={defaultDetailsPanelRowIds}
|
|
338
|
+
onDetailsPanelChange={onDetailsPanelChange}
|
|
339
|
+
getDetailsPanelContent={getDetailsPanelContent}
|
|
340
|
+
isDetailsPanelExpandable={isDetailsPanelExpandable}
|
|
341
|
+
getDetailsPanelHeight={getDetailsPanelHeight}
|
|
342
|
+
showExpandAll={showExpandAll}
|
|
343
|
+
>
|
|
344
|
+
<div className="aksel-data-table__border-wrapper">
|
|
345
|
+
<div className="aksel-data-table__scroll-wrapper">
|
|
346
|
+
<table
|
|
347
|
+
{...rest}
|
|
348
|
+
ref={mergedRef}
|
|
349
|
+
className={cl("aksel-data-table", className)}
|
|
350
|
+
data-zebra-stripes={zebraStripes}
|
|
351
|
+
data-truncate-content={truncateContent}
|
|
352
|
+
data-density={rowDensity}
|
|
353
|
+
data-layout={layout}
|
|
354
|
+
data-loading={isLoading || undefined}
|
|
355
|
+
tabIndex={tabIndex}
|
|
356
|
+
aria-busy={isLoading || undefined}
|
|
384
357
|
>
|
|
358
|
+
<DataTableThead>
|
|
359
|
+
<DataTableTr>
|
|
360
|
+
{columns.map(({ isSticky, colDef }) => {
|
|
361
|
+
const sortEntry = sortState.find(
|
|
362
|
+
(s) => s.columnId === colDef.id,
|
|
363
|
+
);
|
|
364
|
+
const sortDirection = sortEntry?.direction ?? "none";
|
|
365
|
+
return (
|
|
366
|
+
<DataTableColumnHeader
|
|
367
|
+
maxWidth={colDef.maxWidth}
|
|
368
|
+
minWidth={colDef.minWidth}
|
|
369
|
+
width={colDef.width}
|
|
370
|
+
defaultWidth={colDef.defaultWidth ?? "100%"}
|
|
371
|
+
textAlign={colDef.align ?? "left"}
|
|
372
|
+
key={colDef.id}
|
|
373
|
+
isSticky={isSticky}
|
|
374
|
+
sortable={colDef.sortable}
|
|
375
|
+
sortDirection={sortDirection}
|
|
376
|
+
onSortClick={(event) => onSortClick(colDef.id, event)}
|
|
377
|
+
>
|
|
378
|
+
{colDef.header}
|
|
379
|
+
</DataTableColumnHeader>
|
|
380
|
+
);
|
|
381
|
+
})}
|
|
382
|
+
</DataTableTr>
|
|
383
|
+
</DataTableThead>
|
|
384
|
+
|
|
385
385
|
<DataTableTbody>
|
|
386
386
|
<DataTableAutoTBodyContent
|
|
387
387
|
loadingState={loadingState}
|
|
@@ -391,11 +391,11 @@ function DataTableAutoInner<T>(
|
|
|
391
391
|
fullWidthColSpan={fullWidthColSpan}
|
|
392
392
|
/>
|
|
393
393
|
</DataTableTbody>
|
|
394
|
-
</
|
|
395
|
-
</
|
|
394
|
+
</table>
|
|
395
|
+
</div>
|
|
396
396
|
</div>
|
|
397
|
-
</
|
|
398
|
-
</
|
|
397
|
+
</DataTableExpansionProvider>
|
|
398
|
+
</TableItemsProvider>
|
|
399
399
|
</DataTableContextProvider>
|
|
400
400
|
);
|
|
401
401
|
}
|
|
@@ -438,7 +438,7 @@ function DataTableAutoTBodyContent({
|
|
|
438
438
|
<DataTableTr key={`skeleton-row-${rowIndex}`} aria-hidden>
|
|
439
439
|
{columns.map(({ isSticky, colDef }, colDefIndex) => (
|
|
440
440
|
<DataTableBaseCell
|
|
441
|
-
textAlign={colDef.
|
|
441
|
+
textAlign={colDef.align ?? "left"}
|
|
442
442
|
key={colDef.id || colDefIndex}
|
|
443
443
|
as={colDef.isRowHeader ? "th" : "td"}
|
|
444
444
|
isSticky={isSticky}
|
|
@@ -462,59 +462,64 @@ function DataTableAutoTBodyContent({
|
|
|
462
462
|
|
|
463
463
|
const renderLoadingAnnouncement = isLoading && !loadingState && !loadingRows;
|
|
464
464
|
|
|
465
|
-
return
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
{
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
465
|
+
return (
|
|
466
|
+
<>
|
|
467
|
+
{renderLoadingAnnouncement && (
|
|
468
|
+
<tr>
|
|
469
|
+
<td colSpan={fullWidthColSpan} className="aksel-sr-only">
|
|
470
|
+
{loadingLabel}
|
|
471
|
+
</td>
|
|
472
|
+
</tr>
|
|
473
|
+
)}
|
|
474
|
+
{items.map((rowData) => {
|
|
475
|
+
const details = itemDetails.get(rowData);
|
|
476
|
+
|
|
477
|
+
/* Should in theory be impossible. Look about typing this? */
|
|
478
|
+
if (!details) {
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const hasSubRows = details.children.length > 0;
|
|
483
|
+
|
|
484
|
+
return (
|
|
485
|
+
<React.Fragment key={details.id}>
|
|
486
|
+
<DataTableTr rowId={details.id}>
|
|
487
|
+
{columns.map(({ isSticky, colDef }, colDefIndex) => {
|
|
488
|
+
const renderNestedToggle = colDefIndex === 0 && hasSubRows;
|
|
489
|
+
const renderNestedIndent =
|
|
490
|
+
colDefIndex === 0 && (details.level > 0 || hasSubRows);
|
|
491
|
+
|
|
492
|
+
const style: React.CSSProperties = {
|
|
493
|
+
"--__axc-data-table-nested-depth": details.level,
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
return (
|
|
497
|
+
<DataTableBaseCell
|
|
498
|
+
textAlign={colDef.align ?? "left"}
|
|
499
|
+
key={colDef.id || colDefIndex}
|
|
500
|
+
as={colDef.isRowHeader ? "th" : "td"}
|
|
501
|
+
isSticky={isSticky}
|
|
502
|
+
data-nested={renderNestedIndent || undefined}
|
|
503
|
+
style={style}
|
|
504
|
+
>
|
|
505
|
+
{renderNestedToggle && (
|
|
506
|
+
<NestedRowToggle details={details} />
|
|
507
|
+
)}
|
|
508
|
+
{colDef.cell(rowData)}
|
|
509
|
+
</DataTableBaseCell>
|
|
510
|
+
);
|
|
511
|
+
})}
|
|
512
|
+
</DataTableTr>
|
|
513
|
+
<DataTableExpandedRow
|
|
514
|
+
rowId={details.id}
|
|
515
|
+
rowData={rowData}
|
|
516
|
+
fullWidthColSpan={fullWidthColSpan}
|
|
517
|
+
/>
|
|
518
|
+
</React.Fragment>
|
|
519
|
+
);
|
|
520
|
+
})}
|
|
521
|
+
</>
|
|
522
|
+
);
|
|
518
523
|
}
|
|
519
524
|
|
|
520
525
|
function NestedRowToggle({ details }: { details: ItemDetail<any> }) {
|
|
@@ -583,12 +588,16 @@ function DataTableExpandedRow<T>({
|
|
|
583
588
|
return null;
|
|
584
589
|
}
|
|
585
590
|
|
|
591
|
+
const panelHeight = getDetailsPanelHeight?.(rowData);
|
|
592
|
+
|
|
593
|
+
const style: React.CSSProperties = panelHeight
|
|
594
|
+
? { height: panelHeight, overflow: "auto" }
|
|
595
|
+
: { height: "auto" };
|
|
596
|
+
|
|
586
597
|
return (
|
|
587
598
|
<tr>
|
|
588
599
|
<td id={expansionId} colSpan={fullWidthColSpan}>
|
|
589
|
-
<div style={{
|
|
590
|
-
{content}
|
|
591
|
-
</div>
|
|
600
|
+
<div style={style}>{content}</div>
|
|
592
601
|
</td>
|
|
593
602
|
</tr>
|
|
594
603
|
);
|
|
@@ -11,10 +11,11 @@ import {
|
|
|
11
11
|
type DataTableEmptyStateProps,
|
|
12
12
|
} from "../empty-state/DataTableEmptyState";
|
|
13
13
|
import { DataTableExpansionProvider } from "../hooks/useTableExpansion";
|
|
14
|
-
import type { ItemDetail } from "../hooks/useTableItems";
|
|
15
14
|
import { useTableKeyboardNav } from "../hooks/useTableKeyboardNav";
|
|
16
|
-
import {
|
|
17
|
-
|
|
15
|
+
import {
|
|
16
|
+
type SelectionProps,
|
|
17
|
+
noSelectionState,
|
|
18
|
+
} from "../hooks/useTableSelection";
|
|
18
19
|
import {
|
|
19
20
|
DataTableLoadingState,
|
|
20
21
|
type DataTableLoadingStateProps,
|
|
@@ -36,8 +37,6 @@ import {
|
|
|
36
37
|
import { DataTableTr, type DataTableTrProps } from "../tr/DataTableTr";
|
|
37
38
|
import { DataTableContextProvider } from "./DataTableRoot.context";
|
|
38
39
|
|
|
39
|
-
const EMPTY_ITEM_DETAILS = new Map<never, ItemDetail<never>>();
|
|
40
|
-
|
|
41
40
|
interface DataTableProps
|
|
42
41
|
extends React.HTMLAttributes<HTMLTableElement>, SelectionProps {
|
|
43
42
|
children: React.ReactNode;
|
|
@@ -232,7 +231,7 @@ const DataTable = forwardRef<HTMLTableElement, DataTableProps>(
|
|
|
232
231
|
withKeyboardNav={withKeyboardNav}
|
|
233
232
|
selectionState={noSelectionState}
|
|
234
233
|
stickySelection={false}
|
|
235
|
-
stickyHeader={
|
|
234
|
+
stickyHeader={true}
|
|
236
235
|
tableId={useId()}
|
|
237
236
|
showLoadingSkeletons={false}
|
|
238
237
|
onRowClick={undefined}
|
|
@@ -240,7 +239,7 @@ const DataTable = forwardRef<HTMLTableElement, DataTableProps>(
|
|
|
240
239
|
showLoadingOverlay={false}
|
|
241
240
|
columns={[]}
|
|
242
241
|
>
|
|
243
|
-
<DataTableExpansionProvider
|
|
242
|
+
<DataTableExpansionProvider>
|
|
244
243
|
<div className="aksel-data-table__border-wrapper">
|
|
245
244
|
<div className="aksel-data-table__scroll-wrapper">
|
|
246
245
|
<table
|
package/src/form/radio/Radio.tsx
CHANGED
|
@@ -24,7 +24,13 @@ export const Radio = forwardRef<HTMLInputElement, RadioProps>(
|
|
|
24
24
|
>
|
|
25
25
|
<RadioInput
|
|
26
26
|
ref={forwardedRef}
|
|
27
|
-
{...omit(props, [
|
|
27
|
+
{...omit(props, [
|
|
28
|
+
"children",
|
|
29
|
+
"size",
|
|
30
|
+
"description",
|
|
31
|
+
"readOnly",
|
|
32
|
+
"className",
|
|
33
|
+
])}
|
|
28
34
|
{...omit(inputProps, ["aria-invalid", "aria-describedby"])}
|
|
29
35
|
aria-describedby={
|
|
30
36
|
cl(inputProps["aria-describedby"], {
|
package/src/modal/types.ts
CHANGED
|
@@ -39,7 +39,8 @@ interface ModalPropsBase extends React.DialogHTMLAttributes<HTMLDialogElement> {
|
|
|
39
39
|
/**
|
|
40
40
|
* Called when the user tries to close the modal by one of the built-in methods.
|
|
41
41
|
* Used if you want to ask the user for confirmation before closing.
|
|
42
|
-
*
|
|
42
|
+
*
|
|
43
|
+
* **NB:** Will not always be called when pressing Esc. See `onCancel` for more info.
|
|
43
44
|
* @returns Whether to close the modal or not
|
|
44
45
|
*/
|
|
45
46
|
onBeforeClose?: () => boolean;
|
|
@@ -52,7 +53,8 @@ interface ModalPropsBase extends React.DialogHTMLAttributes<HTMLDialogElement> {
|
|
|
52
53
|
onCancel?: React.ReactEventHandler<HTMLDialogElement>;
|
|
53
54
|
/**
|
|
54
55
|
* Whether to close when clicking on the backdrop.
|
|
55
|
-
*
|
|
56
|
+
*
|
|
57
|
+
* **NB:** Users may click outside by accident. Don't use if closing can cause data loss, or the modal contains important info.
|
|
56
58
|
* @default false
|
|
57
59
|
*/
|
|
58
60
|
closeOnBackdropClick?: boolean;
|
|
@@ -77,13 +79,15 @@ interface ModalPropsBase extends React.DialogHTMLAttributes<HTMLDialogElement> {
|
|
|
77
79
|
/**
|
|
78
80
|
* ID of the element that labels the modal.
|
|
79
81
|
* No need to set this manually if the `header` prop is used. A reference to `header.heading` will be created automatically.
|
|
80
|
-
*
|
|
82
|
+
*
|
|
83
|
+
* **NB:** If not using `header`, you should set either `aria-labelledby` or `aria-label`.
|
|
81
84
|
*/
|
|
82
85
|
"aria-labelledby"?: string;
|
|
83
86
|
/**
|
|
84
87
|
* String value that labels the modal.
|
|
85
88
|
* No need to set this if the `header` prop is used.
|
|
86
|
-
*
|
|
89
|
+
*
|
|
90
|
+
* **NB:** If not using `header`, you should set either `aria-labelledby` or `aria-label`.
|
|
87
91
|
*/
|
|
88
92
|
"aria-label"?: string;
|
|
89
93
|
}
|