@navikt/ds-react 8.10.6 → 8.11.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/cjs/data/drag-and-drop/root/DragAndDropRoot.d.ts +1 -1
- package/cjs/data/drag-and-drop/root/DragAndDropRoot.js +2 -2
- package/cjs/data/drag-and-drop/root/DragAndDropRoot.js.map +1 -1
- package/cjs/data/stories/Data.test-data.d.ts +2 -2
- package/cjs/data/stories/Data.test-data.js +37 -42
- package/cjs/data/stories/Data.test-data.js.map +1 -1
- package/cjs/data/table/base-cell/DataTableBaseCell.d.ts +4 -4
- package/cjs/data/table/base-cell/DataTableBaseCell.js +2 -2
- package/cjs/data/table/base-cell/DataTableBaseCell.js.map +1 -1
- package/cjs/data/table/column-header/DataTableColumnHeader.d.ts +3 -15
- package/cjs/data/table/column-header/DataTableColumnHeader.js +8 -5
- package/cjs/data/table/column-header/DataTableColumnHeader.js.map +1 -1
- package/cjs/data/table/column-header/useTableColumnResize.d.ts +2 -2
- package/cjs/data/table/column-header/useTableColumnResize.js +10 -10
- package/cjs/data/table/column-header/useTableColumnResize.js.map +1 -1
- package/cjs/data/table/helpers/collectTableRowEntries.d.ts +1 -1
- package/cjs/data/table/helpers/selection/getMultipleSelectProps.d.ts +6 -5
- package/cjs/data/table/helpers/selection/getMultipleSelectProps.js +6 -2
- package/cjs/data/table/helpers/selection/getMultipleSelectProps.js.map +1 -1
- package/cjs/data/table/helpers/selection/getSingleSelectProps.d.ts +3 -3
- package/cjs/data/table/helpers/selection/getSingleSelectProps.js +1 -1
- package/cjs/data/table/helpers/selection/getSingleSelectProps.js.map +1 -1
- package/cjs/data/table/helpers/selection/selection.types.d.ts +19 -27
- package/cjs/data/table/helpers/selection/selection.utils.d.ts +1 -1
- package/cjs/data/table/hooks/useColumnOptions.d.ts +3 -3
- package/cjs/data/table/hooks/useColumnOptions.js +2 -2
- package/cjs/data/table/hooks/useColumnOptions.js.map +1 -1
- package/cjs/data/table/hooks/useTableDetailsPanel.d.ts +8 -9
- package/cjs/data/table/hooks/useTableDetailsPanel.js.map +1 -1
- package/cjs/data/table/hooks/useTableItems.d.ts +10 -11
- package/cjs/data/table/hooks/useTableItems.js +11 -3
- package/cjs/data/table/hooks/useTableItems.js.map +1 -1
- package/cjs/data/table/hooks/useTableSelection.d.ts +2 -1
- package/cjs/data/table/hooks/useTableSelection.js +46 -29
- package/cjs/data/table/hooks/useTableSelection.js.map +1 -1
- package/cjs/data/table/hooks/useTableSort.d.ts +13 -7
- package/cjs/data/table/hooks/useTableSort.js +8 -9
- package/cjs/data/table/hooks/useTableSort.js.map +1 -1
- package/cjs/data/table/index.d.ts +1 -1
- package/cjs/data/table/index.js +3 -23
- package/cjs/data/table/index.js.map +1 -1
- package/cjs/data/table/root/{DataTable.types.d.ts → DataGridTable.types.d.ts} +16 -26
- package/cjs/data/table/root/DataGridTable.types.js +3 -0
- package/cjs/data/table/root/DataGridTable.types.js.map +1 -0
- package/cjs/data/table/root/DataGridTableRoot.d.ts +104 -0
- package/cjs/data/table/root/{DataTableRoot.js → DataGridTableRoot.js} +57 -37
- package/cjs/data/table/root/DataGridTableRoot.js.map +1 -0
- package/cjs/data/table/root/DataTableRoot.context.d.ts +6 -2
- package/cjs/data/table/root/DataTableRoot.context.js.map +1 -1
- package/cjs/data/table/tbody/DataTableTbody.js +3 -3
- package/cjs/data/table/tbody/DataTableTbody.js.map +1 -1
- package/cjs/data/table/tr/DataTableTr.d.ts +3 -3
- package/cjs/data/table/tr/DataTableTr.js +44 -20
- package/cjs/data/table/tr/DataTableTr.js.map +1 -1
- package/cjs/data/token-filter/TokenFilter.d.ts +0 -6
- package/cjs/data/token-filter/TokenFilter.js +1 -1
- package/cjs/data-grid/index.d.ts +2 -0
- package/cjs/data-grid/index.js +9 -0
- package/cjs/data-grid/index.js.map +1 -0
- package/cjs/data-grid/root/DataGrid.types.d.ts +35 -0
- package/cjs/{data/table/root/DataTable.types.js → data-grid/root/DataGrid.types.js} +1 -1
- package/cjs/data-grid/root/DataGrid.types.js.map +1 -0
- package/cjs/data-grid/root/DataGridRoot.context.d.ts +16 -0
- package/cjs/{data/data-grid → data-grid}/root/DataGridRoot.context.js +1 -1
- package/cjs/data-grid/root/DataGridRoot.context.js.map +1 -0
- package/cjs/data-grid/root/DataGridRoot.d.ts +89 -0
- package/cjs/{data/data-grid → data-grid}/root/DataGridRoot.js +33 -8
- package/cjs/data-grid/root/DataGridRoot.js.map +1 -0
- package/cjs/preview.d.ts +1 -0
- package/cjs/{data/data-grid/index.js → preview.js} +3 -3
- package/cjs/preview.js.map +1 -0
- package/cjs/table/ColumnHeader.js.map +1 -1
- package/esm/data/drag-and-drop/root/DragAndDropRoot.d.ts +1 -1
- package/esm/data/drag-and-drop/root/DragAndDropRoot.js +2 -2
- package/esm/data/drag-and-drop/root/DragAndDropRoot.js.map +1 -1
- package/esm/data/stories/Data.test-data.d.ts +2 -2
- package/esm/data/stories/Data.test-data.js +37 -42
- package/esm/data/stories/Data.test-data.js.map +1 -1
- package/esm/data/table/base-cell/DataTableBaseCell.d.ts +4 -4
- package/esm/data/table/base-cell/DataTableBaseCell.js +2 -2
- package/esm/data/table/base-cell/DataTableBaseCell.js.map +1 -1
- package/esm/data/table/column-header/DataTableColumnHeader.d.ts +3 -15
- package/esm/data/table/column-header/DataTableColumnHeader.js +8 -5
- package/esm/data/table/column-header/DataTableColumnHeader.js.map +1 -1
- package/esm/data/table/column-header/useTableColumnResize.d.ts +2 -2
- package/esm/data/table/column-header/useTableColumnResize.js +10 -10
- package/esm/data/table/column-header/useTableColumnResize.js.map +1 -1
- package/esm/data/table/helpers/collectTableRowEntries.d.ts +1 -1
- package/esm/data/table/helpers/selection/getMultipleSelectProps.d.ts +6 -5
- package/esm/data/table/helpers/selection/getMultipleSelectProps.js +6 -2
- package/esm/data/table/helpers/selection/getMultipleSelectProps.js.map +1 -1
- package/esm/data/table/helpers/selection/getSingleSelectProps.d.ts +3 -3
- package/esm/data/table/helpers/selection/getSingleSelectProps.js +1 -1
- package/esm/data/table/helpers/selection/getSingleSelectProps.js.map +1 -1
- package/esm/data/table/helpers/selection/selection.types.d.ts +19 -27
- package/esm/data/table/helpers/selection/selection.utils.d.ts +1 -1
- package/esm/data/table/hooks/useColumnOptions.d.ts +3 -3
- package/esm/data/table/hooks/useColumnOptions.js +2 -2
- package/esm/data/table/hooks/useColumnOptions.js.map +1 -1
- package/esm/data/table/hooks/useTableDetailsPanel.d.ts +8 -9
- package/esm/data/table/hooks/useTableDetailsPanel.js.map +1 -1
- package/esm/data/table/hooks/useTableItems.d.ts +10 -11
- package/esm/data/table/hooks/useTableItems.js +11 -3
- package/esm/data/table/hooks/useTableItems.js.map +1 -1
- package/esm/data/table/hooks/useTableSelection.d.ts +2 -1
- package/esm/data/table/hooks/useTableSelection.js +46 -29
- package/esm/data/table/hooks/useTableSelection.js.map +1 -1
- package/esm/data/table/hooks/useTableSort.d.ts +13 -7
- package/esm/data/table/hooks/useTableSort.js +9 -10
- package/esm/data/table/hooks/useTableSort.js.map +1 -1
- package/esm/data/table/index.d.ts +1 -1
- package/esm/data/table/index.js +1 -21
- package/esm/data/table/index.js.map +1 -1
- package/esm/data/table/root/{DataTable.types.d.ts → DataGridTable.types.d.ts} +16 -26
- package/esm/data/table/root/DataGridTable.types.js +2 -0
- package/esm/data/table/root/DataGridTable.types.js.map +1 -0
- package/esm/data/table/root/DataGridTableRoot.d.ts +104 -0
- package/esm/data/table/root/{DataTableRoot.js → DataGridTableRoot.js} +59 -38
- package/esm/data/table/root/DataGridTableRoot.js.map +1 -0
- package/esm/data/table/root/DataTableRoot.context.d.ts +6 -2
- package/esm/data/table/root/DataTableRoot.context.js.map +1 -1
- package/esm/data/table/tbody/DataTableTbody.js +3 -3
- package/esm/data/table/tbody/DataTableTbody.js.map +1 -1
- package/esm/data/table/tr/DataTableTr.d.ts +3 -3
- package/esm/data/table/tr/DataTableTr.js +44 -20
- package/esm/data/table/tr/DataTableTr.js.map +1 -1
- package/esm/data/token-filter/TokenFilter.d.ts +0 -6
- package/esm/data/token-filter/TokenFilter.js +1 -1
- package/esm/data-grid/index.d.ts +2 -0
- package/esm/data-grid/index.js +4 -0
- package/esm/data-grid/index.js.map +1 -0
- package/esm/data-grid/root/DataGrid.types.d.ts +35 -0
- package/esm/data-grid/root/DataGrid.types.js +2 -0
- package/esm/data-grid/root/DataGrid.types.js.map +1 -0
- package/esm/data-grid/root/DataGridRoot.context.d.ts +16 -0
- package/esm/{data/data-grid → data-grid}/root/DataGridRoot.context.js +1 -1
- package/esm/data-grid/root/DataGridRoot.context.js.map +1 -0
- package/esm/data-grid/root/DataGridRoot.d.ts +89 -0
- package/esm/data-grid/root/DataGridRoot.js +57 -0
- package/esm/data-grid/root/DataGridRoot.js.map +1 -0
- package/esm/preview.d.ts +1 -0
- package/esm/preview.js +3 -0
- package/esm/preview.js.map +1 -0
- package/esm/table/ColumnHeader.js.map +1 -1
- package/package.json +23 -3
- package/src/data/drag-and-drop/root/DragAndDropRoot.tsx +3 -3
- package/src/data/stories/Data.test-data.tsx +53 -51
- package/src/data/table/base-cell/DataTableBaseCell.tsx +6 -6
- package/src/data/table/column-header/DataTableColumnHeader.tsx +17 -20
- package/src/data/table/column-header/useTableColumnResize.ts +14 -14
- package/src/data/table/helpers/collectTableRowEntries.ts +1 -1
- package/src/data/table/helpers/selection/getMultipleSelectProps.ts +11 -5
- package/src/data/table/helpers/selection/getSingleSelectProps.ts +4 -4
- package/src/data/table/helpers/selection/selection.types.ts +19 -29
- package/src/data/table/helpers/selection/selection.utils.test.ts +1 -1
- package/src/data/table/helpers/selection/selection.utils.ts +1 -1
- package/src/data/table/hooks/__tests__/useTableItems.test.ts +1 -1
- package/src/data/table/hooks/useColumnOptions.ts +5 -5
- package/src/data/table/hooks/useTableDetailsPanel.tsx +14 -18
- package/src/data/table/hooks/useTableItems.ts +37 -23
- package/src/data/table/hooks/useTableSelection.ts +62 -45
- package/src/data/table/hooks/useTableSort.ts +29 -17
- package/src/data/table/index.tsx +4 -21
- package/src/data/table/root/{DataTable.types.ts → DataGridTable.types.ts} +17 -30
- package/src/data/table/root/{DataTableRoot.tsx → DataGridTableRoot.tsx} +196 -143
- package/src/data/table/root/DataTableRoot.context.ts +10 -8
- package/src/data/table/sub-row-toggle/DataTableSubRowToggle.tsx +1 -1
- package/src/data/table/tbody/DataTableTbody.tsx +3 -3
- package/src/data/table/tr/DataTableTr.tsx +51 -16
- package/src/data/token-filter/TokenFilter.tsx +1 -1
- package/src/data-grid/index.ts +3 -0
- package/src/data-grid/root/DataGrid.types.ts +36 -0
- package/src/data-grid/root/DataGridRoot.context.ts +21 -0
- package/src/data-grid/root/DataGridRoot.tsx +152 -0
- package/src/preview.ts +2 -0
- package/src/table/ColumnHeader.tsx +1 -0
- package/cjs/data/data-grid/index.d.ts +0 -2
- package/cjs/data/data-grid/index.js.map +0 -1
- package/cjs/data/data-grid/root/DataGridRoot.context.d.ts +0 -11
- package/cjs/data/data-grid/root/DataGridRoot.context.js.map +0 -1
- package/cjs/data/data-grid/root/DataGridRoot.d.ts +0 -38
- package/cjs/data/data-grid/root/DataGridRoot.js.map +0 -1
- package/cjs/data/table/root/DataTable.types.js.map +0 -1
- package/cjs/data/table/root/DataTableRoot.d.ts +0 -118
- package/cjs/data/table/root/DataTableRoot.js.map +0 -1
- package/cjs/data/table/root/DataTableRoot.legacy.d.ts +0 -172
- package/cjs/data/table/root/DataTableRoot.legacy.js +0 -118
- package/cjs/data/table/root/DataTableRoot.legacy.js.map +0 -1
- package/esm/data/data-grid/index.d.ts +0 -2
- package/esm/data/data-grid/index.js +0 -3
- package/esm/data/data-grid/index.js.map +0 -1
- package/esm/data/data-grid/root/DataGridRoot.context.d.ts +0 -11
- package/esm/data/data-grid/root/DataGridRoot.context.js.map +0 -1
- package/esm/data/data-grid/root/DataGridRoot.d.ts +0 -38
- package/esm/data/data-grid/root/DataGridRoot.js +0 -32
- package/esm/data/data-grid/root/DataGridRoot.js.map +0 -1
- package/esm/data/table/root/DataTable.types.js +0 -2
- package/esm/data/table/root/DataTable.types.js.map +0 -1
- package/esm/data/table/root/DataTableRoot.d.ts +0 -118
- package/esm/data/table/root/DataTableRoot.js.map +0 -1
- package/esm/data/table/root/DataTableRoot.legacy.d.ts +0 -172
- package/esm/data/table/root/DataTableRoot.legacy.js +0 -73
- package/esm/data/table/root/DataTableRoot.legacy.js.map +0 -1
- package/src/data/data-grid/index.ts +0 -3
- package/src/data/data-grid/root/DataGridRoot.context.ts +0 -16
- package/src/data/data-grid/root/DataGridRoot.tsx +0 -71
- package/src/data/table/Readme.md +0 -11
- package/src/data/table/agent-component-review.md +0 -175
- package/src/data/table/root/DataTableRoot.legacy.tsx +0 -305
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { DataTableCaption, type DataTableCaptionProps } from "../caption/DataTableCaption.js";
|
|
3
|
-
import { DataTableEmptyState, type DataTableEmptyStateProps } from "../empty-state/DataTableEmptyState.js";
|
|
4
|
-
import { type SelectionProps } from "../hooks/useTableSelection.js";
|
|
5
|
-
import { DataTableLoadingState, type DataTableLoadingStateProps } from "../loading-state/DataTableLoadingState.js";
|
|
6
|
-
import { DataTableTbody, type DataTableTbodyProps } from "../tbody/DataTableTbody.js";
|
|
7
|
-
import { DataTableTd, type DataTableTdProps } from "../td/DataTableTd.js";
|
|
8
|
-
import { DataTableTfoot, type DataTableTfootProps } from "../tfoot/DataTableTfoot.js";
|
|
9
|
-
import { DataTableTh, type DataTableThProps } from "../th/DataTableTh.js";
|
|
10
|
-
import { DataTableThead, type DataTableTheadProps } from "../thead/DataTableThead.js";
|
|
11
|
-
import { DataTableTr, type DataTableTrProps } from "../tr/DataTableTr.js";
|
|
12
|
-
interface DataTableProps extends React.HTMLAttributes<HTMLTableElement> {
|
|
13
|
-
children: React.ReactNode;
|
|
14
|
-
/**
|
|
15
|
-
* Controls vertical cell padding.
|
|
16
|
-
* @default "normal"
|
|
17
|
-
*/
|
|
18
|
-
rowDensity?: "condensed" | "normal" | "spacious";
|
|
19
|
-
/**
|
|
20
|
-
* Zebra striped table
|
|
21
|
-
* @default false
|
|
22
|
-
*/
|
|
23
|
-
zebraStripes?: boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Truncate content in cells and show ellipsis for overflowed text.
|
|
26
|
-
*
|
|
27
|
-
* **NB:** When using `layout="auto"`, you have to manually set a `maxWidth` on columns that should be truncated.
|
|
28
|
-
* @default true
|
|
29
|
-
*/
|
|
30
|
-
truncateContent?: boolean;
|
|
31
|
-
/**
|
|
32
|
-
* Enables keyboard navigation for table rows and cells.
|
|
33
|
-
* @default false
|
|
34
|
-
*/
|
|
35
|
-
withKeyboardNav?: boolean;
|
|
36
|
-
/**
|
|
37
|
-
* Controls table layout.
|
|
38
|
-
*
|
|
39
|
-
* ### fixed
|
|
40
|
-
* Gives you full control of column widths. This is required for resizable columns.
|
|
41
|
-
*
|
|
42
|
-
* ### auto
|
|
43
|
-
* Makes the columns resize automatically based on the content.
|
|
44
|
-
* The table will take up at least 100% of available width.
|
|
45
|
-
*
|
|
46
|
-
* **NB:** When using this with `truncateContent`, you have to manually
|
|
47
|
-
* set a `contentMaxWidth` on cells that should be truncated.
|
|
48
|
-
* @default "fixed"
|
|
49
|
-
*/
|
|
50
|
-
layout?: "fixed" | "auto";
|
|
51
|
-
selection?: SelectionProps;
|
|
52
|
-
}
|
|
53
|
-
interface DataTableRootComponent extends React.ForwardRefExoticComponent<DataTableProps & React.RefAttributes<HTMLTableElement>> {
|
|
54
|
-
/**
|
|
55
|
-
* @see 🏷️ {@link DataTableCaptionProps}
|
|
56
|
-
* @example
|
|
57
|
-
* ```jsx
|
|
58
|
-
* <DataTable>
|
|
59
|
-
* <DataTable.Caption>
|
|
60
|
-
* Lorem ipsum
|
|
61
|
-
* </DataTable.Caption
|
|
62
|
-
* </DataTable>
|
|
63
|
-
* ```
|
|
64
|
-
*/
|
|
65
|
-
Caption: typeof DataTableCaption;
|
|
66
|
-
/**
|
|
67
|
-
* @see 🏷️ {@link DataTableTheadProps}
|
|
68
|
-
* @example
|
|
69
|
-
* ```jsx
|
|
70
|
-
* <DataTable>
|
|
71
|
-
* <DataTable.Thead>
|
|
72
|
-
* ... TODO
|
|
73
|
-
* </DataTable.Thead>
|
|
74
|
-
* </DataTable>
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
Thead: typeof DataTableThead;
|
|
78
|
-
/**
|
|
79
|
-
* @see 🏷️ {@link DataTableTbodyProps}
|
|
80
|
-
* @example
|
|
81
|
-
* ```jsx
|
|
82
|
-
* <DataTable>
|
|
83
|
-
* <DataTable.Tbody>
|
|
84
|
-
* ... TODO
|
|
85
|
-
* </DataTable.Tbody>
|
|
86
|
-
* </DataTable>
|
|
87
|
-
* ```
|
|
88
|
-
*/
|
|
89
|
-
Tbody: typeof DataTableTbody;
|
|
90
|
-
/**
|
|
91
|
-
* @see 🏷️ {@link DataTableTrProps}
|
|
92
|
-
* @example
|
|
93
|
-
* ```jsx
|
|
94
|
-
* <DataTable>
|
|
95
|
-
* <DataTable.Tr>
|
|
96
|
-
* ... TODO
|
|
97
|
-
* </DataTable.Tr
|
|
98
|
-
* </DataTable>
|
|
99
|
-
* ```
|
|
100
|
-
*/
|
|
101
|
-
Tr: typeof DataTableTr;
|
|
102
|
-
/**
|
|
103
|
-
* @see 🏷️ {@link DataTableThProps}
|
|
104
|
-
* @example
|
|
105
|
-
* ```jsx
|
|
106
|
-
* ```
|
|
107
|
-
*/
|
|
108
|
-
Th: typeof DataTableTh;
|
|
109
|
-
/**
|
|
110
|
-
* @see 🏷️ {@link DataTableTdProps}
|
|
111
|
-
* @example
|
|
112
|
-
* ```jsx
|
|
113
|
-
* <DataTable>
|
|
114
|
-
* <DataTable.Tbody>
|
|
115
|
-
* <DataTable.Td>
|
|
116
|
-
* Lorem ipsum
|
|
117
|
-
* </DataTable.Td>
|
|
118
|
-
* <DataTable.Td>
|
|
119
|
-
* Dolor sit amet
|
|
120
|
-
* </DataTable.Td>
|
|
121
|
-
* </DataTable.Tbody>
|
|
122
|
-
* </DataTable>
|
|
123
|
-
* ```
|
|
124
|
-
*/
|
|
125
|
-
Td: typeof DataTableTd;
|
|
126
|
-
/**
|
|
127
|
-
* @see 🏷️ {@link DataTableTfootProps}
|
|
128
|
-
* @example
|
|
129
|
-
* ```jsx
|
|
130
|
-
* <DataTable>
|
|
131
|
-
* <DataTable.Tfoot>
|
|
132
|
-
* ...
|
|
133
|
-
* </DataTable.Tfoot>
|
|
134
|
-
* </DataTable>
|
|
135
|
-
* ```
|
|
136
|
-
*/
|
|
137
|
-
Tfoot: typeof DataTableTfoot;
|
|
138
|
-
/**
|
|
139
|
-
* @see 🏷️ {@link DataTableEmptyStateProps}
|
|
140
|
-
* @example
|
|
141
|
-
* ```jsx
|
|
142
|
-
* <DataTable>
|
|
143
|
-
* <DataTable.TBody>
|
|
144
|
-
* <DataTable.EmptyState />
|
|
145
|
-
* </DataTable.TBody>
|
|
146
|
-
* </DataTable>
|
|
147
|
-
* ```
|
|
148
|
-
*/
|
|
149
|
-
EmptyState: typeof DataTableEmptyState;
|
|
150
|
-
/**
|
|
151
|
-
* @see 🏷️ {@link DataTableEmptyStateProps}
|
|
152
|
-
* @example
|
|
153
|
-
* ```jsx
|
|
154
|
-
* <DataTable>
|
|
155
|
-
* <DataTable.TBody>
|
|
156
|
-
* <DataTable.LoadingState />
|
|
157
|
-
* </DataTable.TBody>
|
|
158
|
-
* </DataTable>
|
|
159
|
-
* ```
|
|
160
|
-
*/
|
|
161
|
-
LoadingState: typeof DataTableLoadingState;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* TODO Component description etc.
|
|
165
|
-
*
|
|
166
|
-
* **NB:** To get sticky headers, you have to set a height restriction on the table container. You can use VStack for this:
|
|
167
|
-
* TODO example
|
|
168
|
-
*/
|
|
169
|
-
declare const DataTable: DataTableRootComponent;
|
|
170
|
-
export { DataTable, DataTableCaption, DataTableEmptyState, DataTableLoadingState, DataTableTbody, DataTableTd, DataTableTfoot, DataTableTh, DataTableThead, DataTableTr, };
|
|
171
|
-
export default DataTable;
|
|
172
|
-
export type { DataTableCaptionProps, DataTableEmptyStateProps, DataTableLoadingStateProps, DataTableProps, DataTableTbodyProps, DataTableTdProps, DataTableTfootProps, DataTableTheadProps, DataTableThProps, DataTableTrProps, };
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
-
var t = {};
|
|
3
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
-
t[p] = s[p];
|
|
5
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
-
t[p[i]] = s[p[i]];
|
|
9
|
-
}
|
|
10
|
-
return t;
|
|
11
|
-
};
|
|
12
|
-
import React, { forwardRef } from "react";
|
|
13
|
-
import { useId } from "../../../utils-external/index.js";
|
|
14
|
-
import { cl } from "../../../utils/helpers/index.js";
|
|
15
|
-
import { useMergeRefs } from "../../../utils/hooks/index.js";
|
|
16
|
-
import { DataTableCaption, } from "../caption/DataTableCaption.js";
|
|
17
|
-
import { DataTableEmptyState, } from "../empty-state/DataTableEmptyState.js";
|
|
18
|
-
import { DataTableDetailsPanelProvider } from "../hooks/useTableDetailsPanel.js";
|
|
19
|
-
import { useTableKeyboardNav } from "../hooks/useTableKeyboardNav.js";
|
|
20
|
-
import { noSelectionState, } from "../hooks/useTableSelection.js";
|
|
21
|
-
import { DataTableLoadingState, } from "../loading-state/DataTableLoadingState.js";
|
|
22
|
-
import { DataTableTbody, } from "../tbody/DataTableTbody.js";
|
|
23
|
-
import { DataTableTd } from "../td/DataTableTd.js";
|
|
24
|
-
import { DataTableTfoot, } from "../tfoot/DataTableTfoot.js";
|
|
25
|
-
import { DataTableTh } from "../th/DataTableTh.js";
|
|
26
|
-
import { DataTableThead, } from "../thead/DataTableThead.js";
|
|
27
|
-
import { DataTableTr } from "../tr/DataTableTr.js";
|
|
28
|
-
import { DataTableContextProvider } from "./DataTableRoot.context.js";
|
|
29
|
-
/**
|
|
30
|
-
* TODO Component description etc.
|
|
31
|
-
*
|
|
32
|
-
* **NB:** To get sticky headers, you have to set a height restriction on the table container. You can use VStack for this:
|
|
33
|
-
* TODO example
|
|
34
|
-
*/
|
|
35
|
-
const DataTable = forwardRef((_a, forwardedRef) => {
|
|
36
|
-
var { className, rowDensity = "normal", withKeyboardNav = false, zebraStripes = false, truncateContent = true, layout = "fixed" } = _a, rest = __rest(_a, ["className", "rowDensity", "withKeyboardNav", "zebraStripes", "truncateContent", "layout"]);
|
|
37
|
-
const { tabIndex, setTableRef } = useTableKeyboardNav({
|
|
38
|
-
enabled: withKeyboardNav,
|
|
39
|
-
});
|
|
40
|
-
const mergedRef = useMergeRefs(forwardedRef, setTableRef);
|
|
41
|
-
return (React.createElement(DataTableContextProvider, { layout: layout, withKeyboardNav: withKeyboardNav, selectionState: noSelectionState, stickyStart: {
|
|
42
|
-
expansion: false,
|
|
43
|
-
selection: false,
|
|
44
|
-
selectionOffset: 0,
|
|
45
|
-
firstColumnOffset: 0,
|
|
46
|
-
}, stickyHeader: true, tableId: useId(), loading: undefined, onRowClick: undefined, columns: [], totalColSpan: 9999, tableItems: {
|
|
47
|
-
childRowIdsById: new Map(),
|
|
48
|
-
visibleRowIds: [],
|
|
49
|
-
itemDetails: new Map(),
|
|
50
|
-
items: [],
|
|
51
|
-
isSubRowExpanded: () => false,
|
|
52
|
-
onExpandedRowIdsChange: () => null,
|
|
53
|
-
}, sortingState: {
|
|
54
|
-
onSortClick: () => null,
|
|
55
|
-
sortState: [],
|
|
56
|
-
} },
|
|
57
|
-
React.createElement(DataTableDetailsPanelProvider, null,
|
|
58
|
-
React.createElement("div", { className: "aksel-data-table__border-wrapper" },
|
|
59
|
-
React.createElement("div", { className: "aksel-data-table__scroll-wrapper" },
|
|
60
|
-
React.createElement("table", Object.assign({}, rest, { ref: mergedRef, className: cl("aksel-data-table", className), "data-zebra-stripes": zebraStripes, "data-truncate-content": truncateContent, "data-density": rowDensity, "data-layout": layout, tabIndex: tabIndex })))))));
|
|
61
|
-
});
|
|
62
|
-
DataTable.Caption = DataTableCaption;
|
|
63
|
-
DataTable.Thead = DataTableThead;
|
|
64
|
-
DataTable.Tbody = DataTableTbody;
|
|
65
|
-
DataTable.Th = DataTableTh;
|
|
66
|
-
DataTable.Tr = DataTableTr;
|
|
67
|
-
DataTable.Td = DataTableTd;
|
|
68
|
-
DataTable.Tfoot = DataTableTfoot;
|
|
69
|
-
DataTable.EmptyState = DataTableEmptyState;
|
|
70
|
-
DataTable.LoadingState = DataTableLoadingState;
|
|
71
|
-
export { DataTable, DataTableCaption, DataTableEmptyState, DataTableLoadingState, DataTableTbody, DataTableTd, DataTableTfoot, DataTableTh, DataTableThead, DataTableTr, };
|
|
72
|
-
export default DataTable;
|
|
73
|
-
//# sourceMappingURL=DataTableRoot.legacy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DataTableRoot.legacy.js","sourceRoot":"","sources":["../../../../src/data/table/root/DataTableRoot.legacy.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { createStrictContext } from "../../../utils/helpers";
|
|
2
|
-
import type { ColumnDefinitions } from "../../table/root/DataTable.types";
|
|
3
|
-
|
|
4
|
-
type DataGridContextValue<RowDef = unknown> = {
|
|
5
|
-
data: RowDef[];
|
|
6
|
-
columnDefinitions: ColumnDefinitions<RowDef>;
|
|
7
|
-
getRowId?: (rowData: RowDef) => string;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const { Provider: DataGridContextProvider, useContext: useDataGridContext } =
|
|
11
|
-
createStrictContext<DataGridContextValue>({
|
|
12
|
-
name: "DataGridContext",
|
|
13
|
-
errorMessage: "DataGrid hooks must be used within a <DataGrid />",
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export { DataGridContextProvider, useDataGridContext };
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import React, { HTMLAttributes, forwardRef } from "react";
|
|
2
|
-
import { cl } from "../../../utils/helpers";
|
|
3
|
-
import type { ColumnDefinitions } from "../../table/root/DataTable.types";
|
|
4
|
-
import { DataGridContextProvider } from "./DataGridRoot.context";
|
|
5
|
-
|
|
6
|
-
type RowTId = string;
|
|
7
|
-
|
|
8
|
-
export interface DataGridProps<RowT> extends HTMLAttributes<HTMLDivElement> {
|
|
9
|
-
children: React.ReactNode;
|
|
10
|
-
/**
|
|
11
|
-
* Definitions of the columns to display in the data grid.
|
|
12
|
-
*
|
|
13
|
-
* Each column definition should have a unique `id` and a `cell`-renderer function that takes the row data as argument and returns a React node.
|
|
14
|
-
*/
|
|
15
|
-
columnDefinitions: ColumnDefinitions<RowT>;
|
|
16
|
-
/**
|
|
17
|
-
* The data to display.
|
|
18
|
-
*
|
|
19
|
-
* Each object in the array represents a row, and the properties of the object are used to render the cells based on the `columnDefinitions`.
|
|
20
|
-
*/
|
|
21
|
-
data: RowT[];
|
|
22
|
-
/**
|
|
23
|
-
* Function to get unique row id from row data.
|
|
24
|
-
*
|
|
25
|
-
* If not provided, the row index will be used as id. This can cause issues if your data changes dynamically, so it's recommended to provide a stable id if possible.
|
|
26
|
-
*/
|
|
27
|
-
getRowId?: (rowData: RowT) => RowTId;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
type DataGridRootComponent = <RowT>(
|
|
31
|
-
props: DataGridProps<RowT> & React.RefAttributes<HTMLDivElement>,
|
|
32
|
-
) => React.ReactElement | null;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @see [📝 Documentation](https://aksel.nav.no/komponenter/core/data-grid)
|
|
36
|
-
* @see 🏷️ {@link DataGridProps}
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```jsx
|
|
40
|
-
* <DataGrid columnDefinitions={columnDefs} data={rowData} getRowId={(row) => row.id}>
|
|
41
|
-
* <DataTable />
|
|
42
|
-
* </DataGrid>
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
export const DataGridRoot = forwardRef<HTMLDivElement, DataGridProps<unknown>>(
|
|
46
|
-
(
|
|
47
|
-
{
|
|
48
|
-
children,
|
|
49
|
-
className,
|
|
50
|
-
columnDefinitions,
|
|
51
|
-
data,
|
|
52
|
-
getRowId,
|
|
53
|
-
...rest
|
|
54
|
-
}: DataGridProps<unknown>,
|
|
55
|
-
ref,
|
|
56
|
-
) => {
|
|
57
|
-
return (
|
|
58
|
-
<div {...rest} ref={ref} className={cl("aksel-data-grid", className)}>
|
|
59
|
-
<DataGridContextProvider
|
|
60
|
-
columnDefinitions={columnDefinitions}
|
|
61
|
-
data={data}
|
|
62
|
-
getRowId={getRowId}
|
|
63
|
-
>
|
|
64
|
-
{children}
|
|
65
|
-
</DataGridContextProvider>
|
|
66
|
-
</div>
|
|
67
|
-
);
|
|
68
|
-
},
|
|
69
|
-
) as DataGridRootComponent;
|
|
70
|
-
|
|
71
|
-
export default DataGridRoot;
|
package/src/data/table/Readme.md
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
# DataTable Beta Readiness Review
|
|
2
|
-
|
|
3
|
-
## Summary
|
|
4
|
-
|
|
5
|
-
The DataTable is a well-architected component with thoughtful separation of concerns (hooks, helpers, sub-components). The keyboard navigation, selection cascading, and sort state management are solid. However, there are several a11y gaps, API inconsistencies, and edge cases that should be addressed before a public beta.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Findings
|
|
10
|
-
|
|
11
|
-
| # | Category | Finding | Severity | Recommendation |
|
|
12
|
-
| --- | --------------- | ------------------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
13
|
-
| 2 | A11y | No `aria-selected` on selected rows | 🔴 | Add `aria-selected="true"` on `<tr>` for selected rows (required by grid/table selection pattern per ARIA APG). |
|
|
14
|
-
| 3 | A11y | No `aria-label`/`aria-labelledby` on the table element | 🟡 | Expose a `label` or `aria-label` prop. Without it, screen readers announce the table generically. React Aria requires a label on every table. |
|
|
15
|
-
| 4 | A11y | Hardcoded Norwegian strings without i18n support | 🟡 | All aria-labels ("Vis under-rader", "Skjul detaljer", "Velg alle synlige rader", "Laster innhold", resize labels) are Norwegian-only. Expose a `labels`/`translations` prop or accept them via column definitions for i18n. |
|
|
16
|
-
| 5 | A11y | Sub-rows should use `role="treegrid"` | 🟡 | When `subRows` is provided, the table should use `role="treegrid"` with `aria-level`, `aria-setsize`, `aria-posinset` on rows. Already flagged as TODO in code. |
|
|
17
|
-
| 7 | API | `disableRowSelection` signature inconsistency with stories | 🔴 | Type declares `({ row, id }) => boolean` but stories pass `({ id }) => id === 2`. The prop name is confusing: "disable" + returns `true` to disable = double negative. Consider `isRowSelectable` (positive predicate) like React Aria's `disabledKeys` pattern. |
|
|
18
|
-
| 8 | API | `stickyColumns` type is overly restrictive | 🟡 | `first?: "1"` and `last?: "1"` prevent future extension to 2+ sticky columns. Use `number` instead. |
|
|
19
|
-
| 9 | API | `sort` and `onSortChange` mixed into `DataTableProps` via `TableSortOptions` | 🟡 | Spreading sort props at root level makes the API flat but could collide with native HTML attributes or future features. Consider grouping into a `sort={{ state, onChange, defaultState }}` pattern. However, this is a style preference — the flat API is also valid. |
|
|
20
|
-
| 10 | API | `children?: never` prevents slot-based composition | 🟢 | The data-driven API is good for beta, but consider a path to compositional usage (render props or slot API) for GA. MUI and TanStack offer both modes. |
|
|
21
|
-
| 11 | API | Missing `aria-rowcount`/`aria-colcount` for virtualized/paginated tables | 🟡 | When data is paginated (as in `SelectionPagination` story), ATs cannot know total row count. Expose `totalRowCount` prop that maps to `aria-rowcount`. |
|
|
22
|
-
| 12 | Code Quality | `selectableIdsSet` in `getMultipleSelectProps` iterates all rows including sub-rows | 🟡 | "Select all" selects ALL rows in `itemDetails` including hidden sub-rows. The `selectableIdsSet` should filter by `visibleRowIds` for the "select all" checkbox, while still cascading to children when selecting individual parent rows. Variable naming is misleading. |
|
|
23
|
-
| 13 | Code Quality | `useTableSelection` passes `tableItems` (full object) to `getMultipleSelectProps` | 🟡 | This couples selection logic to the full table items shape. Consider passing only what's needed (`visibleRowIds`, `childRowIdsById`, `itemDetails`). |
|
|
24
|
-
| 14 | Performance | `columns.map()` inside render creates new objects on each render | 🟢 | `useColumnOptions` is memoized — this is fine. The `columns.map()` inside `DataTableTBodyContent` render loop is acceptable for normal table sizes. |
|
|
25
|
-
| 15 | Performance | No virtualization support | 🟢 | For beta, this is acceptable. Document the performance ceiling (recommended max ~500-1000 rows without virtualization). For GA, consider integrating with `@tanstack/react-virtual`. |
|
|
26
|
-
| 16 | Potential Issue | `fullWidthColSpan` may be wrong when `subRows` adds the expansion column | 🔴 | `fullWidthColSpan` counts `columns.length + layout filler + selection + detailsPanel`. The `RowExpansionCell` renders a separate `<td>` for detailsPanel. If both `subRows` AND `detailsPanel` are used together, verify `fullWidthColSpan` is correct. Check with `NestedRowsWithMasterDetail` story. |
|
|
27
|
-
| 17 | Potential Issue | Selection row-click fires AND toggles selection simultaneously | 🟡 | When `onRowClick` and `selection` are both enabled and `disableRowSelectionOnClick` is false (default), clicking a row both selects it and fires `onRowClick`. The default should probably be `disableRowSelectionOnClick: true` when `onRowClick` is also provided. |
|
|
28
|
-
| 18 | Potential Issue | `getRowId` fallback uses index — breaks selection on reorder/filter | 🟡 | If users don't provide `getRowId` and data changes (filter, sort, paginate), selection state becomes stale because index-based IDs shift. Consider logging a dev warning when `selection` is used without `getRowId`. |
|
|
29
|
-
| 19 | API | `loading.loadingLabel` only applies to skeleton/overlay mode | 🟢 | When `loadingState` is a custom ReactNode, there's no mechanism to announce loading to ATs. The `aria-busy` on the table partially covers this but `aria-live` region would be more robust. |
|
|
30
|
-
| 20 | API | `detailsPanel.getHeight` returns `number \| "auto"` — inconsistent with CSS patterns | 🟢 | Consider accepting a CSS value string (`"200px"`, `"auto"`) or always `number` (pixels). The mixed type works but requires the consumer to handle units. |
|
|
31
|
-
| 21 | A11y | Details panel row `aria-controls` relationship from toggle to content | 🟢 | The expansion button has `aria-controls={expansionId}` and the panel `<td>` has the matching `id`. Correctly implemented. ✓ No issue. |
|
|
32
|
-
| 22 | Code Quality | `@ts-expect-error` for Slot ref in `TableElementWrapper` | 🟢 | Minor tech debt. Consider typing the Slot component to accept ref properly. |
|
|
33
|
-
| 23 | API | No `onRowDoubleClick` or `onCellClick` callbacks | 🟢 | Common in MUI DataGrid. Not needed for beta but worth considering for GA. |
|
|
34
|
-
| 24 | Potential Issue | Sort `onSortChange` may double-fire in controlled mode | 🟡 | In `useTableSort`, `setSort(next)` is called and then `onSortChange?.(next, detail)` separately. If `useControllableState` invokes `onChange` internally, `onSortChange` fires twice in controlled mode. Verify. |
|
|
35
|
-
| 25 | API | `selection` prop type accepts partial object with no `selectionMode` | 🟡 | `SelectionProps` has `selectionMode?: "none" \| "single" \| "multiple"` defaulting to `"none"`. Passing `selection={{}}` without `selectionMode` silently does nothing. Consider requiring `selectionMode` when `selection` is provided (discriminated union). |
|
|
36
|
-
| 26 | Potential Issue | Keyboard nav `focusInitialTableTarget` always focuses first cell (including header) | 🟢 | Initial focus can go to the first data cell. Currently goes to first `td`/`th` which may be the selection header cell. Minor UX concern. |
|
|
37
|
-
| 27 | A11y | Resize handle uses `role="slider"` without `aria-valuemin`/`aria-valuemax` | 🟡 | ARIA slider requires `aria-valuemin` and `aria-valuemax`. Currently only `aria-valuenow` is set. Screen readers may not announce the range correctly. |
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## Details
|
|
42
|
-
|
|
43
|
-
### Finding #2 — Missing `aria-selected`
|
|
44
|
-
|
|
45
|
-
```tsx
|
|
46
|
-
// In DataTableTr, add:
|
|
47
|
-
<tr
|
|
48
|
-
{...rest}
|
|
49
|
-
aria-selected={selected || undefined}
|
|
50
|
-
// ...existing props
|
|
51
|
-
>
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### Finding #7 — `disableRowSelection` API
|
|
55
|
-
|
|
56
|
-
Current signature:
|
|
57
|
-
|
|
58
|
-
```ts
|
|
59
|
-
disableRowSelection?: (({ row, id }: { row: T; id: string | number }) => boolean) | boolean;
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Stories use:
|
|
63
|
-
|
|
64
|
-
```tsx
|
|
65
|
-
disableRowSelection: ({ id }) => id === 2 || id === 1;
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Recommended rename for clarity (breaking but pre-beta):
|
|
69
|
-
|
|
70
|
-
```ts
|
|
71
|
-
isRowSelectionDisabled?: (row: T, id: string | number) => boolean;
|
|
72
|
-
// OR (React Aria style):
|
|
73
|
-
disabledKeys?: (string | number)[];
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Finding #24 — Possible double-fire of `onSortChange`
|
|
77
|
-
|
|
78
|
-
In `useTableSort`:
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
const handleSortClick = useCallback((id, event) => {
|
|
82
|
-
// ...
|
|
83
|
-
setSort(next); // If controlled, useControllableState calls onChange
|
|
84
|
-
onSortChange?.(next, detail); // Also called explicitly
|
|
85
|
-
}, [...]);
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
If `useControllableState` invokes `onChange` when the `value` prop changes, `onSortChange` is called twice. Verify by checking if `useControllableState` has its own `onChange` invocation path. If it does, remove the explicit `onSortChange` call and pass it as `onChange` to `useControllableState`.
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## API & Developer Experience Analysis
|
|
93
|
-
|
|
94
|
-
### Overall API shape
|
|
95
|
-
|
|
96
|
-
The top-level API uses a **data-driven pattern** — you pass `data` + `columnDefinitions` and the component renders everything. This is the right choice for a "batteries included" table. The prop surface splits into:
|
|
97
|
-
|
|
98
|
-
- **Core:** `data`, `columnDefinitions`, `getRowId`
|
|
99
|
-
- **Features (objects):** `selection`, `loading`, `detailsPanel`, `subRows`, `stickyColumns`
|
|
100
|
-
- **Features (flat):** `sort`, `defaultSort`, `onSortChange`, `onRowClick`, `withKeyboardNav`
|
|
101
|
-
- **Appearance:** `rowDensity`, `zebraStripes`, `truncateContent`, `textSize`, `layout`
|
|
102
|
-
|
|
103
|
-
This is generally good — feature-objects group related props, and appearance props are flat. However there are some inconsistencies.
|
|
104
|
-
|
|
105
|
-
### Findings: API & DX
|
|
106
|
-
|
|
107
|
-
| # | Category | Finding | Severity | Recommendation |
|
|
108
|
-
| --- | -------- | -------------------------------------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
109
|
-
| 28 | DX | `header` vs `label` in ColumnDefinition is confusing | 🟡 | Both exist on every column. `label` is required and used for a11y/sort button labels. `header` is optional and overrides what's rendered. Developers will ask "which one is my header text?" Consider: `header` (required, replaces current `label`) + `headerContent` or just always use `header` for rendering and `aria-label` when the header is non-textual. |
|
|
110
|
-
| 29 | DX | `selection` vs sort props use different grouping patterns | 🟡 | Selection is grouped: `selection={{ selectionMode, onSelectionChange, ... }}`. Sort is flat: `sort`, `defaultSort`, `onSortChange`. This inconsistency will confuse devs. Either group sort (`sort={{ state, defaultState, onChange }}`) or flatten selection. Since sort also uses `detail` parameter, the flat pattern is defensible, but be consistent — pick one and apply it everywhere. |
|
|
111
|
-
| 30 | DX | `ColumnDefinition` mixes rendering, behavior, and sizing concerns | 🟢 | A single column def contains `cell`, `header`, `label`, `sortable`, `align`, `resizable`, `width`, `defaultWidth`, `autoWidth`, `minWidth`, `maxWidth`, `onWidthChange`, `isRowHeader`, `details`. That's 14+ properties. For beta this is fine (flat = discoverable), but for GA consider splitting into `column.sizing` or using separate configuration layers for power users. |
|
|
112
|
-
| 31 | DX | `detailsPanel` and `subRows` both have `expandedRowIds`/`defaultExpandedRowIds`/`onExpandedRowIdsChange` | 🟡 | Same prop names exist in both objects. When both features are used together (`NestedRowsWithMasterDetail`), developers must understand these are independent expansion states. The naming collision makes this unclear. Consider `detailsPanel.expandedRowIds` staying as-is but subRows using `expandedSubRowIds` or documenting clearly that they're independent. |
|
|
113
|
-
| 32 | DX | Resize props pollute column definition for non-resizable tables | 🟢 | When `layout="auto"`, resize props (`resizable`, `width`, `defaultWidth`, `autoWidth`, `minWidth`, `maxWidth`, `onWidthChange`) are all ignored. Developers may set them without realizing they have no effect. The JSDoc on `resizable` mentions this, but it's easy to miss. |
|
|
114
|
-
| 33 | DX | `getRowId` return type `string \| number` makes controlled selection awkward | 🟡 | `selectedKeys` is `(string \| number)[]`. If `getRowId` returns a number (like `row.id`), the consumer can pass `selectedKeys: [1, 2]` fine. But if they later compare with `===`, `string` vs `number` mismatches bite. TanStack Table uses `string` only for row IDs. Consider normalizing to `string` internally (with automatic `String()` coercion) or staying `number` only — pick one. |
|
|
115
|
-
| 34 | DX | No way to hide/show columns dynamically | 🟡 | Consumers must filter `columnDefinitions` array externally to toggle column visibility. This is fine API-wise (keep it data-driven), but should be documented as the expected pattern. The `Data.settings.stories.tsx` likely shows this but it's not obvious from the types alone. |
|
|
116
|
-
| 35 | DX | `loading` object has confusing interaction between its props | 🟡 | Three modes: (1) `isLoading + loadingState` → custom content, (2) `isLoading + loadingRows` → skeletons, (3) `isLoading` alone → overlay on existing data. These modes are implicit from which subset of props you pass. A discriminated union would make intent explicit, but adds verbosity. At minimum, JSDoc should clearly document "if you pass X, Y is ignored." |
|
|
117
|
-
| 36 | DX | `withKeyboardNav` defaults to `true` — unexpected for simple tables | 🟢 | Most table components default keyboard nav to off. When devs use DataTable for a simple read-only table, the `tabIndex=0` and arrow-key behavior is unexpected. Consider defaulting to `false` or auto-enabling only when interactive features (selection, sorting) are present. |
|
|
118
|
-
| 37 | DX | `onRowClick` doesn't convey which row data was clicked | 🟡 | Signature is `(rowId, event) => void`. Consumers must look up `rowId` in their own data array to get the row object. Consider `(rowData: T, rowId, event) => void` — this is what MUI and TanStack expose. Avoids forcing an O(n) lookup. |
|
|
119
|
-
| 38 | DX | `isRowHeader` on ColumnDefinition has no enforcement or guidance | 🟢 | JSDoc says "each row should have one rowheader" but nothing prevents 0 or many. This is a documentation issue, not a code issue. Consider a dev-mode warning if no column has `isRowHeader: true`. |
|
|
120
|
-
|
|
121
|
-
### What's working well (keep as-is)
|
|
122
|
-
|
|
123
|
-
- **Controlled/uncontrolled pattern** is consistent across selection, sort, sub-rows expansion, and details panel expansion. All use `value`/`defaultValue`/`onChange` semantics.
|
|
124
|
-
- **`getRowId`** — good that it's optional with a sensible fallback, and the JSDoc warns about the tradeoff.
|
|
125
|
-
- **`columnDefinitions` as a typed array** — gives excellent autocomplete and catches typos at compile time.
|
|
126
|
-
- **`selection.selectionMode`** driving the UI (checkbox vs radio) automatically — reduces decision surface.
|
|
127
|
-
- **Sort cycling** (none → asc → desc → none) with shift-click for multi-sort is well thought out.
|
|
128
|
-
- **Feature-as-object pattern** (`loading`, `selection`, `detailsPanel`, `subRows`) — good discoverability, scales well for adding future options.
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
## Priority Summary
|
|
133
|
-
|
|
134
|
-
### 🔴 Beta Blockers (must fix)
|
|
135
|
-
|
|
136
|
-
1. **#2** — Add `aria-selected` on selected rows
|
|
137
|
-
2. **#7** — Resolve `disableRowSelection` API inconsistency (breaking change is OK pre-beta)
|
|
138
|
-
3. **#16** — Verify `fullWidthColSpan` correctness with combined subRows + detailsPanel
|
|
139
|
-
|
|
140
|
-
### 🟡 Should Fix Before Beta
|
|
141
|
-
|
|
142
|
-
5. **#3** — Require/encourage table label
|
|
143
|
-
6. **#4** — Externalize hardcoded Norwegian strings
|
|
144
|
-
7. **#5** — `role="treegrid"` for sub-rows
|
|
145
|
-
8. **#8** — `stickyColumns` type to `number`
|
|
146
|
-
9. **#11** — `aria-rowcount` for paginated tables
|
|
147
|
-
10. **#12** — Verify "select all" behavior with pagination
|
|
148
|
-
11. **#17** — Default `disableRowSelectionOnClick: true` when `onRowClick` is set
|
|
149
|
-
12. **#18** — Dev warning for selection without `getRowId`
|
|
150
|
-
13. **#24** — Verify sort `onSortChange` double-fire
|
|
151
|
-
14. **#25** — Make `selectionMode` required when `selection` is provided
|
|
152
|
-
15. **#27** — Add `aria-valuemin`/`aria-valuemax` to resize slider
|
|
153
|
-
16. **#28** — Clarify `header` vs `label` in ColumnDefinition
|
|
154
|
-
17. **#29** — Decide on consistent grouping pattern (flat vs object) for features
|
|
155
|
-
18. **#31** — Disambiguate `expandedRowIds` between subRows and detailsPanel
|
|
156
|
-
19. **#33** — Normalize row ID type (string-only or document clearly)
|
|
157
|
-
20. **#35** — Document loading prop interactions or use discriminated union
|
|
158
|
-
21. **#37** — Add `rowData` to `onRowClick` callback signature
|
|
159
|
-
|
|
160
|
-
### 🟢 Post-Beta / GA
|
|
161
|
-
|
|
162
|
-
22. **#9** — Consider grouping sort props
|
|
163
|
-
23. **#10** — Compositional/slot API
|
|
164
|
-
24. **#15** — Virtualization
|
|
165
|
-
25. **#19** — `aria-live` for loading announcements
|
|
166
|
-
26. **#20** — `getHeight` type cleanup
|
|
167
|
-
27. **#22** — Fix `@ts-expect-error` tech debt
|
|
168
|
-
28. **#23** — `onRowDoubleClick`/`onCellClick`
|
|
169
|
-
29. **#26** — Initial focus target
|
|
170
|
-
30. **#14** — Performance for large tables (acceptable for beta)
|
|
171
|
-
31. **#30** — Split ColumnDefinition into layers for power users
|
|
172
|
-
32. **#32** — Warn when resize props used with `layout="auto"`
|
|
173
|
-
33. **#34** — Document column visibility pattern
|
|
174
|
-
34. **#36** — Consider `withKeyboardNav` default
|
|
175
|
-
35. **#38** — Dev warning for missing `isRowHeader`
|