@navikt/ds-react 8.10.5 → 8.10.6

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 (223) hide show
  1. package/cjs/data/data-grid/index.d.ts +2 -0
  2. package/cjs/data/data-grid/index.js +7 -0
  3. package/cjs/data/data-grid/index.js.map +1 -0
  4. package/cjs/data/data-grid/root/DataGridRoot.context.d.ts +11 -0
  5. package/cjs/data/data-grid/root/DataGridRoot.context.js +11 -0
  6. package/cjs/data/data-grid/root/DataGridRoot.context.js.map +1 -0
  7. package/cjs/data/data-grid/root/DataGridRoot.d.ts +38 -0
  8. package/cjs/data/data-grid/root/DataGridRoot.js +68 -0
  9. package/cjs/data/data-grid/root/DataGridRoot.js.map +1 -0
  10. package/cjs/data/drag-and-drop/drag-handler/DragAndDropDragHandler.js +0 -1
  11. package/cjs/data/drag-and-drop/drag-handler/DragAndDropDragHandler.js.map +1 -1
  12. package/cjs/data/drag-and-drop/root/DragAndDropRoot.d.ts +5 -5
  13. package/cjs/data/drag-and-drop/root/DragAndDropRoot.js +4 -27
  14. package/cjs/data/drag-and-drop/root/DragAndDropRoot.js.map +1 -1
  15. package/cjs/data/stories/Data.test-data.d.ts +2 -5
  16. package/cjs/data/stories/Data.test-data.js +30 -38
  17. package/cjs/data/stories/Data.test-data.js.map +1 -1
  18. package/cjs/data/table/base-cell/DataTableBaseCell.d.ts +15 -15
  19. package/cjs/data/table/base-cell/DataTableBaseCell.js +4 -8
  20. package/cjs/data/table/base-cell/DataTableBaseCell.js.map +1 -1
  21. package/cjs/data/table/column-header/DataTableColumnHeader.d.ts +24 -6
  22. package/cjs/data/table/column-header/DataTableColumnHeader.js +22 -27
  23. package/cjs/data/table/column-header/DataTableColumnHeader.js.map +1 -1
  24. package/cjs/data/table/column-header/useTableColumnResize.d.ts +19 -29
  25. package/cjs/data/table/column-header/useTableColumnResize.js +24 -22
  26. package/cjs/data/table/column-header/useTableColumnResize.js.map +1 -1
  27. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.d.ts +1 -1
  28. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.js +2 -2
  29. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.js.map +1 -1
  30. package/cjs/data/table/helpers/collectTableRowEntries.d.ts +2 -2
  31. package/cjs/data/table/helpers/selection/getMultipleSelectProps.d.ts +13 -11
  32. package/cjs/data/table/helpers/selection/getMultipleSelectProps.js +43 -53
  33. package/cjs/data/table/helpers/selection/getMultipleSelectProps.js.map +1 -1
  34. package/cjs/data/table/helpers/selection/getSingleSelectProps.d.ts +9 -8
  35. package/cjs/data/table/helpers/selection/getSingleSelectProps.js +23 -10
  36. package/cjs/data/table/helpers/selection/getSingleSelectProps.js.map +1 -1
  37. package/cjs/data/table/helpers/selection/selection.types.d.ts +19 -19
  38. package/cjs/data/table/helpers/selection/selection.utils.d.ts +21 -0
  39. package/cjs/data/table/helpers/selection/selection.utils.js +46 -0
  40. package/cjs/data/table/helpers/selection/selection.utils.js.map +1 -0
  41. package/cjs/data/table/hooks/useColumnOptions.d.ts +16 -5
  42. package/cjs/data/table/hooks/useColumnOptions.js +26 -8
  43. package/cjs/data/table/hooks/useColumnOptions.js.map +1 -1
  44. package/cjs/data/table/hooks/useTableDetailsPanel.d.ts +10 -13
  45. package/cjs/data/table/hooks/useTableDetailsPanel.js +6 -5
  46. package/cjs/data/table/hooks/useTableDetailsPanel.js.map +1 -1
  47. package/cjs/data/table/hooks/useTableItems.d.ts +29 -15
  48. package/cjs/data/table/hooks/useTableItems.js +2 -12
  49. package/cjs/data/table/hooks/useTableItems.js.map +1 -1
  50. package/cjs/data/table/hooks/useTableKeyboardNav.d.ts +1 -6
  51. package/cjs/data/table/hooks/useTableKeyboardNav.js +1 -4
  52. package/cjs/data/table/hooks/useTableKeyboardNav.js.map +1 -1
  53. package/cjs/data/table/hooks/useTableSelection.d.ts +6 -6
  54. package/cjs/data/table/hooks/useTableSelection.js +13 -13
  55. package/cjs/data/table/hooks/useTableSelection.js.map +1 -1
  56. package/cjs/data/table/hooks/useTableSort.d.ts +2 -2
  57. package/cjs/data/table/hooks/useTableSort.js +4 -5
  58. package/cjs/data/table/hooks/useTableSort.js.map +1 -1
  59. package/cjs/data/table/root/DataTable.types.d.ts +22 -10
  60. package/cjs/data/table/root/DataTableRoot.context.d.ts +13 -7
  61. package/cjs/data/table/root/DataTableRoot.context.js.map +1 -1
  62. package/cjs/data/table/root/DataTableRoot.d.ts +49 -72
  63. package/cjs/data/table/root/DataTableRoot.js +54 -66
  64. package/cjs/data/table/root/DataTableRoot.js.map +1 -1
  65. package/cjs/data/table/root/DataTableRoot.legacy.d.ts +2 -7
  66. package/cjs/data/table/root/DataTableRoot.legacy.js +17 -3
  67. package/cjs/data/table/root/DataTableRoot.legacy.js.map +1 -1
  68. package/cjs/data/table/sub-row-toggle/DataTableSubRowToggle.js +4 -4
  69. package/cjs/data/table/sub-row-toggle/DataTableSubRowToggle.js.map +1 -1
  70. package/cjs/data/table/tbody/DataTableTbody.js +4 -2
  71. package/cjs/data/table/tbody/DataTableTbody.js.map +1 -1
  72. package/cjs/data/table/tr/DataTableTr.d.ts +5 -3
  73. package/cjs/data/table/tr/DataTableTr.js +36 -23
  74. package/cjs/data/table/tr/DataTableTr.js.map +1 -1
  75. package/cjs/table/ColumnHeader.js +2 -1
  76. package/cjs/table/ColumnHeader.js.map +1 -1
  77. package/esm/data/data-grid/index.d.ts +2 -0
  78. package/esm/data/data-grid/index.js +3 -0
  79. package/esm/data/data-grid/index.js.map +1 -0
  80. package/esm/data/data-grid/root/DataGridRoot.context.d.ts +11 -0
  81. package/esm/data/data-grid/root/DataGridRoot.context.js +7 -0
  82. package/esm/data/data-grid/root/DataGridRoot.context.js.map +1 -0
  83. package/esm/data/data-grid/root/DataGridRoot.d.ts +38 -0
  84. package/esm/data/data-grid/root/DataGridRoot.js +32 -0
  85. package/esm/data/data-grid/root/DataGridRoot.js.map +1 -0
  86. package/esm/data/drag-and-drop/drag-handler/DragAndDropDragHandler.js +0 -1
  87. package/esm/data/drag-and-drop/drag-handler/DragAndDropDragHandler.js.map +1 -1
  88. package/esm/data/drag-and-drop/root/DragAndDropRoot.d.ts +5 -5
  89. package/esm/data/drag-and-drop/root/DragAndDropRoot.js +4 -27
  90. package/esm/data/drag-and-drop/root/DragAndDropRoot.js.map +1 -1
  91. package/esm/data/stories/Data.test-data.d.ts +2 -5
  92. package/esm/data/stories/Data.test-data.js +30 -38
  93. package/esm/data/stories/Data.test-data.js.map +1 -1
  94. package/esm/data/table/base-cell/DataTableBaseCell.d.ts +15 -15
  95. package/esm/data/table/base-cell/DataTableBaseCell.js +4 -8
  96. package/esm/data/table/base-cell/DataTableBaseCell.js.map +1 -1
  97. package/esm/data/table/column-header/DataTableColumnHeader.d.ts +24 -6
  98. package/esm/data/table/column-header/DataTableColumnHeader.js +23 -28
  99. package/esm/data/table/column-header/DataTableColumnHeader.js.map +1 -1
  100. package/esm/data/table/column-header/useTableColumnResize.d.ts +19 -29
  101. package/esm/data/table/column-header/useTableColumnResize.js +24 -22
  102. package/esm/data/table/column-header/useTableColumnResize.js.map +1 -1
  103. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.d.ts +1 -1
  104. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.js +2 -2
  105. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.js.map +1 -1
  106. package/esm/data/table/helpers/collectTableRowEntries.d.ts +2 -2
  107. package/esm/data/table/helpers/selection/getMultipleSelectProps.d.ts +13 -11
  108. package/esm/data/table/helpers/selection/getMultipleSelectProps.js +43 -53
  109. package/esm/data/table/helpers/selection/getMultipleSelectProps.js.map +1 -1
  110. package/esm/data/table/helpers/selection/getSingleSelectProps.d.ts +9 -8
  111. package/esm/data/table/helpers/selection/getSingleSelectProps.js +23 -10
  112. package/esm/data/table/helpers/selection/getSingleSelectProps.js.map +1 -1
  113. package/esm/data/table/helpers/selection/selection.types.d.ts +19 -19
  114. package/esm/data/table/helpers/selection/selection.utils.d.ts +21 -0
  115. package/esm/data/table/helpers/selection/selection.utils.js +43 -0
  116. package/esm/data/table/helpers/selection/selection.utils.js.map +1 -0
  117. package/esm/data/table/hooks/useColumnOptions.d.ts +16 -5
  118. package/esm/data/table/hooks/useColumnOptions.js +26 -8
  119. package/esm/data/table/hooks/useColumnOptions.js.map +1 -1
  120. package/esm/data/table/hooks/useTableDetailsPanel.d.ts +10 -13
  121. package/esm/data/table/hooks/useTableDetailsPanel.js +6 -5
  122. package/esm/data/table/hooks/useTableDetailsPanel.js.map +1 -1
  123. package/esm/data/table/hooks/useTableItems.d.ts +29 -15
  124. package/esm/data/table/hooks/useTableItems.js +3 -10
  125. package/esm/data/table/hooks/useTableItems.js.map +1 -1
  126. package/esm/data/table/hooks/useTableKeyboardNav.d.ts +1 -6
  127. package/esm/data/table/hooks/useTableKeyboardNav.js +1 -4
  128. package/esm/data/table/hooks/useTableKeyboardNav.js.map +1 -1
  129. package/esm/data/table/hooks/useTableSelection.d.ts +6 -6
  130. package/esm/data/table/hooks/useTableSelection.js +13 -13
  131. package/esm/data/table/hooks/useTableSelection.js.map +1 -1
  132. package/esm/data/table/hooks/useTableSort.d.ts +2 -2
  133. package/esm/data/table/hooks/useTableSort.js +4 -5
  134. package/esm/data/table/hooks/useTableSort.js.map +1 -1
  135. package/esm/data/table/root/DataTable.types.d.ts +22 -10
  136. package/esm/data/table/root/DataTableRoot.context.d.ts +13 -7
  137. package/esm/data/table/root/DataTableRoot.context.js.map +1 -1
  138. package/esm/data/table/root/DataTableRoot.d.ts +49 -72
  139. package/esm/data/table/root/DataTableRoot.js +56 -68
  140. package/esm/data/table/root/DataTableRoot.js.map +1 -1
  141. package/esm/data/table/root/DataTableRoot.legacy.d.ts +2 -7
  142. package/esm/data/table/root/DataTableRoot.legacy.js +17 -3
  143. package/esm/data/table/root/DataTableRoot.legacy.js.map +1 -1
  144. package/esm/data/table/sub-row-toggle/DataTableSubRowToggle.js +4 -4
  145. package/esm/data/table/sub-row-toggle/DataTableSubRowToggle.js.map +1 -1
  146. package/esm/data/table/tbody/DataTableTbody.js +4 -2
  147. package/esm/data/table/tbody/DataTableTbody.js.map +1 -1
  148. package/esm/data/table/tr/DataTableTr.d.ts +5 -3
  149. package/esm/data/table/tr/DataTableTr.js +35 -23
  150. package/esm/data/table/tr/DataTableTr.js.map +1 -1
  151. package/esm/table/ColumnHeader.js +2 -1
  152. package/esm/table/ColumnHeader.js.map +1 -1
  153. package/package.json +3 -3
  154. package/src/data/data-grid/index.ts +3 -0
  155. package/src/data/data-grid/root/DataGridRoot.context.ts +16 -0
  156. package/src/data/data-grid/root/DataGridRoot.tsx +71 -0
  157. package/src/data/drag-and-drop/drag-handler/DragAndDropDragHandler.tsx +0 -1
  158. package/src/data/drag-and-drop/root/DragAndDropRoot.tsx +15 -49
  159. package/src/data/stories/Data.test-data.tsx +52 -43
  160. package/src/data/table/agent-component-review.md +175 -0
  161. package/src/data/table/base-cell/DataTableBaseCell.tsx +31 -21
  162. package/src/data/table/column-header/DataTableColumnHeader.tsx +61 -58
  163. package/src/data/table/column-header/useTableColumnResize.ts +55 -71
  164. package/src/data/table/details-panel-row/DataTableDetailsPanelRow.tsx +3 -3
  165. package/src/data/table/helpers/collectTableRowEntries.ts +1 -2
  166. package/src/data/table/helpers/selection/getMultipleSelectProps.ts +65 -85
  167. package/src/data/table/helpers/selection/getSingleSelectProps.ts +35 -17
  168. package/src/data/table/helpers/selection/selection.types.ts +19 -19
  169. package/src/data/table/helpers/selection/selection.utils.test.ts +161 -0
  170. package/src/data/table/helpers/selection/selection.utils.ts +73 -0
  171. package/src/data/table/hooks/__tests__/useTableItems.test.ts +2 -1
  172. package/src/data/table/hooks/useColumnOptions.ts +48 -14
  173. package/src/data/table/hooks/useTableDetailsPanel.tsx +22 -25
  174. package/src/data/table/hooks/useTableItems.ts +32 -24
  175. package/src/data/table/hooks/useTableKeyboardNav.ts +1 -13
  176. package/src/data/table/hooks/useTableSelection.ts +26 -31
  177. package/src/data/table/hooks/useTableSort.ts +10 -9
  178. package/src/data/table/root/DataTable.types.ts +30 -22
  179. package/src/data/table/root/DataTableRoot.context.ts +19 -7
  180. package/src/data/table/root/DataTableRoot.legacy.tsx +22 -14
  181. package/src/data/table/root/DataTableRoot.tsx +244 -293
  182. package/src/data/table/sub-row-toggle/DataTableSubRowToggle.tsx +5 -4
  183. package/src/data/table/tbody/DataTableTbody.tsx +6 -2
  184. package/src/data/table/tr/DataTableTr.tsx +98 -35
  185. package/src/table/ColumnHeader.tsx +2 -1
  186. package/cjs/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.d.ts +0 -22
  187. package/cjs/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js +0 -35
  188. package/cjs/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js.map +0 -1
  189. package/cjs/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.d.ts +0 -27
  190. package/cjs/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.js +0 -86
  191. package/cjs/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.js.map +0 -1
  192. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.d.ts +0 -5
  193. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js +0 -6
  194. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js.map +0 -1
  195. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.d.ts +0 -24
  196. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.js +0 -108
  197. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.js.map +0 -1
  198. package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.d.ts +0 -46
  199. package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.js +0 -112
  200. package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.js.map +0 -1
  201. package/esm/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.d.ts +0 -22
  202. package/esm/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js +0 -29
  203. package/esm/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js.map +0 -1
  204. package/esm/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.d.ts +0 -27
  205. package/esm/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.js +0 -50
  206. package/esm/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.js.map +0 -1
  207. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.d.ts +0 -5
  208. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js +0 -3
  209. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js.map +0 -1
  210. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.d.ts +0 -24
  211. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.js +0 -68
  212. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.js.map +0 -1
  213. package/esm/data/table/helpers/selection/SelectionSubtreeHelper.d.ts +0 -46
  214. package/esm/data/table/helpers/selection/SelectionSubtreeHelper.js +0 -109
  215. package/esm/data/table/helpers/selection/SelectionSubtreeHelper.js.map +0 -1
  216. package/src/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.tsx +0 -104
  217. package/src/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.tsx +0 -74
  218. package/src/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.tsx +0 -11
  219. package/src/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.tsx +0 -94
  220. package/src/data/table/helpers/selection/SelectionSubtreeHelper.test.ts +0 -66
  221. package/src/data/table/helpers/selection/SelectionSubtreeHelper.ts +0 -162
  222. package/src/data/table/hooks/__tests__/useTableSelection.test.ts +0 -488
  223. package/src/data/table/root/agent-feature-gap.md +0 -96
@@ -1,9 +1,7 @@
1
- /** biome-ignore-all lint/correctness/useHookAtTopLevel: False positive because of the way forwardRef() is added */
2
1
  import React, {
3
2
  forwardRef,
4
3
  useCallback,
5
4
  useEffect,
6
- useMemo,
7
5
  useRef,
8
6
  useState,
9
7
  } from "react";
@@ -12,6 +10,7 @@ import { useId } from "../../../utils-external";
12
10
  import { Slot } from "../../../utils/components/slot/Slot";
13
11
  import { cl } from "../../../utils/helpers";
14
12
  import { useMergeRefs } from "../../../utils/hooks";
13
+ import { useDataGridContext } from "../../data-grid/root/DataGridRoot.context";
15
14
  import { DataTableBaseCell } from "../base-cell/DataTableBaseCell";
16
15
  import { DataTableColumnHeader } from "../column-header/DataTableColumnHeader";
17
16
  import { DataTableDetailsPanelRow } from "../details-panel-row/DataTableDetailsPanelRow";
@@ -21,12 +20,7 @@ import {
21
20
  DataTableDetailsPanelProvider,
22
21
  type DetailsPanelProps,
23
22
  } from "../hooks/useTableDetailsPanel";
24
- import {
25
- type SubRowsProps,
26
- TableItemsProvider,
27
- useTableItems,
28
- useTableItemsContext,
29
- } from "../hooks/useTableItems";
23
+ import { type SubRowsProps, useTableItems } from "../hooks/useTableItems";
30
24
  import { useTableKeyboardNav } from "../hooks/useTableKeyboardNav";
31
25
  import {
32
26
  type SelectionProps,
@@ -38,14 +32,29 @@ import { DataTableSubRowToggle } from "../sub-row-toggle/DataTableSubRowToggle";
38
32
  import { DataTableTbody } from "../tbody/DataTableTbody";
39
33
  import { DataTableThead } from "../thead/DataTableThead";
40
34
  import { DataTableTr } from "../tr/DataTableTr";
41
- import type { ColumnDefinitions } from "./DataTable.types";
35
+ import type {
36
+ DataTableLoadingConfig,
37
+ TableRowEntryId,
38
+ } from "./DataTable.types";
42
39
  import {
43
40
  DataTableContextProvider,
44
41
  useDataTableContext,
45
42
  } from "./DataTableRoot.context";
46
43
 
47
- interface DataTableProps<T>
48
- extends React.HTMLAttributes<HTMLTableElement>, TableSortOptions {
44
+ /**
45
+ * TODO: For consideration:
46
+ * - Use namespacing for types. There will be a lot of standalone types connected to this component,
47
+ * it could make sense to access them under DataTable.X instead of separate imports.
48
+ * - Consider having a "Wrapper" component that only handles context and logic like,
49
+ * "DataTableRoot" or "DataGrid" or something, and then have the main "DataTable" component only handle rendering of table itself.
50
+ * This would make props more focused and discoverable since its not mixed with htmltable-props.
51
+ */
52
+
53
+ /**
54
+ * TODO:
55
+ * - Test `onColumnDefinitionChange` callback that is called when resize, sort, order etc changes
56
+ */
57
+ interface DataTableProps<T> extends React.HTMLAttributes<HTMLTableElement> {
49
58
  children?: never;
50
59
  /**
51
60
  * Controls vertical cell padding.
@@ -60,21 +69,16 @@ interface DataTableProps<T>
60
69
  /**
61
70
  * Truncate content in cells and show ellipsis for overflowed text.
62
71
  *
63
- * **NB:** When using `layout="auto"`, you have to manually set a `maxWidth` on columns that should be truncated.
64
- * @default true
72
+ * **NB:** When using this together with `layout="auto"`,
73
+ * you have to manually set a `maxWidth` on columns that should be truncated.
74
+ * @default false if layout="auto", else true
65
75
  */
66
- truncateContent?: boolean; // TODO: Consider making this default false when layout=auto, and maybe disallow it but add a wrap prop on the td-comp.
76
+ truncateContent?: boolean;
67
77
  /**
68
78
  * Enables keyboard navigation for table rows and cells.
69
79
  * @default true
70
80
  */
71
81
  withKeyboardNav?: boolean;
72
- /**
73
- * Custom callback to determine if navigation should be blocked.
74
- * Called before default blocking logic.
75
- * Requires `withKeyboardNav` to be `true`.
76
- */
77
- shouldBlockNavigation?: (event: KeyboardEvent) => boolean;
78
82
  /**
79
83
  * Controls table layout.
80
84
  *
@@ -90,35 +94,14 @@ interface DataTableProps<T>
90
94
  * @default "fixed"
91
95
  */
92
96
  layout?: "fixed" | "auto";
93
- /**
94
- * Defines the columns of the table and how to render them.
95
- *
96
- *
97
- * 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.
98
- */
99
- columnDefinitions: ColumnDefinitions<T>;
100
- /**
101
- * The data to display in the table.
102
- *
103
- *
104
- * Each object in the array represents a row, and the properties of the object are used to render the cells based on the `columnDefinitions`.
105
- */
106
- data: T[];
107
- /**
108
- * Function to get unique row id from row data.
109
- *
110
- *
111
- * 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.
112
- */
113
- getRowId?: (rowData: T) => string | number;
114
97
  /**
115
98
  * Sticky columns that remain visible when horizontally scrolling the table.
116
99
  *
117
100
  * You can specify 1 sticky column on the left and 1 on the right.
118
101
  */
119
102
  stickyColumns?: {
120
- first?: "1";
121
- last?: "1";
103
+ start?: "1";
104
+ end?: "1";
122
105
  };
123
106
  /**
124
107
  * @default true
@@ -129,215 +112,167 @@ interface DataTableProps<T>
129
112
  * Not called when clicking header, loading, or empty-state rows.
130
113
  */
131
114
  onRowClick?: (
132
- rowId: string | number,
115
+ rowId: TableRowEntryId,
133
116
  event: React.MouseEvent<HTMLTableRowElement>,
134
117
  ) => void;
135
118
  /**
136
119
  * Content to render when `data` is empty.
137
120
  * Rendered inside a `DataTable.EmptyState` row spanning all columns.
138
121
  */
139
- emptyState?: React.ReactNode;
140
- loading?: {
141
- /**
142
- * Shows the table in a loading state.
143
- *
144
- * - When `loadingState` is provided, it is rendered inside a `DataTable.LoadingState` row.
145
- * - When `loadingState` is **not** provided, skeleton placeholder rows are rendered instead.
146
- * @default false
147
- */
148
- isLoading?: boolean;
149
- /**
150
- * Custom content to render when `isLoading` is `true`.
151
- * Rendered inside a `DataTable.LoadingState` row spanning all columns.
152
- * When omitted, skeleton rows are rendered based on `loadingRows`.
153
- */
154
- loadingState?: React.ReactNode;
155
- /**
156
- * Number of skeleton rows to render when `isLoading` is `true` and no `loadingState` is provided.
157
- *
158
- *
159
- * If not provided, the rendered content will get a temporarily overlay while loading
160
- */
161
- loadingRows?: number;
162
- /**
163
- * Visually hidden label announced to screen readers when skeleton rows are shown.
164
- * Only used when `isLoading` is `true` and no `loadingState` is provided.
165
- * @default "Laster innhold"
166
- */
167
- loadingLabel?: string;
168
- };
169
-
122
+ emptyContent?: React.ReactNode;
170
123
  /**
171
- * Function to get sub-rows for a given row, used for nested rows.
172
- * When provided, an expand toggle column is added automatically.
173
- *
124
+ * Configures how the table behaves during loading.
174
125
  *
175
- * TODO:
176
- * - Table might need to be implemented with role="treegrid" for a11y when having nested rows.
126
+ * Use `variant` to select the loading strategy:
127
+ * - `"content"` renders custom content inside a full-width row.
128
+ * - `"skeleton"` — renders skeleton placeholder rows.
129
+ * - `"overlay"` — keeps existing data visible with a loading overlay.
130
+ */
131
+ loading?: DataTableLoadingConfig;
132
+ /**
133
+ * Adjusts font-size
134
+ * @default "medium"
135
+ */
136
+ textSize?: "small" | "medium";
137
+ /**
138
+ * Object with props related to row selection.
139
+ */
140
+ selection?: SelectionProps<T>;
141
+ /**
142
+ * Object with props related to nested rows (sub-rows).
143
+ */
144
+ subRows?: SubRowsProps<T>; // TODO: Table might need to be implemented with role="treegrid" for a11y when having nested rows.
145
+ /**
146
+ * Object with props related to details panel.
147
+ * This is a panel that can be expanded below each row to show arbitrary content.
177
148
  */
178
- selection?: SelectionProps;
179
- subRows?: SubRowsProps<T>;
180
149
  detailsPanel?: DetailsPanelProps<T>;
150
+ /**
151
+ * Object with props related to sorting.
152
+ */
153
+ sorting?: TableSortOptions;
181
154
  }
182
155
 
183
- function DataTableInner<T>(
184
- {
185
- className,
186
- id,
187
- rowDensity = "normal",
188
- withKeyboardNav = true,
189
- zebraStripes = false,
190
- truncateContent = true,
191
- shouldBlockNavigation,
192
- layout = "fixed",
193
- selection,
194
- data,
195
- columnDefinitions,
196
- getRowId,
197
- stickyColumns,
198
- stickyHeader = true,
199
- sort: sortProp,
200
- defaultSort = [],
201
- onSortChange,
202
- onRowClick,
203
- emptyState,
204
- loading,
205
- detailsPanel,
206
- subRows,
207
- ...rest
208
- }: DataTableProps<T>,
209
- forwardedRef: React.ForwardedRef<HTMLTableElement>,
210
- ) {
211
- const { sortState, onSortClick } = useTableSort({
212
- defaultSort,
213
- onSortChange,
214
- sort: sortProp,
215
- });
156
+ const DataTableInternal = forwardRef<HTMLTableElement, DataTableProps<any>>(
157
+ (
158
+ {
159
+ className,
160
+ id,
161
+ rowDensity = "normal",
162
+ textSize = "medium",
163
+ withKeyboardNav = true,
164
+ zebraStripes = false,
165
+ truncateContent: truncateContentProp,
166
+ layout = "fixed",
167
+ stickyColumns,
168
+ stickyHeader = true,
169
+ onRowClick,
170
+ emptyContent,
171
+ selection,
172
+ loading,
173
+ detailsPanel,
174
+ subRows,
175
+ sorting,
176
+ ...rest
177
+ }: DataTableProps<any>, // Have to use <any> for docgen to work
178
+ forwardedRef,
179
+ ) => {
180
+ const { columnDefinitions, data, getRowId } = useDataGridContext();
181
+
182
+ const sortingState = useTableSort(sorting);
183
+
184
+ const tableItems = useTableItems({
185
+ items: data,
186
+ getRowId,
187
+ subRows,
188
+ });
216
189
 
217
- const tableItems = useTableItems({
218
- items: data,
219
- getRowId,
220
- subRows,
221
- });
190
+ const tableSelectionState = useTableSelection({
191
+ selection,
192
+ tableItems,
193
+ });
222
194
 
223
- const tableSelectionState = useTableSelection({
224
- selection,
225
- visibleRowIds: tableItems.visibleRowIds,
226
- childRowIdsById: tableItems.childRowIdsById,
227
- });
195
+ const { columns, stickyStart, totalColSpan } = useColumnOptions(
196
+ columnDefinitions,
197
+ {
198
+ stickyColumns,
199
+ hasSelection: tableSelectionState.selection.selectionMode !== "none",
200
+ hasDetailsPanel: !!detailsPanel?.getContent,
201
+ layout,
202
+ },
203
+ );
228
204
 
229
- const { columns, stickySelection } = useColumnOptions<T>(columnDefinitions, {
230
- stickyColumns,
231
- selectionMode: tableSelectionState.selection.selectionMode,
232
- });
205
+ const tableId = useId(id);
233
206
 
234
- const {
235
- isLoading = false,
236
- loadingState,
237
- loadingRows,
238
- loadingLabel = "Laster innhold",
239
- } = loading || {};
207
+ const truncateContent = truncateContentProp ?? layout !== "auto";
240
208
 
241
- const fullWidthColSpan = useMemo(() => {
242
209
  return (
243
- columns.length +
244
- (layout === "fixed" ? 1 : 0) +
245
- (tableSelectionState.selection.selectionMode !== "none" ? 1 : 0) +
246
- (detailsPanel?.getContent ? 1 : 0)
247
- );
248
- }, [
249
- columns,
250
- layout,
251
- tableSelectionState.selection.selectionMode,
252
- detailsPanel,
253
- ]);
254
-
255
- const tableId = useId(id);
256
-
257
- return (
258
- <DataTableContextProvider
259
- layout={layout}
260
- withKeyboardNav={withKeyboardNav}
261
- selectionState={tableSelectionState}
262
- stickySelection={stickySelection}
263
- stickyHeader={stickyHeader}
264
- tableId={tableId}
265
- showLoadingSkeletons={isLoading && loadingState == null}
266
- onRowClick={onRowClick}
267
- isLoading={isLoading}
268
- showLoadingOverlay={isLoading && !loadingState && !loadingRows}
269
- columns={columns}
270
- fullWidthColSpan={fullWidthColSpan}
271
- >
272
- <TableItemsProvider
273
- itemDetails={tableItems.itemDetails}
274
- items={tableItems.items}
275
- visibleRowIds={tableItems.visibleRowIds}
276
- onExpandedRowIdsChange={tableItems.onExpandedRowIdsChange}
277
- isSubRowExpanded={tableItems.isSubRowExpanded}
210
+ <DataTableContextProvider
211
+ layout={layout}
212
+ withKeyboardNav={withKeyboardNav}
213
+ selectionState={tableSelectionState}
214
+ stickyStart={stickyStart}
215
+ stickyHeader={stickyHeader}
216
+ tableId={tableId}
217
+ loading={loading}
218
+ onRowClick={onRowClick}
219
+ columns={columns}
220
+ totalColSpan={totalColSpan}
221
+ tableItems={tableItems}
222
+ sortingState={sortingState}
278
223
  >
279
- <DataTableDetailsPanelProvider detailsPanel={detailsPanel}>
280
- <TableElementWrapper
281
- shouldBlockNavigation={shouldBlockNavigation}
282
- enabled={withKeyboardNav}
224
+ <TableElementWrapper enabled={withKeyboardNav}>
225
+ <table
226
+ {...rest}
227
+ ref={forwardedRef}
228
+ className={cl("aksel-data-table", className)}
229
+ data-zebra-stripes={zebraStripes}
230
+ data-truncate-content={truncateContent}
231
+ data-density={rowDensity}
232
+ data-text-size={textSize}
233
+ data-layout={layout}
234
+ data-loading={loading?.isLoading || undefined}
235
+ aria-busy={loading?.isLoading || undefined}
283
236
  >
284
- <table
285
- {...rest}
286
- ref={forwardedRef}
287
- className={cl("aksel-data-table", className)}
288
- data-zebra-stripes={zebraStripes}
289
- data-truncate-content={truncateContent}
290
- data-density={rowDensity}
291
- data-layout={layout}
292
- data-loading={isLoading || undefined}
293
- aria-busy={isLoading || undefined}
294
- >
237
+ <DataTableDetailsPanelProvider detailsPanel={detailsPanel}>
295
238
  <DataTableThead>
296
239
  <DataTableTr>
297
- {columns.map(({ isSticky, colDef }) => {
298
- const sortEntry = sortState.find(
299
- (s) => s.columnId === colDef.id,
300
- );
301
- const sortDirection = sortEntry?.direction ?? "none";
302
- return (
303
- <DataTableColumnHeader
304
- resizable={colDef.resizable}
305
- width={colDef.width}
306
- defaultWidth={colDef.defaultWidth}
307
- autoWidth={colDef.autoWidth}
308
- minWidth={colDef.minWidth}
309
- maxWidth={colDef.maxWidth}
310
- onWidthChange={colDef.onWidthChange}
311
- textAlign={colDef.align ?? "left"}
312
- key={colDef.id}
313
- isSticky={isSticky}
314
- sortable={colDef.sortable}
315
- sortDirection={sortDirection}
316
- onSortClick={(event) => onSortClick(colDef.id, event)}
317
- label={colDef.label}
318
- >
319
- {colDef.header ?? colDef.label}
320
- </DataTableColumnHeader>
321
- );
322
- })}
240
+ {columns.map(
241
+ ({ isSticky, isStickyLast, stickyLeftOffset, colDef }) => {
242
+ return (
243
+ <DataTableColumnHeader
244
+ id={colDef.id}
245
+ width={colDef.width}
246
+ textAlign={colDef.align ?? "left"}
247
+ key={colDef.id}
248
+ isSticky={isSticky}
249
+ sortable={colDef.sortable}
250
+ label={colDef.label}
251
+ style={
252
+ stickyLeftOffset
253
+ ? { left: stickyLeftOffset }
254
+ : undefined
255
+ }
256
+ data-sticky-last={isStickyLast || undefined}
257
+ >
258
+ {colDef.header ?? colDef.label}
259
+ </DataTableColumnHeader>
260
+ );
261
+ },
262
+ )}
323
263
  </DataTableTr>
324
264
  </DataTableThead>
325
265
 
326
266
  <DataTableTbody>
327
- <DataTableTBodyContent
328
- loadingState={loadingState}
329
- loadingRows={loadingRows}
330
- loadingLabel={loadingLabel}
331
- emptyState={emptyState}
332
- />
267
+ <DataTableTBodyContent emptyContent={emptyContent} />
333
268
  </DataTableTbody>
334
- </table>
335
- </TableElementWrapper>
336
- </DataTableDetailsPanelProvider>
337
- </TableItemsProvider>
338
- </DataTableContextProvider>
339
- );
340
- }
269
+ </DataTableDetailsPanelProvider>
270
+ </table>
271
+ </TableElementWrapper>
272
+ </DataTableContextProvider>
273
+ );
274
+ },
275
+ );
341
276
 
342
277
  /**
343
278
  * Temp optimization to avoid re-renders on every keyboard-move, selection change etc
@@ -345,10 +280,8 @@ function DataTableInner<T>(
345
280
  function TableElementWrapper({
346
281
  children,
347
282
  enabled,
348
- shouldBlockNavigation,
349
283
  }: {
350
284
  children: React.ReactNode;
351
- shouldBlockNavigation?: (event: KeyboardEvent) => boolean;
352
285
  enabled: boolean;
353
286
  }) {
354
287
  const [applyStickyStyles, setApplyStickyStyles] = useState<boolean>(false);
@@ -358,7 +291,6 @@ function TableElementWrapper({
358
291
  const rafRef = useRef<number | null>(null);
359
292
  const { tabIndex, setTableRef } = useTableKeyboardNav({
360
293
  enabled,
361
- shouldBlockNavigation,
362
294
  });
363
295
 
364
296
  const mergedTableRefs = useMergeRefs(tableRef, setTableRef);
@@ -437,77 +369,86 @@ function TableElementWrapper({
437
369
  }
438
370
 
439
371
  interface DataTableTBodyContentProps {
440
- loadingState: React.ReactNode;
441
- loadingLabel: string;
442
- loadingRows?: number;
443
- emptyState: React.ReactNode;
372
+ emptyContent: React.ReactNode;
444
373
  }
445
374
 
446
- function DataTableTBodyContent({
447
- loadingState,
448
- loadingRows,
449
- loadingLabel,
450
- emptyState,
451
- }: DataTableTBodyContentProps) {
452
- const { items, itemDetails, visibleRowIds } = useTableItemsContext();
453
- const { columns, isLoading, fullWidthColSpan } = useDataTableContext();
375
+ function DataTableTBodyContent({ emptyContent }: DataTableTBodyContentProps) {
376
+ const { columns, loading, totalColSpan, tableItems } = useDataTableContext();
454
377
 
455
- if (isLoading && loadingState != null) {
378
+ if (loading?.isLoading && loading?.variant === "content") {
456
379
  return (
457
- <DataTableLoadingState colSpan={fullWidthColSpan}>
458
- {loadingState}
380
+ <DataTableLoadingState colSpan={totalColSpan}>
381
+ {loading.content}
459
382
  </DataTableLoadingState>
460
383
  );
461
384
  }
462
385
 
463
- if (isLoading && loadingRows) {
386
+ if (loading?.isLoading && loading?.variant === "skeleton") {
387
+ const rows = loading.rows ?? 5;
388
+ const label = loading.label ?? "Laster innhold";
464
389
  return (
465
390
  <>
466
391
  <tr>
467
- <td colSpan={fullWidthColSpan} className="aksel-sr-only">
468
- {loadingLabel}
392
+ <td colSpan={totalColSpan} className="aksel-sr-only">
393
+ {label}
469
394
  </td>
470
395
  </tr>
471
- {Array.from({ length: loadingRows }, (_, rowIndex) => (
396
+ {Array.from({ length: rows }, (_, rowIndex) => (
472
397
  <DataTableTr key={`skeleton-row-${rowIndex}`} aria-hidden>
473
- {columns.map(({ isSticky, colDef }, colDefIndex) => (
474
- <DataTableBaseCell
475
- textAlign={colDef.align ?? "left"}
476
- key={colDef.id || colDefIndex}
477
- as={colDef.isRowHeader ? "th" : "td"}
478
- isSticky={isSticky}
479
- >
480
- <Skeleton variant="text" />
481
- </DataTableBaseCell>
482
- ))}
398
+ {columns.map(
399
+ (
400
+ { isSticky, isStickyLast, stickyLeftOffset, colDef },
401
+ colDefIndex,
402
+ ) => (
403
+ <DataTableBaseCell
404
+ textAlign={colDef.align ?? "left"}
405
+ key={colDef.id || colDefIndex}
406
+ as={colDef.isRowHeader ? "th" : "td"}
407
+ isSticky={isSticky}
408
+ style={
409
+ stickyLeftOffset ? { left: stickyLeftOffset } : undefined
410
+ }
411
+ data-sticky-last={isStickyLast || undefined}
412
+ >
413
+ <Skeleton variant="text" />
414
+ </DataTableBaseCell>
415
+ ),
416
+ )}
483
417
  </DataTableTr>
484
418
  ))}
485
419
  </>
486
420
  );
487
421
  }
488
422
 
489
- if (items.length === 0 && emptyState !== undefined) {
423
+ if (tableItems.items.length === 0 && emptyContent !== undefined) {
490
424
  return (
491
- <DataTableEmptyState colSpan={fullWidthColSpan}>
492
- {emptyState}
425
+ <DataTableEmptyState colSpan={totalColSpan}>
426
+ {emptyContent}
493
427
  </DataTableEmptyState>
494
428
  );
495
429
  }
496
430
 
497
- const renderLoadingAnnouncement = isLoading && !loadingState && !loadingRows;
431
+ const renderLoadingAnnouncement =
432
+ loading?.isLoading && loading?.variant === "overlay";
433
+
434
+ const overlayLabel =
435
+ loading?.variant === "overlay"
436
+ ? (loading.label ?? "Laster innhold")
437
+ : "Laster innhold";
498
438
 
499
439
  return (
500
440
  <>
501
441
  {renderLoadingAnnouncement && (
502
442
  <tr>
503
- <td colSpan={fullWidthColSpan} className="aksel-sr-only">
504
- {loadingLabel}
443
+ <td colSpan={totalColSpan} className="aksel-sr-only">
444
+ {overlayLabel}
505
445
  </td>
506
446
  </tr>
507
447
  )}
508
- {items.map((rowData, rowIndex) => {
509
- const rowId = visibleRowIds[rowIndex];
510
- const details = rowId != null ? itemDetails.get(rowId) : undefined;
448
+ {tableItems.items.map((rowData, rowIndex) => {
449
+ const rowId = tableItems.visibleRowIds[rowIndex];
450
+ const details =
451
+ rowId != null ? tableItems.itemDetails.get(rowId) : undefined;
511
452
 
512
453
  /* Should in theory be impossible. Look about typing this? */
513
454
  if (!details) {
@@ -519,31 +460,40 @@ function DataTableTBodyContent({
519
460
  return (
520
461
  <React.Fragment key={details.id}>
521
462
  <DataTableTr rowId={details.id}>
522
- {columns.map(({ isSticky, colDef }, colDefIndex) => {
523
- const renderNestedToggle = colDefIndex === 0 && hasSubRows;
524
- const renderNestedIndent =
525
- colDefIndex === 0 && (details.level > 0 || hasSubRows);
526
-
527
- const style: React.CSSProperties = {
528
- "--__axc-data-table-nested-depth": details.level,
529
- };
530
-
531
- return (
532
- <DataTableBaseCell
533
- textAlign={colDef.align ?? "left"}
534
- key={colDef.id || colDefIndex}
535
- as={colDef.isRowHeader ? "th" : "td"}
536
- isSticky={isSticky}
537
- data-nested={renderNestedIndent || undefined}
538
- style={style}
539
- >
540
- {renderNestedToggle && (
541
- <DataTableSubRowToggle details={details} />
542
- )}
543
- {colDef.cell(rowData)}
544
- </DataTableBaseCell>
545
- );
546
- })}
463
+ {columns.map(
464
+ (
465
+ { isSticky, isStickyLast, stickyLeftOffset, colDef },
466
+ colDefIndex,
467
+ ) => {
468
+ const renderNestedToggle = colDefIndex === 0 && hasSubRows;
469
+ const renderNestedIndent =
470
+ colDefIndex === 0 && (details.level > 0 || hasSubRows);
471
+
472
+ const style: React.CSSProperties = {
473
+ "--__axc-data-table-nested-depth": details.level,
474
+ ...(stickyLeftOffset ? { left: stickyLeftOffset } : {}),
475
+ };
476
+
477
+ return (
478
+ <DataTableBaseCell
479
+ textAlign={colDef.align ?? "left"}
480
+ key={colDef.id || colDefIndex}
481
+ as={colDef.isRowHeader ? "th" : "td"}
482
+ isSticky={isSticky}
483
+ data-nested={renderNestedIndent || undefined}
484
+ data-sticky-last={isStickyLast || undefined}
485
+ style={style}
486
+ beforeContent={
487
+ renderNestedToggle ? (
488
+ <DataTableSubRowToggle details={details} />
489
+ ) : undefined
490
+ }
491
+ >
492
+ {colDef.cell(rowData)}
493
+ </DataTableBaseCell>
494
+ );
495
+ },
496
+ )}
547
497
  </DataTableTr>
548
498
  <DataTableDetailsPanelRow rowId={details.id} rowData={rowData} />
549
499
  </React.Fragment>
@@ -553,10 +503,11 @@ function DataTableTBodyContent({
553
503
  );
554
504
  }
555
505
 
556
- const DataTable = forwardRef(DataTableInner) as <T>(
506
+ const DataTable = DataTableInternal as <T>(
557
507
  props: DataTableProps<T> & React.RefAttributes<HTMLTableElement>,
558
508
  ) => React.ReactElement | null;
559
509
 
560
- export { DataTable };
510
+ // docgen doesn't work well with type params, so we let it use DataTableInternal instead
511
+ export { DataTable, DataTableInternal };
561
512
  export type { DataTableProps };
562
513
  export default DataTable;