@navikt/ds-react 8.10.5 → 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.
Files changed (266) hide show
  1. package/cjs/data/drag-and-drop/drag-handler/DragAndDropDragHandler.js +0 -1
  2. package/cjs/data/drag-and-drop/drag-handler/DragAndDropDragHandler.js.map +1 -1
  3. package/cjs/data/drag-and-drop/root/DragAndDropRoot.d.ts +6 -6
  4. package/cjs/data/drag-and-drop/root/DragAndDropRoot.js +6 -29
  5. package/cjs/data/drag-and-drop/root/DragAndDropRoot.js.map +1 -1
  6. package/cjs/data/stories/Data.test-data.d.ts +3 -6
  7. package/cjs/data/stories/Data.test-data.js +46 -59
  8. package/cjs/data/stories/Data.test-data.js.map +1 -1
  9. package/cjs/data/table/base-cell/DataTableBaseCell.d.ts +18 -18
  10. package/cjs/data/table/base-cell/DataTableBaseCell.js +4 -8
  11. package/cjs/data/table/base-cell/DataTableBaseCell.js.map +1 -1
  12. package/cjs/data/table/column-header/DataTableColumnHeader.d.ts +19 -13
  13. package/cjs/data/table/column-header/DataTableColumnHeader.js +26 -28
  14. package/cjs/data/table/column-header/DataTableColumnHeader.js.map +1 -1
  15. package/cjs/data/table/column-header/useTableColumnResize.d.ts +19 -29
  16. package/cjs/data/table/column-header/useTableColumnResize.js +30 -28
  17. package/cjs/data/table/column-header/useTableColumnResize.js.map +1 -1
  18. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.d.ts +1 -1
  19. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.js +2 -2
  20. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.js.map +1 -1
  21. package/cjs/data/table/helpers/collectTableRowEntries.d.ts +2 -2
  22. package/cjs/data/table/helpers/selection/getMultipleSelectProps.d.ts +14 -11
  23. package/cjs/data/table/helpers/selection/getMultipleSelectProps.js +45 -51
  24. package/cjs/data/table/helpers/selection/getMultipleSelectProps.js.map +1 -1
  25. package/cjs/data/table/helpers/selection/getSingleSelectProps.d.ts +9 -8
  26. package/cjs/data/table/helpers/selection/getSingleSelectProps.js +23 -10
  27. package/cjs/data/table/helpers/selection/getSingleSelectProps.js.map +1 -1
  28. package/cjs/data/table/helpers/selection/selection.types.d.ts +24 -32
  29. package/cjs/data/table/helpers/selection/selection.utils.d.ts +21 -0
  30. package/cjs/data/table/helpers/selection/selection.utils.js +46 -0
  31. package/cjs/data/table/helpers/selection/selection.utils.js.map +1 -0
  32. package/cjs/data/table/hooks/useColumnOptions.d.ts +17 -6
  33. package/cjs/data/table/hooks/useColumnOptions.js +26 -8
  34. package/cjs/data/table/hooks/useColumnOptions.js.map +1 -1
  35. package/cjs/data/table/hooks/useTableDetailsPanel.d.ts +10 -14
  36. package/cjs/data/table/hooks/useTableDetailsPanel.js +6 -5
  37. package/cjs/data/table/hooks/useTableDetailsPanel.js.map +1 -1
  38. package/cjs/data/table/hooks/useTableItems.d.ts +32 -19
  39. package/cjs/data/table/hooks/useTableItems.js +13 -15
  40. package/cjs/data/table/hooks/useTableItems.js.map +1 -1
  41. package/cjs/data/table/hooks/useTableKeyboardNav.d.ts +1 -6
  42. package/cjs/data/table/hooks/useTableKeyboardNav.js +1 -4
  43. package/cjs/data/table/hooks/useTableKeyboardNav.js.map +1 -1
  44. package/cjs/data/table/hooks/useTableSelection.d.ts +7 -6
  45. package/cjs/data/table/hooks/useTableSelection.js +52 -35
  46. package/cjs/data/table/hooks/useTableSelection.js.map +1 -1
  47. package/cjs/data/table/hooks/useTableSort.d.ts +15 -9
  48. package/cjs/data/table/hooks/useTableSort.js +9 -11
  49. package/cjs/data/table/hooks/useTableSort.js.map +1 -1
  50. package/cjs/data/table/index.d.ts +1 -1
  51. package/cjs/data/table/index.js +3 -23
  52. package/cjs/data/table/index.js.map +1 -1
  53. package/cjs/data/table/root/DataGridTable.types.d.ts +65 -0
  54. package/cjs/data/table/root/DataGridTable.types.js +3 -0
  55. package/cjs/data/table/root/DataGridTable.types.js.map +1 -0
  56. package/cjs/data/table/root/DataGridTableRoot.d.ts +104 -0
  57. package/cjs/data/table/root/DataGridTableRoot.js +237 -0
  58. package/cjs/data/table/root/DataGridTableRoot.js.map +1 -0
  59. package/cjs/data/table/root/DataTableRoot.context.d.ts +17 -7
  60. package/cjs/data/table/root/DataTableRoot.context.js.map +1 -1
  61. package/cjs/data/table/sub-row-toggle/DataTableSubRowToggle.js +4 -4
  62. package/cjs/data/table/sub-row-toggle/DataTableSubRowToggle.js.map +1 -1
  63. package/cjs/data/table/tbody/DataTableTbody.js +4 -2
  64. package/cjs/data/table/tbody/DataTableTbody.js.map +1 -1
  65. package/cjs/data/table/tr/DataTableTr.d.ts +7 -5
  66. package/cjs/data/table/tr/DataTableTr.js +69 -32
  67. package/cjs/data/table/tr/DataTableTr.js.map +1 -1
  68. package/cjs/data/token-filter/TokenFilter.d.ts +0 -6
  69. package/cjs/data/token-filter/TokenFilter.js +1 -1
  70. package/cjs/data-grid/index.d.ts +2 -0
  71. package/cjs/data-grid/index.js +9 -0
  72. package/cjs/data-grid/index.js.map +1 -0
  73. package/cjs/data-grid/root/DataGrid.types.d.ts +35 -0
  74. package/cjs/{data/table/root/DataTable.types.js → data-grid/root/DataGrid.types.js} +1 -1
  75. package/cjs/data-grid/root/DataGrid.types.js.map +1 -0
  76. package/cjs/data-grid/root/DataGridRoot.context.d.ts +16 -0
  77. package/cjs/data-grid/root/DataGridRoot.context.js +11 -0
  78. package/cjs/data-grid/root/DataGridRoot.context.js.map +1 -0
  79. package/cjs/data-grid/root/DataGridRoot.d.ts +89 -0
  80. package/cjs/data-grid/root/DataGridRoot.js +93 -0
  81. package/cjs/data-grid/root/DataGridRoot.js.map +1 -0
  82. package/cjs/preview.d.ts +1 -0
  83. package/cjs/preview.js +7 -0
  84. package/cjs/preview.js.map +1 -0
  85. package/cjs/table/ColumnHeader.js +2 -1
  86. package/cjs/table/ColumnHeader.js.map +1 -1
  87. package/esm/data/drag-and-drop/drag-handler/DragAndDropDragHandler.js +0 -1
  88. package/esm/data/drag-and-drop/drag-handler/DragAndDropDragHandler.js.map +1 -1
  89. package/esm/data/drag-and-drop/root/DragAndDropRoot.d.ts +6 -6
  90. package/esm/data/drag-and-drop/root/DragAndDropRoot.js +6 -29
  91. package/esm/data/drag-and-drop/root/DragAndDropRoot.js.map +1 -1
  92. package/esm/data/stories/Data.test-data.d.ts +3 -6
  93. package/esm/data/stories/Data.test-data.js +46 -59
  94. package/esm/data/stories/Data.test-data.js.map +1 -1
  95. package/esm/data/table/base-cell/DataTableBaseCell.d.ts +18 -18
  96. package/esm/data/table/base-cell/DataTableBaseCell.js +4 -8
  97. package/esm/data/table/base-cell/DataTableBaseCell.js.map +1 -1
  98. package/esm/data/table/column-header/DataTableColumnHeader.d.ts +19 -13
  99. package/esm/data/table/column-header/DataTableColumnHeader.js +27 -29
  100. package/esm/data/table/column-header/DataTableColumnHeader.js.map +1 -1
  101. package/esm/data/table/column-header/useTableColumnResize.d.ts +19 -29
  102. package/esm/data/table/column-header/useTableColumnResize.js +30 -28
  103. package/esm/data/table/column-header/useTableColumnResize.js.map +1 -1
  104. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.d.ts +1 -1
  105. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.js +2 -2
  106. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.js.map +1 -1
  107. package/esm/data/table/helpers/collectTableRowEntries.d.ts +2 -2
  108. package/esm/data/table/helpers/selection/getMultipleSelectProps.d.ts +14 -11
  109. package/esm/data/table/helpers/selection/getMultipleSelectProps.js +45 -51
  110. package/esm/data/table/helpers/selection/getMultipleSelectProps.js.map +1 -1
  111. package/esm/data/table/helpers/selection/getSingleSelectProps.d.ts +9 -8
  112. package/esm/data/table/helpers/selection/getSingleSelectProps.js +23 -10
  113. package/esm/data/table/helpers/selection/getSingleSelectProps.js.map +1 -1
  114. package/esm/data/table/helpers/selection/selection.types.d.ts +24 -32
  115. package/esm/data/table/helpers/selection/selection.utils.d.ts +21 -0
  116. package/esm/data/table/helpers/selection/selection.utils.js +43 -0
  117. package/esm/data/table/helpers/selection/selection.utils.js.map +1 -0
  118. package/esm/data/table/hooks/useColumnOptions.d.ts +17 -6
  119. package/esm/data/table/hooks/useColumnOptions.js +26 -8
  120. package/esm/data/table/hooks/useColumnOptions.js.map +1 -1
  121. package/esm/data/table/hooks/useTableDetailsPanel.d.ts +10 -14
  122. package/esm/data/table/hooks/useTableDetailsPanel.js +6 -5
  123. package/esm/data/table/hooks/useTableDetailsPanel.js.map +1 -1
  124. package/esm/data/table/hooks/useTableItems.d.ts +32 -19
  125. package/esm/data/table/hooks/useTableItems.js +14 -13
  126. package/esm/data/table/hooks/useTableItems.js.map +1 -1
  127. package/esm/data/table/hooks/useTableKeyboardNav.d.ts +1 -6
  128. package/esm/data/table/hooks/useTableKeyboardNav.js +1 -4
  129. package/esm/data/table/hooks/useTableKeyboardNav.js.map +1 -1
  130. package/esm/data/table/hooks/useTableSelection.d.ts +7 -6
  131. package/esm/data/table/hooks/useTableSelection.js +52 -35
  132. package/esm/data/table/hooks/useTableSelection.js.map +1 -1
  133. package/esm/data/table/hooks/useTableSort.d.ts +15 -9
  134. package/esm/data/table/hooks/useTableSort.js +10 -12
  135. package/esm/data/table/hooks/useTableSort.js.map +1 -1
  136. package/esm/data/table/index.d.ts +1 -1
  137. package/esm/data/table/index.js +1 -21
  138. package/esm/data/table/index.js.map +1 -1
  139. package/esm/data/table/root/DataGridTable.types.d.ts +65 -0
  140. package/esm/data/table/root/DataGridTable.types.js +2 -0
  141. package/esm/data/table/root/DataGridTable.types.js.map +1 -0
  142. package/esm/data/table/root/DataGridTableRoot.d.ts +104 -0
  143. package/esm/data/table/root/DataGridTableRoot.js +202 -0
  144. package/esm/data/table/root/DataGridTableRoot.js.map +1 -0
  145. package/esm/data/table/root/DataTableRoot.context.d.ts +17 -7
  146. package/esm/data/table/root/DataTableRoot.context.js.map +1 -1
  147. package/esm/data/table/sub-row-toggle/DataTableSubRowToggle.js +4 -4
  148. package/esm/data/table/sub-row-toggle/DataTableSubRowToggle.js.map +1 -1
  149. package/esm/data/table/tbody/DataTableTbody.js +4 -2
  150. package/esm/data/table/tbody/DataTableTbody.js.map +1 -1
  151. package/esm/data/table/tr/DataTableTr.d.ts +7 -5
  152. package/esm/data/table/tr/DataTableTr.js +68 -32
  153. package/esm/data/table/tr/DataTableTr.js.map +1 -1
  154. package/esm/data/token-filter/TokenFilter.d.ts +0 -6
  155. package/esm/data/token-filter/TokenFilter.js +1 -1
  156. package/esm/data-grid/index.d.ts +2 -0
  157. package/esm/data-grid/index.js +4 -0
  158. package/esm/data-grid/index.js.map +1 -0
  159. package/esm/data-grid/root/DataGrid.types.d.ts +35 -0
  160. package/esm/data-grid/root/DataGrid.types.js +2 -0
  161. package/esm/data-grid/root/DataGrid.types.js.map +1 -0
  162. package/esm/data-grid/root/DataGridRoot.context.d.ts +16 -0
  163. package/esm/data-grid/root/DataGridRoot.context.js +7 -0
  164. package/esm/data-grid/root/DataGridRoot.context.js.map +1 -0
  165. package/esm/data-grid/root/DataGridRoot.d.ts +89 -0
  166. package/esm/data-grid/root/DataGridRoot.js +57 -0
  167. package/esm/data-grid/root/DataGridRoot.js.map +1 -0
  168. package/esm/preview.d.ts +1 -0
  169. package/esm/preview.js +3 -0
  170. package/esm/preview.js.map +1 -0
  171. package/esm/table/ColumnHeader.js +2 -1
  172. package/esm/table/ColumnHeader.js.map +1 -1
  173. package/package.json +23 -3
  174. package/src/data/drag-and-drop/drag-handler/DragAndDropDragHandler.tsx +0 -1
  175. package/src/data/drag-and-drop/root/DragAndDropRoot.tsx +18 -52
  176. package/src/data/stories/Data.test-data.tsx +76 -65
  177. package/src/data/table/base-cell/DataTableBaseCell.tsx +36 -26
  178. package/src/data/table/column-header/DataTableColumnHeader.tsx +62 -62
  179. package/src/data/table/column-header/useTableColumnResize.ts +63 -79
  180. package/src/data/table/details-panel-row/DataTableDetailsPanelRow.tsx +3 -3
  181. package/src/data/table/helpers/collectTableRowEntries.ts +1 -2
  182. package/src/data/table/helpers/selection/getMultipleSelectProps.ts +69 -83
  183. package/src/data/table/helpers/selection/getSingleSelectProps.ts +35 -17
  184. package/src/data/table/helpers/selection/selection.types.ts +23 -33
  185. package/src/data/table/helpers/selection/selection.utils.test.ts +161 -0
  186. package/src/data/table/helpers/selection/selection.utils.ts +73 -0
  187. package/src/data/table/hooks/__tests__/useTableItems.test.ts +2 -1
  188. package/src/data/table/hooks/useColumnOptions.ts +49 -15
  189. package/src/data/table/hooks/useTableDetailsPanel.tsx +21 -28
  190. package/src/data/table/hooks/useTableItems.ts +60 -38
  191. package/src/data/table/hooks/useTableKeyboardNav.ts +1 -13
  192. package/src/data/table/hooks/useTableSelection.ts +80 -68
  193. package/src/data/table/hooks/useTableSort.ts +36 -23
  194. package/src/data/table/index.tsx +4 -21
  195. package/src/data/table/root/DataGridTable.types.ts +82 -0
  196. package/src/data/table/root/DataGridTableRoot.tsx +566 -0
  197. package/src/data/table/root/DataTableRoot.context.ts +24 -10
  198. package/src/data/table/sub-row-toggle/DataTableSubRowToggle.tsx +6 -5
  199. package/src/data/table/tbody/DataTableTbody.tsx +6 -2
  200. package/src/data/table/tr/DataTableTr.tsx +145 -47
  201. package/src/data/token-filter/TokenFilter.tsx +1 -1
  202. package/src/data-grid/index.ts +3 -0
  203. package/src/data-grid/root/DataGrid.types.ts +36 -0
  204. package/src/data-grid/root/DataGridRoot.context.ts +21 -0
  205. package/src/data-grid/root/DataGridRoot.tsx +152 -0
  206. package/src/preview.ts +2 -0
  207. package/src/table/ColumnHeader.tsx +3 -1
  208. package/cjs/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.d.ts +0 -22
  209. package/cjs/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js +0 -35
  210. package/cjs/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js.map +0 -1
  211. package/cjs/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.d.ts +0 -27
  212. package/cjs/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.js +0 -86
  213. package/cjs/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.js.map +0 -1
  214. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.d.ts +0 -5
  215. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js +0 -6
  216. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js.map +0 -1
  217. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.d.ts +0 -24
  218. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.js +0 -108
  219. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.js.map +0 -1
  220. package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.d.ts +0 -46
  221. package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.js +0 -112
  222. package/cjs/data/table/helpers/selection/SelectionSubtreeHelper.js.map +0 -1
  223. package/cjs/data/table/root/DataTable.types.d.ts +0 -63
  224. package/cjs/data/table/root/DataTable.types.js.map +0 -1
  225. package/cjs/data/table/root/DataTableRoot.d.ts +0 -141
  226. package/cjs/data/table/root/DataTableRoot.js +0 -229
  227. package/cjs/data/table/root/DataTableRoot.js.map +0 -1
  228. package/cjs/data/table/root/DataTableRoot.legacy.d.ts +0 -177
  229. package/cjs/data/table/root/DataTableRoot.legacy.js +0 -104
  230. package/cjs/data/table/root/DataTableRoot.legacy.js.map +0 -1
  231. package/esm/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.d.ts +0 -22
  232. package/esm/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js +0 -29
  233. package/esm/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js.map +0 -1
  234. package/esm/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.d.ts +0 -27
  235. package/esm/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.js +0 -50
  236. package/esm/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.js.map +0 -1
  237. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.d.ts +0 -5
  238. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js +0 -3
  239. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js.map +0 -1
  240. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.d.ts +0 -24
  241. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.js +0 -68
  242. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.js.map +0 -1
  243. package/esm/data/table/helpers/selection/SelectionSubtreeHelper.d.ts +0 -46
  244. package/esm/data/table/helpers/selection/SelectionSubtreeHelper.js +0 -109
  245. package/esm/data/table/helpers/selection/SelectionSubtreeHelper.js.map +0 -1
  246. package/esm/data/table/root/DataTable.types.d.ts +0 -63
  247. package/esm/data/table/root/DataTable.types.js +0 -2
  248. package/esm/data/table/root/DataTable.types.js.map +0 -1
  249. package/esm/data/table/root/DataTableRoot.d.ts +0 -141
  250. package/esm/data/table/root/DataTableRoot.js +0 -193
  251. package/esm/data/table/root/DataTableRoot.js.map +0 -1
  252. package/esm/data/table/root/DataTableRoot.legacy.d.ts +0 -177
  253. package/esm/data/table/root/DataTableRoot.legacy.js +0 -59
  254. package/esm/data/table/root/DataTableRoot.legacy.js.map +0 -1
  255. package/src/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.tsx +0 -104
  256. package/src/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.tsx +0 -74
  257. package/src/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.tsx +0 -11
  258. package/src/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.tsx +0 -94
  259. package/src/data/table/Readme.md +0 -11
  260. package/src/data/table/helpers/selection/SelectionSubtreeHelper.test.ts +0 -66
  261. package/src/data/table/helpers/selection/SelectionSubtreeHelper.ts +0 -162
  262. package/src/data/table/hooks/__tests__/useTableSelection.test.ts +0 -488
  263. package/src/data/table/root/DataTable.types.ts +0 -87
  264. package/src/data/table/root/DataTableRoot.legacy.tsx +0 -297
  265. package/src/data/table/root/DataTableRoot.tsx +0 -562
  266. package/src/data/table/root/agent-feature-gap.md +0 -96
@@ -1,562 +0,0 @@
1
- /** biome-ignore-all lint/correctness/useHookAtTopLevel: False positive because of the way forwardRef() is added */
2
- import React, {
3
- forwardRef,
4
- useCallback,
5
- useEffect,
6
- useMemo,
7
- useRef,
8
- useState,
9
- } from "react";
10
- import { Skeleton } from "../../../skeleton";
11
- import { useId } from "../../../utils-external";
12
- import { Slot } from "../../../utils/components/slot/Slot";
13
- import { cl } from "../../../utils/helpers";
14
- import { useMergeRefs } from "../../../utils/hooks";
15
- import { DataTableBaseCell } from "../base-cell/DataTableBaseCell";
16
- import { DataTableColumnHeader } from "../column-header/DataTableColumnHeader";
17
- import { DataTableDetailsPanelRow } from "../details-panel-row/DataTableDetailsPanelRow";
18
- import { DataTableEmptyState } from "../empty-state/DataTableEmptyState";
19
- import { useColumnOptions } from "../hooks/useColumnOptions";
20
- import {
21
- DataTableDetailsPanelProvider,
22
- type DetailsPanelProps,
23
- } from "../hooks/useTableDetailsPanel";
24
- import {
25
- type SubRowsProps,
26
- TableItemsProvider,
27
- useTableItems,
28
- useTableItemsContext,
29
- } from "../hooks/useTableItems";
30
- import { useTableKeyboardNav } from "../hooks/useTableKeyboardNav";
31
- import {
32
- type SelectionProps,
33
- useTableSelection,
34
- } from "../hooks/useTableSelection";
35
- import { type TableSortOptions, useTableSort } from "../hooks/useTableSort";
36
- import { DataTableLoadingState } from "../loading-state/DataTableLoadingState";
37
- import { DataTableSubRowToggle } from "../sub-row-toggle/DataTableSubRowToggle";
38
- import { DataTableTbody } from "../tbody/DataTableTbody";
39
- import { DataTableThead } from "../thead/DataTableThead";
40
- import { DataTableTr } from "../tr/DataTableTr";
41
- import type { ColumnDefinitions } from "./DataTable.types";
42
- import {
43
- DataTableContextProvider,
44
- useDataTableContext,
45
- } from "./DataTableRoot.context";
46
-
47
- interface DataTableProps<T>
48
- extends React.HTMLAttributes<HTMLTableElement>, TableSortOptions {
49
- children?: never;
50
- /**
51
- * Controls vertical cell padding.
52
- * @default "normal"
53
- */
54
- rowDensity?: "condensed" | "normal" | "spacious";
55
- /**
56
- * Zebra striped table
57
- * @default false
58
- */
59
- zebraStripes?: boolean;
60
- /**
61
- * Truncate content in cells and show ellipsis for overflowed text.
62
- *
63
- * **NB:** When using `layout="auto"`, you have to manually set a `maxWidth` on columns that should be truncated.
64
- * @default true
65
- */
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.
67
- /**
68
- * Enables keyboard navigation for table rows and cells.
69
- * @default true
70
- */
71
- 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
- /**
79
- * Controls table layout.
80
- *
81
- * ### fixed
82
- * Gives you full control of column widths. This is required for resizable columns.
83
- *
84
- * ### auto
85
- * Makes the columns resize automatically based on the content.
86
- * The table will take up at least 100% of available width.
87
- *
88
- * **NB:** When using this with `truncateContent`, you have to manually
89
- * set a `contentMaxWidth` on cells that should be truncated.
90
- * @default "fixed"
91
- */
92
- 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
- /**
115
- * Sticky columns that remain visible when horizontally scrolling the table.
116
- *
117
- * You can specify 1 sticky column on the left and 1 on the right.
118
- */
119
- stickyColumns?: {
120
- first?: "1";
121
- last?: "1";
122
- };
123
- /**
124
- * @default true
125
- */
126
- stickyHeader?: boolean;
127
- /**
128
- * Callback invoked when a data row is clicked.
129
- * Not called when clicking header, loading, or empty-state rows.
130
- */
131
- onRowClick?: (
132
- rowId: string | number,
133
- event: React.MouseEvent<HTMLTableRowElement>,
134
- ) => void;
135
- /**
136
- * Content to render when `data` is empty.
137
- * Rendered inside a `DataTable.EmptyState` row spanning all columns.
138
- */
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
-
170
- /**
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
- *
174
- *
175
- * TODO:
176
- * - Table might need to be implemented with role="treegrid" for a11y when having nested rows.
177
- */
178
- selection?: SelectionProps;
179
- subRows?: SubRowsProps<T>;
180
- detailsPanel?: DetailsPanelProps<T>;
181
- }
182
-
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
- });
216
-
217
- const tableItems = useTableItems({
218
- items: data,
219
- getRowId,
220
- subRows,
221
- });
222
-
223
- const tableSelectionState = useTableSelection({
224
- selection,
225
- visibleRowIds: tableItems.visibleRowIds,
226
- childRowIdsById: tableItems.childRowIdsById,
227
- });
228
-
229
- const { columns, stickySelection } = useColumnOptions<T>(columnDefinitions, {
230
- stickyColumns,
231
- selectionMode: tableSelectionState.selection.selectionMode,
232
- });
233
-
234
- const {
235
- isLoading = false,
236
- loadingState,
237
- loadingRows,
238
- loadingLabel = "Laster innhold",
239
- } = loading || {};
240
-
241
- const fullWidthColSpan = useMemo(() => {
242
- 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}
278
- >
279
- <DataTableDetailsPanelProvider detailsPanel={detailsPanel}>
280
- <TableElementWrapper
281
- shouldBlockNavigation={shouldBlockNavigation}
282
- enabled={withKeyboardNav}
283
- >
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
- >
295
- <DataTableThead>
296
- <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
- })}
323
- </DataTableTr>
324
- </DataTableThead>
325
-
326
- <DataTableTbody>
327
- <DataTableTBodyContent
328
- loadingState={loadingState}
329
- loadingRows={loadingRows}
330
- loadingLabel={loadingLabel}
331
- emptyState={emptyState}
332
- />
333
- </DataTableTbody>
334
- </table>
335
- </TableElementWrapper>
336
- </DataTableDetailsPanelProvider>
337
- </TableItemsProvider>
338
- </DataTableContextProvider>
339
- );
340
- }
341
-
342
- /**
343
- * Temp optimization to avoid re-renders on every keyboard-move, selection change etc
344
- */
345
- function TableElementWrapper({
346
- children,
347
- enabled,
348
- shouldBlockNavigation,
349
- }: {
350
- children: React.ReactNode;
351
- shouldBlockNavigation?: (event: KeyboardEvent) => boolean;
352
- enabled: boolean;
353
- }) {
354
- const [applyStickyStyles, setApplyStickyStyles] = useState<boolean>(false);
355
-
356
- const tableWrapperRef = useRef<HTMLDivElement>(null);
357
- const tableRef = useRef<HTMLTableElement>(null);
358
- const rafRef = useRef<number | null>(null);
359
- const { tabIndex, setTableRef } = useTableKeyboardNav({
360
- enabled,
361
- shouldBlockNavigation,
362
- });
363
-
364
- const mergedTableRefs = useMergeRefs(tableRef, setTableRef);
365
-
366
- const updateStickyStyles = useCallback(() => {
367
- if (!tableWrapperRef.current) {
368
- return;
369
- }
370
-
371
- const doesWrapperHasScroll =
372
- tableWrapperRef.current.scrollWidth > tableWrapperRef.current.clientWidth;
373
-
374
- setApplyStickyStyles(doesWrapperHasScroll);
375
- }, []);
376
-
377
- const scheduleStickyStylesUpdate = useCallback(() => {
378
- if (rafRef.current !== null) {
379
- return;
380
- }
381
-
382
- rafRef.current = requestAnimationFrame(() => {
383
- rafRef.current = null;
384
- updateStickyStyles();
385
- });
386
- }, [updateStickyStyles]);
387
-
388
- useEffect(
389
- function observeAndUpdateStickyStyles() {
390
- const tableWrapperElement = tableWrapperRef.current;
391
-
392
- if (!tableWrapperElement) {
393
- return;
394
- }
395
-
396
- const handleResize = () => scheduleStickyStylesUpdate();
397
-
398
- window.addEventListener("resize", handleResize);
399
-
400
- let resizeObserver: ResizeObserver | undefined;
401
- if (typeof ResizeObserver !== "undefined") {
402
- resizeObserver = new ResizeObserver(handleResize);
403
- resizeObserver.observe(tableWrapperElement);
404
- if (tableRef.current) {
405
- resizeObserver.observe(tableRef.current);
406
- }
407
- }
408
-
409
- scheduleStickyStylesUpdate();
410
-
411
- return () => {
412
- window.removeEventListener("resize", handleResize);
413
- resizeObserver?.disconnect();
414
- if (rafRef.current !== null) {
415
- cancelAnimationFrame(rafRef.current);
416
- rafRef.current = null;
417
- }
418
- };
419
- },
420
- [scheduleStickyStylesUpdate],
421
- );
422
-
423
- return (
424
- <div className="aksel-data-table__border-wrapper">
425
- <div ref={tableWrapperRef} className="aksel-data-table__scroll-wrapper">
426
- <Slot
427
- tabIndex={tabIndex}
428
- /* @ts-expect-error Ref is not typed correctly to handle this case */
429
- ref={mergedTableRefs}
430
- data-scroll={applyStickyStyles ? "true" : undefined}
431
- >
432
- {children}
433
- </Slot>
434
- </div>
435
- </div>
436
- );
437
- }
438
-
439
- interface DataTableTBodyContentProps {
440
- loadingState: React.ReactNode;
441
- loadingLabel: string;
442
- loadingRows?: number;
443
- emptyState: React.ReactNode;
444
- }
445
-
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();
454
-
455
- if (isLoading && loadingState != null) {
456
- return (
457
- <DataTableLoadingState colSpan={fullWidthColSpan}>
458
- {loadingState}
459
- </DataTableLoadingState>
460
- );
461
- }
462
-
463
- if (isLoading && loadingRows) {
464
- return (
465
- <>
466
- <tr>
467
- <td colSpan={fullWidthColSpan} className="aksel-sr-only">
468
- {loadingLabel}
469
- </td>
470
- </tr>
471
- {Array.from({ length: loadingRows }, (_, rowIndex) => (
472
- <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
- ))}
483
- </DataTableTr>
484
- ))}
485
- </>
486
- );
487
- }
488
-
489
- if (items.length === 0 && emptyState !== undefined) {
490
- return (
491
- <DataTableEmptyState colSpan={fullWidthColSpan}>
492
- {emptyState}
493
- </DataTableEmptyState>
494
- );
495
- }
496
-
497
- const renderLoadingAnnouncement = isLoading && !loadingState && !loadingRows;
498
-
499
- return (
500
- <>
501
- {renderLoadingAnnouncement && (
502
- <tr>
503
- <td colSpan={fullWidthColSpan} className="aksel-sr-only">
504
- {loadingLabel}
505
- </td>
506
- </tr>
507
- )}
508
- {items.map((rowData, rowIndex) => {
509
- const rowId = visibleRowIds[rowIndex];
510
- const details = rowId != null ? itemDetails.get(rowId) : undefined;
511
-
512
- /* Should in theory be impossible. Look about typing this? */
513
- if (!details) {
514
- return null;
515
- }
516
-
517
- const hasSubRows = details.children.length > 0;
518
-
519
- return (
520
- <React.Fragment key={details.id}>
521
- <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
- })}
547
- </DataTableTr>
548
- <DataTableDetailsPanelRow rowId={details.id} rowData={rowData} />
549
- </React.Fragment>
550
- );
551
- })}
552
- </>
553
- );
554
- }
555
-
556
- const DataTable = forwardRef(DataTableInner) as <T>(
557
- props: DataTableProps<T> & React.RefAttributes<HTMLTableElement>,
558
- ) => React.ReactElement | null;
559
-
560
- export { DataTable };
561
- export type { DataTableProps };
562
- export default DataTable;
@@ -1,96 +0,0 @@
1
- ### Component: DataTable
2
-
3
- **Primitive type:** Data table with optional selection, sorting, nested rows, details panels, sticky columns, column resizing, and keyboard cell navigation.
4
- **Reference libraries:** React Aria Table / Adobe Spectrum TableView, MUI Data Grid, Base UI table patterns. Cloudscape Table is a useful secondary reference for resize/details behavior.
5
-
6
- ### Launch Review Findings
7
-
8
- 1. **The auto API has no visible caption slot or caption prop.**
9
- Consumers can still pass `aria-label`/`aria-labelledby` through native table props, but `children?: never` means the preview API cannot render a native `caption` or a built-in visible summary/title. Mature table APIs usually provide at least one clear accessible naming path.
10
-
11
- 2. **Column resizing is present, but the preview API still reads as unfinished.**
12
- Resizing is effectively opt-out in fixed layout because `DataTableColumnHeader` defaults `resizable` to `true`. The interaction also still has unfinished accessibility and i18n details, and `onWidthChange` currently fires for every width step while dragging.
13
-
14
- 3. **Critical behaviors are under-tested for a preview launch.**
15
- Existing tests cover selection trees, item expansion state, and low-level keyboard helpers, but not the end-to-end behaviors users will notice first: sorting, details panels, loading states, row click behavior, column resizing, and selection accessibility.
16
-
17
- ### Feature Gap Table
18
-
19
- | # | Feature | Status | Priority | Reference | Notes |
20
- | --- | --------------------------------------------------- | ---------- | --------------- | ---------------------------- | ----------------------------------------------------------------------- |
21
- | 1 | Arrow/Home/End keyboard cell navigation | ✅ Present | — | React Aria, MUI | Good base coverage in helper tests. |
22
- | 2 | Controlled/uncontrolled sorting | ✅ Present | — | React Aria, MUI | Supports controlled and uncontrolled sort arrays. |
23
- | 3 | Multi-column sorting | ✅ Present | — | MUI, Spectrum | Shift-click is supported. |
24
- | 4 | Controlled/uncontrolled row selection | ✅ Present | — | React Aria, MUI | Single and multiple selection both exist. |
25
- | 5 | Controlled/uncontrolled nested row expansion | ✅ Present | — | MUI, Spectrum | `subRows` API is already solid for preview. |
26
- | 6 | Controlled/uncontrolled details panel expansion | ✅ Present | — | MUI | Good baseline, limited to top-level rows by design. |
27
- | 7 | Loading overlay / loading rows / empty state | ✅ Present | — | MUI, Spectrum | Baseline states exist. |
28
- | 9 | Visible caption / built-in accessible naming path | ❌ Missing | 🔴 Expected | React Aria, Spectrum | Auto API cannot render `caption`; users only get raw HTML attrs. |
29
- | 13 | Opt-in / polished column resize API | ⚠️ Partial | 🟡 Valuable | MUI, Cloudscape | Feature exists, but defaults and a11y polish are not preview-ready yet. |
30
- | 14 | Per-row disabled selection callback | ❌ Missing | 🟡 Valuable | React Aria, MUI | Current API only accepts disabled keys, not row-driven logic. |
31
- | 15 | Row-level prop/className callback | ❌ Missing | 🟡 Valuable | MUI | No way to attach row-specific attrs/classes without custom rendering. |
32
- | 16 | Header-group / multi-row header support in auto API | ❌ Missing | 🟢 Nice-to-have | React Aria, MUI | Current auto API is intentionally flat. |
33
- | 17 | Accessor shorthand for simple columns | ❌ Missing | 🟢 Nice-to-have | MUI, TanStack-style patterns | Would reduce boilerplate for simple data tables. |
34
- | 18 | Typeahead row navigation | ❌ Missing | 🟢 Nice-to-have | React Aria | Useful on large data sets, not necessary for first preview. |
35
- | 19 | RTL-aware sticky/nesting layout | ❌ Missing | 🟢 Nice-to-have | React Aria, MUI | Current sticky/nesting CSS is mostly physical, not logical. |
36
-
37
- ### Implementation Notes
38
-
39
- #### 9. Visible caption / built-in accessible naming path
40
-
41
- - **What it does:** Lets consumers provide a native table caption or a clearly supported naming API without dropping to raw HTML attributes.
42
- - **Reference behavior:** React Aria tables require an accessible label; Spectrum and MUI also expose a clear naming path.
43
- - **Approach here:** Keep `children` forbidden, but add a `caption?: React.ReactNode` prop that renders a native `caption`. Optionally add `captionProps` for styling hooks.
44
- - **Props/API additions needed:** `caption?: React.ReactNode`, optionally `captionProps?: React.HTMLAttributes<HTMLTableCaptionElement>`.
45
-
46
- #### 13. Opt-in / polished column resize API
47
-
48
- - **What it does:** Makes resize behavior predictable and avoids surprising every preview consumer with advanced header affordances.
49
- - **Reference behavior:** MUI and Cloudscape treat column resize as an explicit feature and spend a lot of API surface on labels, limits, and commit behavior.
50
- - **Approach here:** Default `resizable` to `false`, add missing slider aria metadata, and only call `onWidthChange` on commit or with a small debounce. Also move hard-coded Norwegian labels into the same i18n pattern as the rest of the component.
51
- - **Props/API additions needed:** No new public props required for a first pass. The main change is default behavior and polish.
52
-
53
- #### 14. Per-row disabled selection callback
54
-
55
- - **What it does:** Lets consumers disable selection from row data instead of precomputing key arrays.
56
- - **Reference behavior:** Many mature table APIs allow row-driven selection rules.
57
- - **Approach here:** Resolve disabled state during row collection so selection helpers can still work with ids internally.
58
- - **Props/API additions needed:** `isRowSelectionDisabled?: (rowData: T) => boolean`.
59
-
60
- #### 15. Row-level prop/className callback
61
-
62
- - **What it does:** Lets consumers add row-specific classes, test hooks, aria hooks, and state styling without replacing the table implementation.
63
- - **Reference behavior:** MUI exposes row-class callbacks and row metadata hooks.
64
- - **Approach here:** Apply callbacks when rendering `DataTableTr` so the row id and row data are both available.
65
- - **Props/API additions needed:** `getRowProps?: (rowData: T, rowId: string | number) => React.HTMLAttributes<HTMLTableRowElement>` or a narrower `getRowClassName` if you want to keep the API tighter.
66
-
67
- ### Internal Refactors
68
-
69
- 1. Split the current root into a small orchestration hook plus presentational sub-components. `DataTableRoot.tsx` currently owns state setup, context assembly, loading/empty rendering, row rendering, and sticky-wrapper logic in one file.
70
-
71
- 2. Replace object-keyed `itemDetails` lookups with id-keyed row entries. This fixes the duplicate-object bug and simplifies details-panel and selection wiring.
72
-
73
- 3. Unify loading-state presence checks. `DataTableTBodyContent` uses nullish checks for `loadingState`, while `showLoadingOverlay` in the root uses truthiness checks; those should match.
74
-
75
- 4. Make localization an explicit seam. The component currently hard-codes visible and aria labels such as sort-resize instructions, expand/collapse labels, and selection labels directly in render code.
76
-
77
- 5. Revisit the resize default and commit path before large-table performance work. Continuous `onWidthChange` callbacks can easily push rerenders through the whole table if consumers control widths externally.
78
-
79
- 6. Decide whether the preview API is a plain table or the start of a data-grid abstraction. A few current seams, especially keyboard navigation and selection, are already grid-like, while captioning and row-header semantics still assume a plain table model.
80
-
81
- ### Test Gaps Before Preview
82
-
83
- 1. Sorting interaction story/test covering click, keyboard activation, and multi-sort.
84
- 2. Details-panel story/test covering expand, collapse, `aria-controls`, and controlled mode.
85
- 3. Loading/empty-state tests covering overlay vs skeleton vs custom loading content.
86
- 4. Row-click tests covering selection interaction, text-selection guard, and interactive-content guard.
87
- 5. Resize tests covering keyboard resize, pointer resize, and form embedding.
88
- 6. Accessibility test coverage for selection labels and row-header semantics once those are implemented.
89
-
90
- ### Suggested Order For Follow-up Work
91
-
92
- 1. Fix selection labeling and row-header semantics together.
93
- 2. Add a built-in caption/naming API.
94
- 3. Harden resize defaults and button semantics.
95
- 4. Refactor row metadata to be id-based.
96
- 5. Fill the missing user-facing stories/tests around sort, details, loading, and row click.