@navikt/ds-react 8.10.2 → 8.10.4

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.
Files changed (200) hide show
  1. package/cjs/action-menu/ActionMenu.js +1 -1
  2. package/cjs/action-menu/ActionMenu.js.map +1 -1
  3. package/cjs/data/stories/Data.test-data.d.ts +24 -0
  4. package/cjs/data/stories/Data.test-data.js +1616 -0
  5. package/cjs/data/stories/Data.test-data.js.map +1 -0
  6. package/cjs/data/table/column-header/DataTableColumnHeader.d.ts +4 -1
  7. package/cjs/data/table/column-header/DataTableColumnHeader.js +4 -2
  8. package/cjs/data/table/column-header/DataTableColumnHeader.js.map +1 -1
  9. package/cjs/data/table/column-header/useTableColumnResize.d.ts +39 -14
  10. package/cjs/data/table/column-header/useTableColumnResize.js +37 -39
  11. package/cjs/data/table/column-header/useTableColumnResize.js.map +1 -1
  12. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.d.ts +6 -0
  13. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.js +32 -0
  14. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.js.map +1 -0
  15. package/cjs/data/table/helpers/collectTableRowEntries.d.ts +13 -5
  16. package/cjs/data/table/helpers/collectTableRowEntries.js +26 -19
  17. package/cjs/data/table/helpers/collectTableRowEntries.js.map +1 -1
  18. package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.d.ts +46 -0
  19. package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.js +112 -0
  20. package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.js.map +1 -0
  21. package/cjs/data/table/helpers/selection/getMultipleSelectProps.d.ts +3 -2
  22. package/cjs/data/table/helpers/selection/getMultipleSelectProps.js +43 -19
  23. package/cjs/data/table/helpers/selection/getMultipleSelectProps.js.map +1 -1
  24. package/cjs/data/table/helpers/selection/selection.types.d.ts +1 -0
  25. package/cjs/data/table/helpers/table-keyboard.d.ts +1 -2
  26. package/cjs/data/table/helpers/table-keyboard.js +1 -2
  27. package/cjs/data/table/helpers/table-keyboard.js.map +1 -1
  28. package/cjs/data/table/hooks/useColumnOptions.js +18 -5
  29. package/cjs/data/table/hooks/useColumnOptions.js.map +1 -1
  30. package/cjs/data/table/hooks/useTableDetailsPanel.d.ts +62 -0
  31. package/cjs/data/table/hooks/{useTableExpansion.js → useTableDetailsPanel.js} +26 -19
  32. package/cjs/data/table/hooks/useTableDetailsPanel.js.map +1 -0
  33. package/cjs/data/table/hooks/useTableItems.d.ts +18 -17
  34. package/cjs/data/table/hooks/useTableItems.js +27 -15
  35. package/cjs/data/table/hooks/useTableItems.js.map +1 -1
  36. package/cjs/data/table/hooks/useTableSelection.d.ts +6 -3
  37. package/cjs/data/table/hooks/useTableSelection.js +10 -4
  38. package/cjs/data/table/hooks/useTableSelection.js.map +1 -1
  39. package/cjs/data/table/index.d.ts +1 -2
  40. package/cjs/data/table/index.js +22 -12
  41. package/cjs/data/table/index.js.map +1 -1
  42. package/cjs/data/table/root/DataTable.types.d.ts +12 -10
  43. package/cjs/data/table/root/DataTableRoot.context.d.ts +5 -1
  44. package/cjs/data/table/root/DataTableRoot.context.js.map +1 -1
  45. package/cjs/data/table/root/DataTableRoot.d.ts +79 -115
  46. package/cjs/data/table/root/DataTableRoot.js +167 -39
  47. package/cjs/data/table/root/DataTableRoot.js.map +1 -1
  48. package/cjs/data/table/root/DataTableRoot.legacy.d.ts +177 -0
  49. package/cjs/data/table/root/DataTableRoot.legacy.js +104 -0
  50. package/cjs/data/table/root/DataTableRoot.legacy.js.map +1 -0
  51. package/cjs/data/table/sub-row-toggle/DataTableSubRowToggle.d.ts +6 -0
  52. package/cjs/data/table/sub-row-toggle/DataTableSubRowToggle.js +21 -0
  53. package/cjs/data/table/sub-row-toggle/DataTableSubRowToggle.js.map +1 -0
  54. package/cjs/data/table/tr/DataTableTr.js +11 -11
  55. package/cjs/data/table/tr/DataTableTr.js.map +1 -1
  56. package/cjs/form/checkbox/Checkbox.js +1 -0
  57. package/cjs/form/checkbox/Checkbox.js.map +1 -1
  58. package/cjs/form/radio/Radio.js +7 -1
  59. package/cjs/form/radio/Radio.js.map +1 -1
  60. package/cjs/modal/types.d.ts +8 -4
  61. package/cjs/utils/components/dismissablelayer/DismissableLayer.js +1 -1
  62. package/cjs/utils/components/dismissablelayer/DismissableLayer.js.map +1 -1
  63. package/cjs/utils/components/floating/Floating.d.ts +16 -1
  64. package/cjs/utils/components/floating/Floating.js +50 -13
  65. package/cjs/utils/components/floating/Floating.js.map +1 -1
  66. package/cjs/utils/components/floating-menu/Menu.js +1 -1
  67. package/cjs/utils/components/floating-menu/Menu.js.map +1 -1
  68. package/cjs/utils/helpers/create-strict-context.js +1 -1
  69. package/cjs/utils/helpers/create-strict-context.js.map +1 -1
  70. package/cjs/utils/hooks/useControllableState.d.ts +5 -5
  71. package/cjs/utils/hooks/useControllableState.js.map +1 -1
  72. package/cjs/utils/hooks/useValueAsRef.js +1 -1
  73. package/cjs/utils/hooks/useValueAsRef.js.map +1 -1
  74. package/cjs/utils-external/hooks/useId.js +1 -1
  75. package/cjs/utils-external/hooks/useId.js.map +1 -1
  76. package/esm/action-menu/ActionMenu.js +1 -1
  77. package/esm/action-menu/ActionMenu.js.map +1 -1
  78. package/esm/data/stories/Data.test-data.d.ts +24 -0
  79. package/esm/data/stories/Data.test-data.js +1607 -0
  80. package/esm/data/stories/Data.test-data.js.map +1 -0
  81. package/esm/data/table/column-header/DataTableColumnHeader.d.ts +4 -1
  82. package/esm/data/table/column-header/DataTableColumnHeader.js +4 -2
  83. package/esm/data/table/column-header/DataTableColumnHeader.js.map +1 -1
  84. package/esm/data/table/column-header/useTableColumnResize.d.ts +39 -14
  85. package/esm/data/table/column-header/useTableColumnResize.js +38 -40
  86. package/esm/data/table/column-header/useTableColumnResize.js.map +1 -1
  87. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.d.ts +6 -0
  88. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.js +27 -0
  89. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.js.map +1 -0
  90. package/esm/data/table/helpers/collectTableRowEntries.d.ts +13 -5
  91. package/esm/data/table/helpers/collectTableRowEntries.js +26 -19
  92. package/esm/data/table/helpers/collectTableRowEntries.js.map +1 -1
  93. package/esm/data/table/helpers/selection/SelectionSubtreeHelper.d.ts +46 -0
  94. package/esm/data/table/helpers/selection/SelectionSubtreeHelper.js +109 -0
  95. package/esm/data/table/helpers/selection/SelectionSubtreeHelper.js.map +1 -0
  96. package/esm/data/table/helpers/selection/getMultipleSelectProps.d.ts +3 -2
  97. package/esm/data/table/helpers/selection/getMultipleSelectProps.js +43 -19
  98. package/esm/data/table/helpers/selection/getMultipleSelectProps.js.map +1 -1
  99. package/esm/data/table/helpers/selection/selection.types.d.ts +1 -0
  100. package/esm/data/table/helpers/table-keyboard.d.ts +1 -2
  101. package/esm/data/table/helpers/table-keyboard.js +1 -2
  102. package/esm/data/table/helpers/table-keyboard.js.map +1 -1
  103. package/esm/data/table/hooks/useColumnOptions.js +18 -5
  104. package/esm/data/table/hooks/useColumnOptions.js.map +1 -1
  105. package/esm/data/table/hooks/useTableDetailsPanel.d.ts +62 -0
  106. package/esm/data/table/hooks/useTableDetailsPanel.js +58 -0
  107. package/esm/data/table/hooks/useTableDetailsPanel.js.map +1 -0
  108. package/esm/data/table/hooks/useTableItems.d.ts +18 -17
  109. package/esm/data/table/hooks/useTableItems.js +27 -15
  110. package/esm/data/table/hooks/useTableItems.js.map +1 -1
  111. package/esm/data/table/hooks/useTableSelection.d.ts +6 -3
  112. package/esm/data/table/hooks/useTableSelection.js +10 -4
  113. package/esm/data/table/hooks/useTableSelection.js.map +1 -1
  114. package/esm/data/table/index.d.ts +1 -2
  115. package/esm/data/table/index.js +21 -1
  116. package/esm/data/table/index.js.map +1 -1
  117. package/esm/data/table/root/DataTable.types.d.ts +12 -10
  118. package/esm/data/table/root/DataTableRoot.context.d.ts +5 -1
  119. package/esm/data/table/root/DataTableRoot.context.js.map +1 -1
  120. package/esm/data/table/root/DataTableRoot.d.ts +79 -115
  121. package/esm/data/table/root/DataTableRoot.js +174 -37
  122. package/esm/data/table/root/DataTableRoot.js.map +1 -1
  123. package/esm/data/table/root/DataTableRoot.legacy.d.ts +177 -0
  124. package/esm/data/table/root/DataTableRoot.legacy.js +59 -0
  125. package/esm/data/table/root/DataTableRoot.legacy.js.map +1 -0
  126. package/esm/data/table/sub-row-toggle/DataTableSubRowToggle.d.ts +6 -0
  127. package/esm/data/table/sub-row-toggle/DataTableSubRowToggle.js +16 -0
  128. package/esm/data/table/sub-row-toggle/DataTableSubRowToggle.js.map +1 -0
  129. package/esm/data/table/tr/DataTableTr.js +11 -11
  130. package/esm/data/table/tr/DataTableTr.js.map +1 -1
  131. package/esm/form/checkbox/Checkbox.js +1 -0
  132. package/esm/form/checkbox/Checkbox.js.map +1 -1
  133. package/esm/form/radio/Radio.js +7 -1
  134. package/esm/form/radio/Radio.js.map +1 -1
  135. package/esm/modal/types.d.ts +8 -4
  136. package/esm/utils/components/dismissablelayer/DismissableLayer.js +1 -1
  137. package/esm/utils/components/dismissablelayer/DismissableLayer.js.map +1 -1
  138. package/esm/utils/components/floating/Floating.d.ts +16 -1
  139. package/esm/utils/components/floating/Floating.js +48 -13
  140. package/esm/utils/components/floating/Floating.js.map +1 -1
  141. package/esm/utils/components/floating-menu/Menu.js +2 -2
  142. package/esm/utils/components/floating-menu/Menu.js.map +1 -1
  143. package/esm/utils/helpers/create-strict-context.js +1 -1
  144. package/esm/utils/helpers/create-strict-context.js.map +1 -1
  145. package/esm/utils/hooks/useControllableState.d.ts +5 -5
  146. package/esm/utils/hooks/useControllableState.js.map +1 -1
  147. package/esm/utils/hooks/useValueAsRef.js +1 -1
  148. package/esm/utils/hooks/useValueAsRef.js.map +1 -1
  149. package/esm/utils-external/hooks/useId.js +1 -1
  150. package/esm/utils-external/hooks/useId.js.map +1 -1
  151. package/package.json +3 -3
  152. package/src/action-menu/ActionMenu.tsx +1 -1
  153. package/src/data/stories/Data.test-data.tsx +1703 -0
  154. package/src/data/table/column-header/DataTableColumnHeader.tsx +11 -7
  155. package/src/data/table/column-header/useTableColumnResize.ts +95 -54
  156. package/src/data/table/details-panel-row/DataTableDetailsPanelRow.tsx +53 -0
  157. package/src/data/table/helpers/collectTableRowEntries.ts +55 -31
  158. package/src/data/table/helpers/selection/SelectionSubtreeHelper.test.ts +66 -0
  159. package/src/data/table/helpers/selection/SelectionSubtreeHelper.ts +162 -0
  160. package/src/data/table/helpers/selection/getMultipleSelectProps.ts +57 -20
  161. package/src/data/table/helpers/selection/selection.types.ts +1 -0
  162. package/src/data/table/helpers/table-keyboard.ts +1 -2
  163. package/src/data/table/hooks/__tests__/useTableItems.test.ts +27 -6
  164. package/src/data/table/hooks/__tests__/useTableSelection.test.ts +182 -58
  165. package/src/data/table/hooks/useColumnOptions.ts +19 -5
  166. package/src/data/table/hooks/useTableDetailsPanel.tsx +182 -0
  167. package/src/data/table/hooks/useTableItems.ts +74 -60
  168. package/src/data/table/hooks/useTableSelection.ts +27 -12
  169. package/src/data/table/index.tsx +5 -3
  170. package/src/data/table/root/DataTable.types.ts +25 -10
  171. package/src/data/table/root/DataTableRoot.context.ts +5 -1
  172. package/src/data/table/root/DataTableRoot.legacy.tsx +297 -0
  173. package/src/data/table/root/DataTableRoot.tsx +483 -219
  174. package/src/data/table/sub-row-toggle/DataTableSubRowToggle.tsx +39 -0
  175. package/src/data/table/tr/DataTableTr.tsx +14 -13
  176. package/src/form/checkbox/Checkbox.tsx +1 -0
  177. package/src/form/radio/Radio.tsx +7 -1
  178. package/src/modal/types.ts +8 -4
  179. package/src/utils/components/dismissablelayer/DismissableLayer.tsx +1 -1
  180. package/src/utils/components/floating/Floating.tsx +56 -13
  181. package/src/utils/components/floating-menu/Menu.tsx +4 -1
  182. package/src/utils/helpers/create-strict-context.tsx +1 -1
  183. package/src/utils/hooks/useControllableState.ts +11 -8
  184. package/src/utils/hooks/useValueAsRef.ts +1 -1
  185. package/src/utils-external/hooks/useId.ts +1 -1
  186. package/cjs/data/table/hooks/useTableExpansion.d.ts +0 -29
  187. package/cjs/data/table/hooks/useTableExpansion.js.map +0 -1
  188. package/cjs/data/table/root/DataTableAuto.d.ts +0 -174
  189. package/cjs/data/table/root/DataTableAuto.js +0 -206
  190. package/cjs/data/table/root/DataTableAuto.js.map +0 -1
  191. package/esm/data/table/hooks/useTableExpansion.d.ts +0 -29
  192. package/esm/data/table/hooks/useTableExpansion.js +0 -51
  193. package/esm/data/table/hooks/useTableExpansion.js.map +0 -1
  194. package/esm/data/table/root/DataTableAuto.d.ts +0 -174
  195. package/esm/data/table/root/DataTableAuto.js +0 -170
  196. package/esm/data/table/root/DataTableAuto.js.map +0 -1
  197. package/src/data/table/hooks/__tests__/useTableExpansion.test.tsx +0 -115
  198. package/src/data/table/hooks/useTableExpansion.tsx +0 -141
  199. package/src/data/table/root/DataTableAuto.test.tsx +0 -118
  200. package/src/data/table/root/DataTableAuto.tsx +0 -603
@@ -1,603 +0,0 @@
1
- /** biome-ignore-all lint/correctness/useHookAtTopLevel: False positive because of the way forwardRef() is added */
2
- import React, { forwardRef, useMemo } from "react";
3
- import { ChevronDownIcon, ChevronRightIcon } from "@navikt/aksel-icons";
4
- import { Button } from "../../../button";
5
- import { Skeleton } from "../../../skeleton";
6
- import { useId } from "../../../utils-external";
7
- import { cl } from "../../../utils/helpers";
8
- import { useMergeRefs } from "../../../utils/hooks";
9
- import { DataTableBaseCell } from "../base-cell/DataTableBaseCell";
10
- import { DataTableColumnHeader } from "../column-header/DataTableColumnHeader";
11
- import { DataTableEmptyState } from "../empty-state/DataTableEmptyState";
12
- import { useColumnOptions } from "../hooks/useColumnOptions";
13
- import {
14
- DataTableExpansionProvider,
15
- getDataTableExpansionId,
16
- useDataTableExpansion,
17
- } from "../hooks/useTableExpansion";
18
- import {
19
- type ItemDetail,
20
- TableItemsProvider,
21
- useTableItems,
22
- useTableItemsContext,
23
- } from "../hooks/useTableItems";
24
- import { useTableKeyboardNav } from "../hooks/useTableKeyboardNav";
25
- import {
26
- type SelectionProps,
27
- useTableSelection,
28
- } from "../hooks/useTableSelection";
29
- import { type TableSortOptions, useTableSort } from "../hooks/useTableSort";
30
- import { DataTableLoadingState } from "../loading-state/DataTableLoadingState";
31
- import { DataTableTbody } from "../tbody/DataTableTbody";
32
- import { DataTableThead } from "../thead/DataTableThead";
33
- import { DataTableTr } from "../tr/DataTableTr";
34
- import type { ColumnDefinitions } from "./DataTable.types";
35
- import {
36
- DataTableContextProvider,
37
- useDataTableContext,
38
- } from "./DataTableRoot.context";
39
-
40
- interface DataTableProps<T>
41
- extends
42
- React.HTMLAttributes<HTMLTableElement>,
43
- SelectionProps,
44
- TableSortOptions {
45
- children?: never;
46
- /**
47
- * Controls vertical cell padding.
48
- * @default "normal"
49
- */
50
- rowDensity?: "condensed" | "normal" | "spacious";
51
- /**
52
- * Zebra striped table
53
- * @default false
54
- */
55
- zebraStripes?: boolean;
56
- /**
57
- * Truncate content in cells and show ellipsis for overflowed text.
58
- *
59
- * **NB:** When using `layout="auto"`, you have to manually set a `maxWidth` on columns that should be truncated.
60
- * @default true
61
- */
62
- truncateContent?: boolean; // TODO: Consider making this default false when layout=auto, and maybe disallow it but add a wrap prop on the td-comp.
63
- /**
64
- * Enables keyboard navigation for table rows and cells.
65
- * @default false
66
- */
67
- withKeyboardNav?: boolean;
68
- /**
69
- * Custom callback to determine if navigation should be blocked.
70
- * Called before default blocking logic.
71
- * Requires `withKeyboardNav` to be `true`.
72
- */
73
- shouldBlockNavigation?: (event: KeyboardEvent) => boolean;
74
- /**
75
- * Controls table layout.
76
- *
77
- * ### fixed
78
- * Gives you full control of column widths. This is required for resizable columns.
79
- *
80
- * ### auto
81
- * Makes the columns resize automatically based on the content.
82
- * The table will take up at least 100% of available width.
83
- *
84
- * **NB:** When using this with `truncateContent`, you have to manually
85
- * set a `contentMaxWidth` on cells that should be truncated.
86
- * @default "fixed"
87
- */
88
- layout?: "fixed" | "auto";
89
- /**
90
- * Defines the columns of the table and how to render them.
91
- *
92
- *
93
- * Each column definition should have a unique `id` (or use the column index as fallback) and a `cell`-renderer function that takes the row data as argument and returns a React node.
94
- */
95
- columnDefinitions: ColumnDefinitions<T>;
96
- /**
97
- * The data to display in the table.
98
- *
99
- *
100
- * Each object in the array represents a row, and the properties of the object are used to render the cells based on the `columnDefinitions`.
101
- */
102
- data: T[];
103
- /**
104
- * Function to get unique row id from row data.
105
- *
106
- *
107
- * 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.
108
- */
109
- getRowId?: (rowData: T, index: number) => string | number;
110
- /**
111
- * Sticky columns that remain visible when horizontally scrolling the table.
112
- *
113
- * You can specify 1 sticky column on the left and 1 on the right.
114
- */
115
- stickyColumns?: {
116
- first?: "1";
117
- last?: "1";
118
- };
119
- /**
120
- * @default false
121
- */
122
- stickyHeader?: boolean;
123
- /**
124
- * Callback invoked when a data row is clicked.
125
- * Not called when clicking header, loading, or empty-state rows.
126
- */
127
- onRowClick?: (
128
- rowId: string | number,
129
- event: React.MouseEvent<HTMLTableRowElement>,
130
- ) => void;
131
- /**
132
- * Content to render when `data` is empty.
133
- * Rendered inside a `DataTable.EmptyState` row spanning all columns.
134
- */
135
- emptyState?: React.ReactNode;
136
- /**
137
- * Shows the table in a loading state.
138
- *
139
- * - When `loadingState` is provided, it is rendered inside a `DataTable.LoadingState` row.
140
- * - When `loadingState` is **not** provided, skeleton placeholder rows are rendered instead.
141
- * @default false
142
- */
143
- isLoading?: boolean;
144
- /**
145
- * Custom content to render when `isLoading` is `true`.
146
- * Rendered inside a `DataTable.LoadingState` row spanning all columns.
147
- * When omitted, skeleton rows are rendered based on `loadingRows`.
148
- */
149
- loadingState?: React.ReactNode;
150
- /**
151
- * Number of skeleton rows to render when `isLoading` is `true` and no `loadingState` is provided.
152
- *
153
- *
154
- * If not provided, the rendered content will get a temporarily overlay while loading
155
- */
156
- loadingRows?: number;
157
- /**
158
- * Visually hidden label announced to screen readers when skeleton rows are shown.
159
- * Only used when `isLoading` is `true` and no `loadingState` is provided.
160
- * @default "Laster innhold"
161
- */
162
- loadingLabel?: string;
163
- /**
164
- * Renders a details panel below the row when expanded.
165
- * When provided, an expand toggle column is added automatically.
166
- */
167
- getDetailsPanelContent?: (rowData: T) => React.ReactNode;
168
- /**
169
- * Determines whether a row can be expanded to show details panel content.
170
- * @default () => true
171
- */
172
- isDetailsPanelExpandable?: (rowData: T) => boolean;
173
- /**
174
- * Controlled list of expanded row IDs.
175
- * Use with `onDetailsPanelChange` for controlled usage, or `defaultDetailsPanelRowIds` for uncontrolled.
176
- */
177
- detailsPanelRowIds?: (string | number)[];
178
- /**
179
- * Initial list of expanded row IDs for uncontrolled usage.
180
- * @default []
181
- */
182
- defaultDetailsPanelRowIds?: (string | number)[];
183
- /**
184
- * Called when the list of expanded row IDs changes.
185
- *
186
- *
187
- * TODO:
188
- * - Docs: This pattern is called "Master / Detail" in general terms
189
- */
190
- onDetailsPanelChange?: (ids: (string | number)[]) => void;
191
- /**
192
- * Returns the height (in px) or `"auto"` for a row's details panel.
193
- * When a number is returned, the panel scrolls within that fixed height.
194
- * @default "auto"
195
- */
196
- getDetailsPanelHeight?: (rowData: T) => number | "auto";
197
- /**
198
- * Shows an expand-all toggle button in the expand column header.
199
- * @default false
200
- */
201
- showExpandAll?: boolean;
202
- /**
203
- * Function to get sub-rows for a given row, used for nested rows.
204
- * When provided, an expand toggle column is added automatically.
205
- */
206
- getSubRows?: (rowData: T) => T[];
207
- expandedSubRowIds?: (string | number)[];
208
- defaultExpandedSubRowIds?: (string | number)[];
209
- isSubRowExpandable?: (rowData: T) => boolean;
210
- onExpandedSubRowIdsChange?: (ids: (string | number)[]) => void;
211
- }
212
-
213
- function DataTableAutoInner<T>(
214
- {
215
- className,
216
- id,
217
- rowDensity = "normal",
218
- withKeyboardNav = false,
219
- zebraStripes = false,
220
- truncateContent = true,
221
- shouldBlockNavigation,
222
- layout = "fixed",
223
- selectionMode: selectionModeProp = "none",
224
- selectedKeys,
225
- defaultSelectedKeys,
226
- onSelectionChange,
227
- disabledSelectionKeys = [],
228
- data,
229
- columnDefinitions,
230
- getRowId,
231
- stickyColumns,
232
- stickyHeader = false,
233
- sort: sortProp,
234
- defaultSort = [],
235
- onSortChange,
236
- onRowClick,
237
- emptyState,
238
- isLoading = false,
239
- loadingState,
240
- loadingRows,
241
- loadingLabel = "Laster innhold",
242
- disableRowSelectionOnClick = false,
243
- getDetailsPanelContent,
244
- isDetailsPanelExpandable,
245
- getDetailsPanelHeight,
246
- showExpandAll = false,
247
- detailsPanelRowIds,
248
- defaultDetailsPanelRowIds,
249
- onDetailsPanelChange,
250
- getSubRows,
251
- expandedSubRowIds,
252
- defaultExpandedSubRowIds,
253
- isSubRowExpandable,
254
- onExpandedSubRowIdsChange,
255
- ...rest
256
- }: DataTableProps<T>,
257
- forwardedRef: React.ForwardedRef<HTMLTableElement>,
258
- ) {
259
- const { tabIndex, setTableRef } = useTableKeyboardNav({
260
- enabled: withKeyboardNav,
261
- shouldBlockNavigation,
262
- });
263
-
264
- const { sortState, onSortClick } = useTableSort({
265
- defaultSort,
266
- onSortChange,
267
- sort: sortProp,
268
- });
269
-
270
- const mergedRef = useMergeRefs(forwardedRef, setTableRef);
271
-
272
- const tableItems = useTableItems({
273
- items: data,
274
- getRowId,
275
- getSubRows,
276
- expandedSubRowIds,
277
- defaultExpandedSubRowIds,
278
- isSubRowExpandable,
279
- onExpandedSubRowIdsChange,
280
- });
281
-
282
- const allRowKeys = useMemo(() => {
283
- const rowKeys: (string | number)[] = [];
284
-
285
- for (const details of tableItems.itemDetails.values()) {
286
- rowKeys.push(details.id);
287
- }
288
-
289
- return rowKeys;
290
- }, [tableItems.itemDetails]);
291
-
292
- const tableSelectionState = useTableSelection({
293
- selectionMode: selectionModeProp,
294
- selectedKeys,
295
- defaultSelectedKeys,
296
- onSelectionChange,
297
- disabledSelectionKeys,
298
- allRowKeys,
299
- });
300
-
301
- const { columns, stickySelection } = useColumnOptions<T>(columnDefinitions, {
302
- stickyColumns,
303
- selectionMode: tableSelectionState.selection.selectionMode,
304
- });
305
-
306
- const fullWidthColSpan =
307
- columns.length +
308
- (layout === "fixed" ? 1 : 0) +
309
- (tableSelectionState.selection.selectionMode !== "none" ? 1 : 0) +
310
- (getDetailsPanelContent ? 1 : 0);
311
-
312
- const tableId = useId(id);
313
-
314
- return (
315
- <DataTableContextProvider
316
- layout={layout}
317
- withKeyboardNav={withKeyboardNav}
318
- selectionState={tableSelectionState}
319
- stickySelection={stickySelection}
320
- stickyHeader={stickyHeader}
321
- tableId={tableId}
322
- showLoadingSkeletons={isLoading && loadingState == null}
323
- onRowClick={onRowClick}
324
- disableRowSelectionOnClick={disableRowSelectionOnClick}
325
- isLoading={isLoading}
326
- showLoadingOverlay={isLoading && !loadingState && !loadingRows}
327
- columns={columns}
328
- >
329
- <DataTableExpansionProvider
330
- detailsPanelRowIds={detailsPanelRowIds}
331
- defaultDetailsPanelRowIds={defaultDetailsPanelRowIds}
332
- onDetailsPanelChange={onDetailsPanelChange}
333
- itemDetails={tableItems.itemDetails}
334
- getDetailsPanelContent={getDetailsPanelContent}
335
- isDetailsPanelExpandable={isDetailsPanelExpandable}
336
- getDetailsPanelHeight={getDetailsPanelHeight}
337
- showExpandAll={showExpandAll}
338
- >
339
- <div className="aksel-data-table__border-wrapper">
340
- <div className="aksel-data-table__scroll-wrapper">
341
- <table
342
- {...rest}
343
- ref={mergedRef}
344
- className={cl("aksel-data-table", className)}
345
- data-zebra-stripes={zebraStripes}
346
- data-truncate-content={truncateContent}
347
- data-density={rowDensity}
348
- data-layout={layout}
349
- data-loading={isLoading || undefined}
350
- tabIndex={tabIndex}
351
- aria-busy={isLoading || undefined}
352
- >
353
- <DataTableThead>
354
- <DataTableTr>
355
- {columns.map(({ isSticky, colDef }) => {
356
- const sortEntry = sortState.find(
357
- (s) => s.columnId === colDef.id,
358
- );
359
- const sortDirection = sortEntry?.direction ?? "none";
360
- return (
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}
384
- >
385
- <DataTableTbody>
386
- <DataTableAutoTBodyContent
387
- loadingState={loadingState}
388
- loadingRows={loadingRows}
389
- loadingLabel={loadingLabel}
390
- emptyState={emptyState}
391
- fullWidthColSpan={fullWidthColSpan}
392
- />
393
- </DataTableTbody>
394
- </TableItemsProvider>
395
- </table>
396
- </div>
397
- </div>
398
- </DataTableExpansionProvider>
399
- </DataTableContextProvider>
400
- );
401
- }
402
-
403
- interface DataTableAutoTBodyContentProps {
404
- loadingState: React.ReactNode;
405
- loadingLabel: string;
406
- loadingRows?: number;
407
- emptyState: React.ReactNode;
408
- fullWidthColSpan: number;
409
- }
410
-
411
- function DataTableAutoTBodyContent({
412
- loadingState,
413
- loadingRows,
414
- loadingLabel,
415
- emptyState,
416
- fullWidthColSpan,
417
- }: DataTableAutoTBodyContentProps) {
418
- const { items, itemDetails } = useTableItemsContext();
419
- const { columns, isLoading } = useDataTableContext();
420
-
421
- if (isLoading && loadingState != null) {
422
- return (
423
- <DataTableLoadingState colSpan={fullWidthColSpan}>
424
- {loadingState}
425
- </DataTableLoadingState>
426
- );
427
- }
428
-
429
- if (isLoading && loadingRows) {
430
- return (
431
- <>
432
- <tr>
433
- <td colSpan={fullWidthColSpan} className="aksel-sr-only">
434
- {loadingLabel}
435
- </td>
436
- </tr>
437
- {Array.from({ length: loadingRows }, (_, rowIndex) => (
438
- <DataTableTr key={`skeleton-row-${rowIndex}`} aria-hidden>
439
- {columns.map(({ isSticky, colDef }, colDefIndex) => (
440
- <DataTableBaseCell
441
- textAlign={colDef.type === "number" ? "right" : "left"}
442
- key={colDef.id || colDefIndex}
443
- as={colDef.isRowHeader ? "th" : "td"}
444
- isSticky={isSticky}
445
- >
446
- <Skeleton variant="text" />
447
- </DataTableBaseCell>
448
- ))}
449
- </DataTableTr>
450
- ))}
451
- </>
452
- );
453
- }
454
-
455
- if (items.length === 0 && emptyState !== undefined) {
456
- return (
457
- <DataTableEmptyState colSpan={fullWidthColSpan}>
458
- {emptyState}
459
- </DataTableEmptyState>
460
- );
461
- }
462
-
463
- const renderLoadingAnnouncement = isLoading && !loadingState && !loadingRows;
464
-
465
- return items.map((rowData) => {
466
- const details = itemDetails.get(rowData);
467
-
468
- /* Should in theory be impossible. Look about typing this? */
469
- if (!details) {
470
- return null;
471
- }
472
-
473
- const hasSubRows = details.children.length > 0;
474
-
475
- return (
476
- <React.Fragment key={details.id}>
477
- {renderLoadingAnnouncement && (
478
- <tr>
479
- <td colSpan={fullWidthColSpan} className="aksel-sr-only">
480
- {loadingLabel}
481
- </td>
482
- </tr>
483
- )}
484
- <DataTableTr rowId={details.id}>
485
- {columns.map(({ isSticky, colDef }, colDefIndex) => {
486
- const renderNestedToggle = colDefIndex === 0 && hasSubRows;
487
- const renderNestedIndent =
488
- colDefIndex === 0 && (details.level > 0 || hasSubRows);
489
-
490
- const style: React.CSSProperties = {
491
- "--__axc-data-table-nested-depth": details.level,
492
- };
493
-
494
- return (
495
- <DataTableBaseCell
496
- /* TODO: Make this configurable */
497
- textAlign={colDef.type === "number" ? "right" : "left"}
498
- key={colDef.id || colDefIndex}
499
- as={colDef.isRowHeader ? "th" : "td"}
500
- isSticky={isSticky}
501
- data-nested={renderNestedIndent || undefined}
502
- style={style}
503
- >
504
- {renderNestedToggle && <NestedRowToggle details={details} />}
505
- {colDef.cell(rowData)}
506
- </DataTableBaseCell>
507
- );
508
- })}
509
- </DataTableTr>
510
- <DataTableExpandedRow
511
- rowId={details.id}
512
- rowData={rowData}
513
- fullWidthColSpan={fullWidthColSpan}
514
- />
515
- </React.Fragment>
516
- );
517
- });
518
- }
519
-
520
- function NestedRowToggle({ details }: { details: ItemDetail<any> }) {
521
- const { isSubRowExpanded, onExpandedSubRowIdsChange } =
522
- useTableItemsContext();
523
-
524
- const subRows = details.children;
525
- const hasSubRows = subRows && subRows.length > 0;
526
- const isRowExpanded = isSubRowExpanded(details.id);
527
-
528
- return (
529
- <div className="aksel-data-table__nested-toggle">
530
- {hasSubRows && (
531
- <Button
532
- variant="tertiary"
533
- data-color="neutral"
534
- size="small"
535
- onClick={(e) => {
536
- e.stopPropagation();
537
- onExpandedSubRowIdsChange(details.id);
538
- }}
539
- aria-expanded={isRowExpanded}
540
- aria-label={isRowExpanded ? "Skjul under-rader" : "Vis under-rader"}
541
- icon={
542
- isRowExpanded ? (
543
- <ChevronDownIcon aria-hidden />
544
- ) : (
545
- <ChevronRightIcon aria-hidden />
546
- )
547
- }
548
- />
549
- )}
550
- </div>
551
- );
552
- }
553
-
554
- function DataTableExpandedRow<T>({
555
- rowId,
556
- rowData,
557
- fullWidthColSpan,
558
- }: {
559
- rowId: string | number;
560
- rowData: T;
561
- fullWidthColSpan: number;
562
- }) {
563
- const { tableId } = useDataTableContext();
564
- const {
565
- enableDetailsPanel,
566
- isExpanded,
567
- getDetailsPanelContent,
568
- getDetailsPanelHeight,
569
- } = useDataTableExpansion();
570
-
571
- if (!enableDetailsPanel) {
572
- return null;
573
- }
574
-
575
- if (!isExpanded(rowId)) {
576
- return null;
577
- }
578
-
579
- const content = getDetailsPanelContent?.(rowData);
580
- const expansionId = getDataTableExpansionId(tableId, rowId);
581
-
582
- if (!content) {
583
- return null;
584
- }
585
-
586
- return (
587
- <tr>
588
- <td id={expansionId} colSpan={fullWidthColSpan}>
589
- <div style={{ height: getDetailsPanelHeight?.(rowData) }}>
590
- {content}
591
- </div>
592
- </td>
593
- </tr>
594
- );
595
- }
596
-
597
- const DataTableAuto = forwardRef(DataTableAutoInner) as <T>(
598
- props: DataTableProps<T> & React.RefAttributes<HTMLTableElement>,
599
- ) => React.ReactElement | null;
600
-
601
- export { DataTableAuto };
602
- export type { DataTableProps };
603
- export default DataTableAuto;