@navikt/ds-react 8.10.1 → 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.d.ts +1 -1
- package/cjs/data/table/column-header/DataTableColumnHeader.js +16 -11
- package/cjs/data/table/column-header/DataTableColumnHeader.js.map +1 -1
- package/cjs/data/table/column-header/useTableColumnResize.d.ts +28 -4
- package/cjs/data/table/column-header/useTableColumnResize.js +144 -53
- package/cjs/data/table/column-header/useTableColumnResize.js.map +1 -1
- package/cjs/data/table/helpers/collectTableRowEntries.d.ts +24 -0
- package/cjs/data/table/helpers/collectTableRowEntries.js +35 -0
- package/cjs/data/table/helpers/collectTableRowEntries.js.map +1 -0
- 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 -5
- package/cjs/data/table/helpers/table-keyboard.js.map +1 -1
- package/cjs/data/table/hooks/useTableExpansion.d.ts +7 -6
- package/cjs/data/table/hooks/useTableExpansion.js +42 -15
- package/cjs/data/table/hooks/useTableExpansion.js.map +1 -1
- package/cjs/data/table/hooks/useTableItems.d.ts +33 -0
- package/cjs/data/table/hooks/useTableItems.js +74 -0
- package/cjs/data/table/hooks/useTableItems.js.map +1 -0
- package/cjs/data/table/hooks/useTableKeyboardNav.js +3 -3
- package/cjs/data/table/hooks/useTableKeyboardNav.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 +27 -1
- package/cjs/data/table/root/DataTableAuto.js +92 -50
- package/cjs/data/table/root/DataTableAuto.js.map +1 -1
- package/cjs/data/table/root/DataTableRoot.context.d.ts +5 -3
- package/cjs/data/table/root/DataTableRoot.context.js.map +1 -1
- package/cjs/data/table/root/DataTableRoot.js +6 -4
- package/cjs/data/table/root/DataTableRoot.js.map +1 -1
- package/cjs/data/table/tr/DataTableTr.js +30 -32
- package/cjs/data/table/tr/DataTableTr.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.d.ts +1 -1
- package/esm/data/table/column-header/DataTableColumnHeader.js +17 -12
- package/esm/data/table/column-header/DataTableColumnHeader.js.map +1 -1
- package/esm/data/table/column-header/useTableColumnResize.d.ts +28 -4
- package/esm/data/table/column-header/useTableColumnResize.js +145 -54
- package/esm/data/table/column-header/useTableColumnResize.js.map +1 -1
- package/esm/data/table/helpers/collectTableRowEntries.d.ts +24 -0
- package/esm/data/table/helpers/collectTableRowEntries.js +33 -0
- package/esm/data/table/helpers/collectTableRowEntries.js.map +1 -0
- 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 -5
- package/esm/data/table/helpers/table-keyboard.js.map +1 -1
- package/esm/data/table/hooks/useTableExpansion.d.ts +7 -6
- package/esm/data/table/hooks/useTableExpansion.js +42 -16
- package/esm/data/table/hooks/useTableExpansion.js.map +1 -1
- package/esm/data/table/hooks/useTableItems.d.ts +33 -0
- package/esm/data/table/hooks/useTableItems.js +69 -0
- package/esm/data/table/hooks/useTableItems.js.map +1 -0
- package/esm/data/table/hooks/useTableKeyboardNav.js +3 -3
- package/esm/data/table/hooks/useTableKeyboardNav.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 +27 -1
- package/esm/data/table/root/DataTableAuto.js +94 -52
- package/esm/data/table/root/DataTableAuto.js.map +1 -1
- package/esm/data/table/root/DataTableRoot.context.d.ts +5 -3
- package/esm/data/table/root/DataTableRoot.context.js.map +1 -1
- package/esm/data/table/root/DataTableRoot.js +7 -5
- package/esm/data/table/root/DataTableRoot.js.map +1 -1
- package/esm/data/table/tr/DataTableTr.js +32 -34
- package/esm/data/table/tr/DataTableTr.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 +7 -7
- package/src/data/table/column-header/DataTableColumnHeader.tsx +26 -14
- package/src/data/table/column-header/useTableColumnResize.ts +209 -80
- package/src/data/table/helpers/collectTableRowEntries.ts +90 -0
- 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 -6
- package/src/data/table/hooks/__tests__/useTableItems.test.ts +145 -0
- package/src/data/table/hooks/__tests__/useTableSelection.test.ts +132 -21
- package/src/data/table/hooks/useTableExpansion.tsx +68 -22
- package/src/data/table/hooks/useTableItems.ts +146 -0
- package/src/data/table/hooks/useTableKeyboardNav.ts +3 -3
- 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 +244 -0
- package/src/data/table/root/DataTableAuto.tsx +260 -141
- package/src/data/table/root/DataTableRoot.context.ts +4 -2
- package/src/data/table/root/DataTableRoot.tsx +22 -16
- package/src/data/table/tr/DataTableTr.tsx +48 -47
- package/src/form/checkbox/Checkbox.tsx +1 -0
- package/src/form/radio/Radio.tsx +7 -1
- package/src/modal/types.ts +8 -4
|
@@ -1,5 +1,7 @@
|
|
|
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
|
+
import { ChevronDownIcon, ChevronRightIcon } from "@navikt/aksel-icons";
|
|
4
|
+
import { Button } from "../../../button";
|
|
3
5
|
import { Skeleton } from "../../../skeleton";
|
|
4
6
|
import { useId } from "../../../utils-external";
|
|
5
7
|
import { cl } from "../../../utils/helpers";
|
|
@@ -7,12 +9,18 @@ import { useMergeRefs } from "../../../utils/hooks";
|
|
|
7
9
|
import { DataTableBaseCell } from "../base-cell/DataTableBaseCell";
|
|
8
10
|
import { DataTableColumnHeader } from "../column-header/DataTableColumnHeader";
|
|
9
11
|
import { DataTableEmptyState } from "../empty-state/DataTableEmptyState";
|
|
10
|
-
import type { UseColumnOptionsResult } from "../hooks/useColumnOptions";
|
|
11
12
|
import { useColumnOptions } from "../hooks/useColumnOptions";
|
|
12
13
|
import {
|
|
13
14
|
DataTableExpansionProvider,
|
|
15
|
+
getDataTableExpansionId,
|
|
14
16
|
useDataTableExpansion,
|
|
15
17
|
} from "../hooks/useTableExpansion";
|
|
18
|
+
import {
|
|
19
|
+
type ItemDetail,
|
|
20
|
+
TableItemsProvider,
|
|
21
|
+
useTableItems,
|
|
22
|
+
useTableItemsContext,
|
|
23
|
+
} from "../hooks/useTableItems";
|
|
16
24
|
import { useTableKeyboardNav } from "../hooks/useTableKeyboardNav";
|
|
17
25
|
import {
|
|
18
26
|
type SelectionProps,
|
|
@@ -30,10 +38,7 @@ import {
|
|
|
30
38
|
} from "./DataTableRoot.context";
|
|
31
39
|
|
|
32
40
|
interface DataTableProps<T>
|
|
33
|
-
extends
|
|
34
|
-
React.HTMLAttributes<HTMLTableElement>,
|
|
35
|
-
SelectionProps,
|
|
36
|
-
TableSortOptions {
|
|
41
|
+
extends React.HTMLAttributes<HTMLTableElement>, TableSortOptions {
|
|
37
42
|
children?: never;
|
|
38
43
|
/**
|
|
39
44
|
* Controls vertical cell padding.
|
|
@@ -157,6 +162,11 @@ interface DataTableProps<T>
|
|
|
157
162
|
* When provided, an expand toggle column is added automatically.
|
|
158
163
|
*/
|
|
159
164
|
getDetailsPanelContent?: (rowData: T) => React.ReactNode;
|
|
165
|
+
/**
|
|
166
|
+
* Determines whether a row can be expanded to show details panel content.
|
|
167
|
+
* @default () => true
|
|
168
|
+
*/
|
|
169
|
+
isDetailsPanelExpandable?: (rowData: T) => boolean;
|
|
160
170
|
/**
|
|
161
171
|
* Controlled list of expanded row IDs.
|
|
162
172
|
* Use with `onDetailsPanelChange` for controlled usage, or `defaultDetailsPanelRowIds` for uncontrolled.
|
|
@@ -169,6 +179,10 @@ interface DataTableProps<T>
|
|
|
169
179
|
defaultDetailsPanelRowIds?: (string | number)[];
|
|
170
180
|
/**
|
|
171
181
|
* Called when the list of expanded row IDs changes.
|
|
182
|
+
*
|
|
183
|
+
*
|
|
184
|
+
* TODO:
|
|
185
|
+
* - Docs: This pattern is called "Master / Detail" in general terms
|
|
172
186
|
*/
|
|
173
187
|
onDetailsPanelChange?: (ids: (string | number)[]) => void;
|
|
174
188
|
/**
|
|
@@ -182,6 +196,23 @@ interface DataTableProps<T>
|
|
|
182
196
|
* @default false
|
|
183
197
|
*/
|
|
184
198
|
showExpandAll?: boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Function to get sub-rows for a given row, used for nested rows.
|
|
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.
|
|
206
|
+
*/
|
|
207
|
+
getSubRows?: (rowData: T) => T[];
|
|
208
|
+
expandedSubRowIds?: (string | number)[];
|
|
209
|
+
defaultExpandedSubRowIds?: (string | number)[];
|
|
210
|
+
isSubRowExpandable?: (rowData: T) => boolean;
|
|
211
|
+
onExpandedSubRowIdsChange?: (ids: (string | number)[]) => void;
|
|
212
|
+
/**
|
|
213
|
+
* Props for row selection functionality.
|
|
214
|
+
*/
|
|
215
|
+
selection?: SelectionProps;
|
|
185
216
|
}
|
|
186
217
|
|
|
187
218
|
function DataTableAutoInner<T>(
|
|
@@ -194,11 +225,7 @@ function DataTableAutoInner<T>(
|
|
|
194
225
|
truncateContent = true,
|
|
195
226
|
shouldBlockNavigation,
|
|
196
227
|
layout = "fixed",
|
|
197
|
-
|
|
198
|
-
selectedKeys,
|
|
199
|
-
defaultSelectedKeys,
|
|
200
|
-
onSelectionChange,
|
|
201
|
-
disabledSelectionKeys = [],
|
|
228
|
+
selection,
|
|
202
229
|
data,
|
|
203
230
|
columnDefinitions,
|
|
204
231
|
getRowId,
|
|
@@ -213,13 +240,18 @@ function DataTableAutoInner<T>(
|
|
|
213
240
|
loadingState,
|
|
214
241
|
loadingRows,
|
|
215
242
|
loadingLabel = "Laster innhold",
|
|
216
|
-
disableRowSelectionOnClick = false,
|
|
217
243
|
getDetailsPanelContent,
|
|
244
|
+
isDetailsPanelExpandable,
|
|
218
245
|
getDetailsPanelHeight,
|
|
219
246
|
showExpandAll = false,
|
|
220
247
|
detailsPanelRowIds,
|
|
221
248
|
defaultDetailsPanelRowIds,
|
|
222
249
|
onDetailsPanelChange,
|
|
250
|
+
getSubRows,
|
|
251
|
+
expandedSubRowIds,
|
|
252
|
+
defaultExpandedSubRowIds,
|
|
253
|
+
isSubRowExpandable,
|
|
254
|
+
onExpandedSubRowIdsChange,
|
|
223
255
|
...rest
|
|
224
256
|
}: DataTableProps<T>,
|
|
225
257
|
forwardedRef: React.ForwardedRef<HTMLTableElement>,
|
|
@@ -237,12 +269,24 @@ function DataTableAutoInner<T>(
|
|
|
237
269
|
|
|
238
270
|
const mergedRef = useMergeRefs(forwardedRef, setTableRef);
|
|
239
271
|
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
272
|
+
const tableItems = useTableItems({
|
|
273
|
+
items: data,
|
|
274
|
+
getRowId,
|
|
275
|
+
getSubRows,
|
|
276
|
+
expandedSubRowIds,
|
|
277
|
+
defaultExpandedSubRowIds,
|
|
278
|
+
isSubRowExpandable,
|
|
279
|
+
onExpandedSubRowIdsChange,
|
|
280
|
+
});
|
|
243
281
|
|
|
244
|
-
|
|
245
|
-
|
|
282
|
+
const {
|
|
283
|
+
selectionMode: selectionModeProp = "none",
|
|
284
|
+
selectedKeys,
|
|
285
|
+
defaultSelectedKeys,
|
|
286
|
+
onSelectionChange,
|
|
287
|
+
disabledSelectionKeys = [],
|
|
288
|
+
disableRowSelectionOnClick = false,
|
|
289
|
+
} = selection || {};
|
|
246
290
|
|
|
247
291
|
const tableSelectionState = useTableSelection({
|
|
248
292
|
selectionMode: selectionModeProp,
|
|
@@ -250,7 +294,8 @@ function DataTableAutoInner<T>(
|
|
|
250
294
|
defaultSelectedKeys,
|
|
251
295
|
onSelectionChange,
|
|
252
296
|
disabledSelectionKeys,
|
|
253
|
-
|
|
297
|
+
visibleRowIds: tableItems.visibleRowIds,
|
|
298
|
+
childRowIdsById: tableItems.childRowIdsById,
|
|
254
299
|
});
|
|
255
300
|
|
|
256
301
|
const { columns, stickySelection } = useColumnOptions<T>(columnDefinitions, {
|
|
@@ -258,6 +303,12 @@ function DataTableAutoInner<T>(
|
|
|
258
303
|
selectionMode: tableSelectionState.selection.selectionMode,
|
|
259
304
|
});
|
|
260
305
|
|
|
306
|
+
const fullWidthColSpan =
|
|
307
|
+
columns.length +
|
|
308
|
+
(layout === "fixed" ? 1 : 0) +
|
|
309
|
+
(tableSelectionState.selection.selectionMode !== "none" ? 1 : 0) +
|
|
310
|
+
(getDetailsPanelContent ? 1 : 0);
|
|
311
|
+
|
|
261
312
|
const tableId = useId(id);
|
|
262
313
|
|
|
263
314
|
return (
|
|
@@ -273,99 +324,103 @@ function DataTableAutoInner<T>(
|
|
|
273
324
|
disableRowSelectionOnClick={disableRowSelectionOnClick}
|
|
274
325
|
isLoading={isLoading}
|
|
275
326
|
showLoadingOverlay={isLoading && !loadingState && !loadingRows}
|
|
327
|
+
columns={columns}
|
|
276
328
|
>
|
|
277
|
-
<
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
getDetailsPanelContent={getDetailsPanelContent}
|
|
283
|
-
getDetailsPanelHeight={getDetailsPanelHeight}
|
|
284
|
-
showExpandAll={showExpandAll}
|
|
329
|
+
<TableItemsProvider
|
|
330
|
+
itemDetails={tableItems.itemDetails}
|
|
331
|
+
items={tableItems.items}
|
|
332
|
+
onExpandedSubRowIdsChange={tableItems.onExpandedSubRowIdsChange}
|
|
333
|
+
isSubRowExpanded={tableItems.isSubRowExpanded}
|
|
285
334
|
>
|
|
286
|
-
<
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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}
|
|
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
|
+
<DataTableTbody>
|
|
386
|
+
<DataTableAutoTBodyContent
|
|
387
|
+
loadingState={loadingState}
|
|
388
|
+
loadingRows={loadingRows}
|
|
389
|
+
loadingLabel={loadingLabel}
|
|
390
|
+
emptyState={emptyState}
|
|
391
|
+
fullWidthColSpan={fullWidthColSpan}
|
|
392
|
+
/>
|
|
393
|
+
</DataTableTbody>
|
|
394
|
+
</table>
|
|
395
|
+
</div>
|
|
338
396
|
</div>
|
|
339
|
-
</
|
|
340
|
-
</
|
|
397
|
+
</DataTableExpansionProvider>
|
|
398
|
+
</TableItemsProvider>
|
|
341
399
|
</DataTableContextProvider>
|
|
342
400
|
);
|
|
343
401
|
}
|
|
344
402
|
|
|
345
|
-
interface DataTableAutoTBodyContentProps
|
|
346
|
-
columns: UseColumnOptionsResult<T>["columns"];
|
|
347
|
-
data: T[];
|
|
348
|
-
allRowKeys: (string | number)[];
|
|
403
|
+
interface DataTableAutoTBodyContentProps {
|
|
349
404
|
loadingState: React.ReactNode;
|
|
350
405
|
loadingLabel: string;
|
|
351
406
|
loadingRows?: number;
|
|
352
407
|
emptyState: React.ReactNode;
|
|
408
|
+
fullWidthColSpan: number;
|
|
353
409
|
}
|
|
354
410
|
|
|
355
|
-
function DataTableAutoTBodyContent
|
|
356
|
-
columns,
|
|
357
|
-
data,
|
|
358
|
-
allRowKeys,
|
|
411
|
+
function DataTableAutoTBodyContent({
|
|
359
412
|
loadingState,
|
|
360
413
|
loadingRows,
|
|
361
414
|
loadingLabel,
|
|
362
415
|
emptyState,
|
|
363
|
-
|
|
364
|
-
|
|
416
|
+
fullWidthColSpan,
|
|
417
|
+
}: DataTableAutoTBodyContentProps) {
|
|
418
|
+
const { items, itemDetails } = useTableItemsContext();
|
|
419
|
+
const { columns, isLoading } = useDataTableContext();
|
|
365
420
|
|
|
366
421
|
if (isLoading && loadingState != null) {
|
|
367
422
|
return (
|
|
368
|
-
<DataTableLoadingState colSpan={
|
|
423
|
+
<DataTableLoadingState colSpan={fullWidthColSpan}>
|
|
369
424
|
{loadingState}
|
|
370
425
|
</DataTableLoadingState>
|
|
371
426
|
);
|
|
@@ -375,7 +430,7 @@ function DataTableAutoTBodyContent<T>({
|
|
|
375
430
|
return (
|
|
376
431
|
<>
|
|
377
432
|
<tr>
|
|
378
|
-
<td colSpan={
|
|
433
|
+
<td colSpan={fullWidthColSpan} className="aksel-sr-only">
|
|
379
434
|
{loadingLabel}
|
|
380
435
|
</td>
|
|
381
436
|
</tr>
|
|
@@ -383,7 +438,7 @@ function DataTableAutoTBodyContent<T>({
|
|
|
383
438
|
<DataTableTr key={`skeleton-row-${rowIndex}`} aria-hidden>
|
|
384
439
|
{columns.map(({ isSticky, colDef }, colDefIndex) => (
|
|
385
440
|
<DataTableBaseCell
|
|
386
|
-
textAlign={colDef.
|
|
441
|
+
textAlign={colDef.align ?? "left"}
|
|
387
442
|
key={colDef.id || colDefIndex}
|
|
388
443
|
as={colDef.isRowHeader ? "th" : "td"}
|
|
389
444
|
isSticky={isSticky}
|
|
@@ -397,88 +452,152 @@ function DataTableAutoTBodyContent<T>({
|
|
|
397
452
|
);
|
|
398
453
|
}
|
|
399
454
|
|
|
400
|
-
if (
|
|
455
|
+
if (items.length === 0 && emptyState !== undefined) {
|
|
401
456
|
return (
|
|
402
|
-
<DataTableEmptyState colSpan={
|
|
457
|
+
<DataTableEmptyState colSpan={fullWidthColSpan}>
|
|
403
458
|
{emptyState}
|
|
404
459
|
</DataTableEmptyState>
|
|
405
460
|
);
|
|
406
461
|
}
|
|
407
462
|
|
|
408
|
-
const
|
|
463
|
+
const renderLoadingAnnouncement = isLoading && !loadingState && !loadingRows;
|
|
409
464
|
|
|
410
|
-
return
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
)
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
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
|
+
);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function NestedRowToggle({ details }: { details: ItemDetail<any> }) {
|
|
526
|
+
const { isSubRowExpanded, onExpandedSubRowIdsChange } =
|
|
527
|
+
useTableItemsContext();
|
|
528
|
+
|
|
529
|
+
const subRows = details.children;
|
|
530
|
+
const hasSubRows = subRows && subRows.length > 0;
|
|
531
|
+
const isRowExpanded = isSubRowExpanded(details.id);
|
|
532
|
+
|
|
533
|
+
return (
|
|
534
|
+
<div className="aksel-data-table__nested-toggle">
|
|
535
|
+
{hasSubRows && (
|
|
536
|
+
<Button
|
|
537
|
+
variant="tertiary"
|
|
538
|
+
data-color="neutral"
|
|
539
|
+
size="small"
|
|
540
|
+
onClick={(e) => {
|
|
541
|
+
e.stopPropagation();
|
|
542
|
+
onExpandedSubRowIdsChange(details.id);
|
|
543
|
+
}}
|
|
544
|
+
aria-expanded={isRowExpanded}
|
|
545
|
+
aria-label={isRowExpanded ? "Skjul under-rader" : "Vis under-rader"}
|
|
546
|
+
icon={
|
|
547
|
+
isRowExpanded ? (
|
|
548
|
+
<ChevronDownIcon aria-hidden />
|
|
549
|
+
) : (
|
|
550
|
+
<ChevronRightIcon aria-hidden />
|
|
551
|
+
)
|
|
552
|
+
}
|
|
440
553
|
/>
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
554
|
+
)}
|
|
555
|
+
</div>
|
|
556
|
+
);
|
|
444
557
|
}
|
|
445
558
|
|
|
446
559
|
function DataTableExpandedRow<T>({
|
|
447
560
|
rowId,
|
|
448
561
|
rowData,
|
|
449
|
-
|
|
562
|
+
fullWidthColSpan,
|
|
450
563
|
}: {
|
|
451
564
|
rowId: string | number;
|
|
452
565
|
rowData: T;
|
|
453
|
-
|
|
566
|
+
fullWidthColSpan: number;
|
|
454
567
|
}) {
|
|
455
568
|
const { tableId } = useDataTableContext();
|
|
456
|
-
const
|
|
569
|
+
const {
|
|
570
|
+
enableDetailsPanel,
|
|
571
|
+
isExpanded,
|
|
572
|
+
getDetailsPanelContent,
|
|
573
|
+
getDetailsPanelHeight,
|
|
574
|
+
} = useDataTableExpansion();
|
|
457
575
|
|
|
458
|
-
|
|
459
|
-
if (!expansionContext) {
|
|
576
|
+
if (!enableDetailsPanel) {
|
|
460
577
|
return null;
|
|
461
578
|
}
|
|
462
579
|
|
|
463
|
-
const { isExpanded, getDetailsPanelContent, getDetailsPanelHeight } =
|
|
464
|
-
expansionContext;
|
|
465
|
-
|
|
466
580
|
if (!isExpanded(rowId)) {
|
|
467
581
|
return null;
|
|
468
582
|
}
|
|
469
583
|
|
|
470
584
|
const content = getDetailsPanelContent?.(rowData);
|
|
585
|
+
const expansionId = getDataTableExpansionId(tableId, rowId);
|
|
471
586
|
|
|
472
587
|
if (!content) {
|
|
473
588
|
return null;
|
|
474
589
|
}
|
|
475
590
|
|
|
591
|
+
const panelHeight = getDetailsPanelHeight?.(rowData);
|
|
592
|
+
|
|
593
|
+
const style: React.CSSProperties = panelHeight
|
|
594
|
+
? { height: panelHeight, overflow: "auto" }
|
|
595
|
+
: { height: "auto" };
|
|
596
|
+
|
|
476
597
|
return (
|
|
477
598
|
<tr>
|
|
478
|
-
<td id={
|
|
479
|
-
<div style={{
|
|
480
|
-
{content}
|
|
481
|
-
</div>
|
|
599
|
+
<td id={expansionId} colSpan={fullWidthColSpan}>
|
|
600
|
+
<div style={style}>{content}</div>
|
|
482
601
|
</td>
|
|
483
602
|
</tr>
|
|
484
603
|
);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createStrictContext } from "../../../utils/helpers";
|
|
2
|
+
import type { UseColumnOptionsResult } from "../hooks/useColumnOptions";
|
|
2
3
|
import type { UseTableSelectionReturn } from "../hooks/useTableSelection";
|
|
3
4
|
|
|
4
|
-
type DataTableContextProps = {
|
|
5
|
+
type DataTableContextProps<T> = {
|
|
5
6
|
layout: "fixed" | "auto";
|
|
6
7
|
withKeyboardNav: boolean;
|
|
7
8
|
selectionState: UseTableSelectionReturn;
|
|
@@ -16,10 +17,11 @@ type DataTableContextProps = {
|
|
|
16
17
|
disableRowSelectionOnClick: boolean;
|
|
17
18
|
isLoading?: boolean;
|
|
18
19
|
showLoadingOverlay: boolean;
|
|
20
|
+
columns: UseColumnOptionsResult<T>["columns"];
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
const { Provider: DataTableContextProvider, useContext: useDataTableContext } =
|
|
22
|
-
createStrictContext<DataTableContextProps
|
|
24
|
+
createStrictContext<DataTableContextProps<any>>({
|
|
23
25
|
name: "DataTableContext",
|
|
24
26
|
errorMessage: "useDataTableContext must be used within DataTable",
|
|
25
27
|
});
|
|
@@ -10,9 +10,12 @@ import {
|
|
|
10
10
|
DataTableEmptyState,
|
|
11
11
|
type DataTableEmptyStateProps,
|
|
12
12
|
} from "../empty-state/DataTableEmptyState";
|
|
13
|
+
import { DataTableExpansionProvider } from "../hooks/useTableExpansion";
|
|
13
14
|
import { useTableKeyboardNav } from "../hooks/useTableKeyboardNav";
|
|
14
|
-
import {
|
|
15
|
-
|
|
15
|
+
import {
|
|
16
|
+
type SelectionProps,
|
|
17
|
+
noSelectionState,
|
|
18
|
+
} from "../hooks/useTableSelection";
|
|
16
19
|
import {
|
|
17
20
|
DataTableLoadingState,
|
|
18
21
|
type DataTableLoadingStateProps,
|
|
@@ -228,27 +231,30 @@ const DataTable = forwardRef<HTMLTableElement, DataTableProps>(
|
|
|
228
231
|
withKeyboardNav={withKeyboardNav}
|
|
229
232
|
selectionState={noSelectionState}
|
|
230
233
|
stickySelection={false}
|
|
231
|
-
stickyHeader={
|
|
234
|
+
stickyHeader={true}
|
|
232
235
|
tableId={useId()}
|
|
233
236
|
showLoadingSkeletons={false}
|
|
234
237
|
onRowClick={undefined}
|
|
235
238
|
disableRowSelectionOnClick={false}
|
|
236
239
|
showLoadingOverlay={false}
|
|
240
|
+
columns={[]}
|
|
237
241
|
>
|
|
238
|
-
<
|
|
239
|
-
<div className="aksel-data-
|
|
240
|
-
<
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
242
|
+
<DataTableExpansionProvider>
|
|
243
|
+
<div className="aksel-data-table__border-wrapper">
|
|
244
|
+
<div className="aksel-data-table__scroll-wrapper">
|
|
245
|
+
<table
|
|
246
|
+
{...rest}
|
|
247
|
+
ref={mergedRef}
|
|
248
|
+
className={cl("aksel-data-table", className)}
|
|
249
|
+
data-zebra-stripes={zebraStripes}
|
|
250
|
+
data-truncate-content={truncateContent}
|
|
251
|
+
data-density={rowDensity}
|
|
252
|
+
data-layout={layout}
|
|
253
|
+
tabIndex={tabIndex}
|
|
254
|
+
/>
|
|
255
|
+
</div>
|
|
250
256
|
</div>
|
|
251
|
-
</
|
|
257
|
+
</DataTableExpansionProvider>
|
|
252
258
|
</DataTableContextProvider>
|
|
253
259
|
);
|
|
254
260
|
},
|