@navikt/ds-react 8.10.3 → 8.10.5

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 (242) 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/drag-and-drop/drag-handler/DragAndDropDragHandler.js +11 -12
  4. package/cjs/data/drag-and-drop/drag-handler/DragAndDropDragHandler.js.map +1 -1
  5. package/cjs/data/drag-and-drop/root/DragAndDrop.context.d.ts +4 -2
  6. package/cjs/data/drag-and-drop/root/DragAndDrop.context.js.map +1 -1
  7. package/cjs/data/drag-and-drop/root/DragAndDropRoot.d.ts +5 -5
  8. package/cjs/data/drag-and-drop/root/DragAndDropRoot.js +49 -28
  9. package/cjs/data/drag-and-drop/root/DragAndDropRoot.js.map +1 -1
  10. package/cjs/data/drag-and-drop/types.d.ts +0 -4
  11. package/cjs/data/{drag-and-drop-old/drag-handler/DataDragAndDropDragHandler.d.ts → drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.d.ts} +3 -3
  12. package/cjs/data/{drag-and-drop-old/drag-handler/DataDragAndDropDragHandler.js → drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js} +5 -5
  13. package/cjs/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js.map +1 -0
  14. package/cjs/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.d.ts +27 -0
  15. package/cjs/data/{drag-and-drop-old/item/DataDragAndDropItem.js → drag-and-drop-legacy/item/DragAndDropItemLegacy.js} +12 -12
  16. package/cjs/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.js.map +1 -0
  17. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.d.ts +5 -0
  18. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js +6 -0
  19. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js.map +1 -0
  20. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.d.ts +24 -0
  21. package/cjs/data/{drag-and-drop-old/root/DataDragAndDropRoot.js → drag-and-drop-legacy/root/DragAndDropLegacyRoot.js} +10 -10
  22. package/cjs/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.js.map +1 -0
  23. package/cjs/data/stories/Data.test-data.d.ts +24 -0
  24. package/cjs/data/stories/Data.test-data.js +1615 -0
  25. package/cjs/data/stories/Data.test-data.js.map +1 -0
  26. package/cjs/data/table/column-header/DataTableColumnHeader.d.ts +4 -1
  27. package/cjs/data/table/column-header/DataTableColumnHeader.js +4 -4
  28. package/cjs/data/table/column-header/DataTableColumnHeader.js.map +1 -1
  29. package/cjs/data/table/column-header/useTableColumnResize.d.ts +21 -18
  30. package/cjs/data/table/column-header/useTableColumnResize.js +7 -25
  31. package/cjs/data/table/column-header/useTableColumnResize.js.map +1 -1
  32. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.d.ts +6 -0
  33. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.js +32 -0
  34. package/cjs/data/table/details-panel-row/DataTableDetailsPanelRow.js.map +1 -0
  35. package/cjs/data/table/helpers/collectTableRowEntries.d.ts +9 -7
  36. package/cjs/data/table/helpers/collectTableRowEntries.js +21 -14
  37. package/cjs/data/table/helpers/collectTableRowEntries.js.map +1 -1
  38. package/cjs/data/table/helpers/table-focus.d.ts +0 -3
  39. package/cjs/data/table/helpers/table-focus.js +38 -8
  40. package/cjs/data/table/helpers/table-focus.js.map +1 -1
  41. package/cjs/data/table/hooks/useColumnOptions.js +18 -5
  42. package/cjs/data/table/hooks/useColumnOptions.js.map +1 -1
  43. package/cjs/data/table/hooks/useGridCache.js +2 -2
  44. package/cjs/data/table/hooks/useGridCache.js.map +1 -1
  45. package/cjs/data/table/hooks/useTableDetailsPanel.d.ts +62 -0
  46. package/cjs/data/table/hooks/{useTableExpansion.js → useTableDetailsPanel.js} +21 -20
  47. package/cjs/data/table/hooks/useTableDetailsPanel.js.map +1 -0
  48. package/cjs/data/table/hooks/useTableItems.d.ts +14 -17
  49. package/cjs/data/table/hooks/useTableItems.js +17 -16
  50. package/cjs/data/table/hooks/useTableItems.js.map +1 -1
  51. package/cjs/data/table/hooks/useTableKeyboardNav.js +5 -1
  52. package/cjs/data/table/hooks/useTableKeyboardNav.js.map +1 -1
  53. package/cjs/data/table/hooks/useTableSelection.d.ts +4 -2
  54. package/cjs/data/table/hooks/useTableSelection.js +6 -1
  55. package/cjs/data/table/hooks/useTableSelection.js.map +1 -1
  56. package/cjs/data/table/index.d.ts +1 -2
  57. package/cjs/data/table/index.js +22 -12
  58. package/cjs/data/table/index.js.map +1 -1
  59. package/cjs/data/table/root/DataTable.types.d.ts +7 -9
  60. package/cjs/data/table/root/DataTableRoot.context.d.ts +5 -1
  61. package/cjs/data/table/root/DataTableRoot.context.js.map +1 -1
  62. package/cjs/data/table/root/DataTableRoot.d.ts +79 -115
  63. package/cjs/data/table/root/DataTableRoot.js +163 -38
  64. package/cjs/data/table/root/DataTableRoot.js.map +1 -1
  65. package/cjs/data/table/root/DataTableRoot.legacy.d.ts +177 -0
  66. package/cjs/data/table/root/DataTableRoot.legacy.js +104 -0
  67. package/cjs/data/table/root/DataTableRoot.legacy.js.map +1 -0
  68. package/cjs/data/table/sub-row-toggle/DataTableSubRowToggle.d.ts +6 -0
  69. package/cjs/data/table/sub-row-toggle/DataTableSubRowToggle.js +21 -0
  70. package/cjs/data/table/sub-row-toggle/DataTableSubRowToggle.js.map +1 -0
  71. package/cjs/data/table/tr/DataTableTr.js +11 -11
  72. package/cjs/data/table/tr/DataTableTr.js.map +1 -1
  73. package/cjs/utils/components/dismissablelayer/DismissableLayer.js +1 -1
  74. package/cjs/utils/components/dismissablelayer/DismissableLayer.js.map +1 -1
  75. package/cjs/utils/components/floating/Floating.d.ts +16 -1
  76. package/cjs/utils/components/floating/Floating.js +50 -13
  77. package/cjs/utils/components/floating/Floating.js.map +1 -1
  78. package/cjs/utils/components/floating-menu/Menu.js +1 -1
  79. package/cjs/utils/components/floating-menu/Menu.js.map +1 -1
  80. package/cjs/utils/helpers/create-strict-context.js +1 -1
  81. package/cjs/utils/helpers/create-strict-context.js.map +1 -1
  82. package/cjs/utils/hooks/useControllableState.d.ts +5 -5
  83. package/cjs/utils/hooks/useControllableState.js.map +1 -1
  84. package/cjs/utils/hooks/useValueAsRef.js +1 -1
  85. package/cjs/utils/hooks/useValueAsRef.js.map +1 -1
  86. package/cjs/utils-external/hooks/useId.js +1 -1
  87. package/cjs/utils-external/hooks/useId.js.map +1 -1
  88. package/esm/action-menu/ActionMenu.js +1 -1
  89. package/esm/action-menu/ActionMenu.js.map +1 -1
  90. package/esm/data/drag-and-drop/drag-handler/DragAndDropDragHandler.js +11 -12
  91. package/esm/data/drag-and-drop/drag-handler/DragAndDropDragHandler.js.map +1 -1
  92. package/esm/data/drag-and-drop/root/DragAndDrop.context.d.ts +4 -2
  93. package/esm/data/drag-and-drop/root/DragAndDrop.context.js.map +1 -1
  94. package/esm/data/drag-and-drop/root/DragAndDropRoot.d.ts +5 -5
  95. package/esm/data/drag-and-drop/root/DragAndDropRoot.js +49 -28
  96. package/esm/data/drag-and-drop/root/DragAndDropRoot.js.map +1 -1
  97. package/esm/data/drag-and-drop/types.d.ts +0 -4
  98. package/esm/data/{drag-and-drop-old/drag-handler/DataDragAndDropDragHandler.d.ts → drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.d.ts} +3 -3
  99. package/esm/data/{drag-and-drop-old/drag-handler/DataDragAndDropDragHandler.js → drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js} +4 -4
  100. package/esm/data/drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.js.map +1 -0
  101. package/esm/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.d.ts +27 -0
  102. package/esm/data/{drag-and-drop-old/item/DataDragAndDropItem.js → drag-and-drop-legacy/item/DragAndDropItemLegacy.js} +11 -11
  103. package/esm/data/drag-and-drop-legacy/item/DragAndDropItemLegacy.js.map +1 -0
  104. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.d.ts +5 -0
  105. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js +3 -0
  106. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacy.context.js.map +1 -0
  107. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.d.ts +24 -0
  108. package/esm/data/{drag-and-drop-old/root/DataDragAndDropRoot.js → drag-and-drop-legacy/root/DragAndDropLegacyRoot.js} +8 -8
  109. package/esm/data/drag-and-drop-legacy/root/DragAndDropLegacyRoot.js.map +1 -0
  110. package/esm/data/stories/Data.test-data.d.ts +24 -0
  111. package/esm/data/stories/Data.test-data.js +1606 -0
  112. package/esm/data/stories/Data.test-data.js.map +1 -0
  113. package/esm/data/table/column-header/DataTableColumnHeader.d.ts +4 -1
  114. package/esm/data/table/column-header/DataTableColumnHeader.js +4 -4
  115. package/esm/data/table/column-header/DataTableColumnHeader.js.map +1 -1
  116. package/esm/data/table/column-header/useTableColumnResize.d.ts +21 -18
  117. package/esm/data/table/column-header/useTableColumnResize.js +7 -25
  118. package/esm/data/table/column-header/useTableColumnResize.js.map +1 -1
  119. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.d.ts +6 -0
  120. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.js +27 -0
  121. package/esm/data/table/details-panel-row/DataTableDetailsPanelRow.js.map +1 -0
  122. package/esm/data/table/helpers/collectTableRowEntries.d.ts +9 -7
  123. package/esm/data/table/helpers/collectTableRowEntries.js +21 -14
  124. package/esm/data/table/helpers/collectTableRowEntries.js.map +1 -1
  125. package/esm/data/table/helpers/table-focus.d.ts +0 -3
  126. package/esm/data/table/helpers/table-focus.js +38 -8
  127. package/esm/data/table/helpers/table-focus.js.map +1 -1
  128. package/esm/data/table/hooks/useColumnOptions.js +18 -5
  129. package/esm/data/table/hooks/useColumnOptions.js.map +1 -1
  130. package/esm/data/table/hooks/useGridCache.js +2 -2
  131. package/esm/data/table/hooks/useGridCache.js.map +1 -1
  132. package/esm/data/table/hooks/useTableDetailsPanel.d.ts +62 -0
  133. package/esm/data/table/hooks/{useTableExpansion.js → useTableDetailsPanel.js} +18 -17
  134. package/esm/data/table/hooks/useTableDetailsPanel.js.map +1 -0
  135. package/esm/data/table/hooks/useTableItems.d.ts +14 -17
  136. package/esm/data/table/hooks/useTableItems.js +17 -16
  137. package/esm/data/table/hooks/useTableItems.js.map +1 -1
  138. package/esm/data/table/hooks/useTableKeyboardNav.js +6 -2
  139. package/esm/data/table/hooks/useTableKeyboardNav.js.map +1 -1
  140. package/esm/data/table/hooks/useTableSelection.d.ts +4 -2
  141. package/esm/data/table/hooks/useTableSelection.js +6 -1
  142. package/esm/data/table/hooks/useTableSelection.js.map +1 -1
  143. package/esm/data/table/index.d.ts +1 -2
  144. package/esm/data/table/index.js +21 -1
  145. package/esm/data/table/index.js.map +1 -1
  146. package/esm/data/table/root/DataTable.types.d.ts +7 -9
  147. package/esm/data/table/root/DataTableRoot.context.d.ts +5 -1
  148. package/esm/data/table/root/DataTableRoot.context.js.map +1 -1
  149. package/esm/data/table/root/DataTableRoot.d.ts +79 -115
  150. package/esm/data/table/root/DataTableRoot.js +170 -36
  151. package/esm/data/table/root/DataTableRoot.js.map +1 -1
  152. package/esm/data/table/root/DataTableRoot.legacy.d.ts +177 -0
  153. package/esm/data/table/root/DataTableRoot.legacy.js +59 -0
  154. package/esm/data/table/root/DataTableRoot.legacy.js.map +1 -0
  155. package/esm/data/table/sub-row-toggle/DataTableSubRowToggle.d.ts +6 -0
  156. package/esm/data/table/sub-row-toggle/DataTableSubRowToggle.js +16 -0
  157. package/esm/data/table/sub-row-toggle/DataTableSubRowToggle.js.map +1 -0
  158. package/esm/data/table/tr/DataTableTr.js +11 -11
  159. package/esm/data/table/tr/DataTableTr.js.map +1 -1
  160. package/esm/utils/components/dismissablelayer/DismissableLayer.js +1 -1
  161. package/esm/utils/components/dismissablelayer/DismissableLayer.js.map +1 -1
  162. package/esm/utils/components/floating/Floating.d.ts +16 -1
  163. package/esm/utils/components/floating/Floating.js +48 -13
  164. package/esm/utils/components/floating/Floating.js.map +1 -1
  165. package/esm/utils/components/floating-menu/Menu.js +2 -2
  166. package/esm/utils/components/floating-menu/Menu.js.map +1 -1
  167. package/esm/utils/helpers/create-strict-context.js +1 -1
  168. package/esm/utils/helpers/create-strict-context.js.map +1 -1
  169. package/esm/utils/hooks/useControllableState.d.ts +5 -5
  170. package/esm/utils/hooks/useControllableState.js.map +1 -1
  171. package/esm/utils/hooks/useValueAsRef.js +1 -1
  172. package/esm/utils/hooks/useValueAsRef.js.map +1 -1
  173. package/esm/utils-external/hooks/useId.js +1 -1
  174. package/esm/utils-external/hooks/useId.js.map +1 -1
  175. package/package.json +8 -7
  176. package/src/action-menu/ActionMenu.tsx +1 -1
  177. package/src/data/drag-and-drop/drag-handler/DragAndDropDragHandler.tsx +11 -16
  178. package/src/data/drag-and-drop/root/DragAndDrop.context.tsx +4 -2
  179. package/src/data/drag-and-drop/root/DragAndDropRoot.tsx +85 -40
  180. package/src/data/drag-and-drop/types.ts +0 -5
  181. package/src/data/{drag-and-drop-old/drag-handler/DataDragAndDropDragHandler.tsx → drag-and-drop-legacy/drag-handler/DragAndDropDragHandlerLegacy.tsx} +5 -5
  182. package/src/data/{drag-and-drop-old/item/DataDragAndDropItem.tsx → drag-and-drop-legacy/item/DragAndDropItemLegacy.tsx} +13 -13
  183. package/src/data/{drag-and-drop-old/root/DataDragAndDrop.context.tsx → drag-and-drop-legacy/root/DragAndDropLegacy.context.tsx} +3 -3
  184. package/src/data/{drag-and-drop-old/root/DataDragAndDropRoot.tsx → drag-and-drop-legacy/root/DragAndDropLegacyRoot.tsx} +19 -21
  185. package/src/data/stories/Data.test-data.tsx +1702 -0
  186. package/src/data/table/column-header/DataTableColumnHeader.tsx +8 -6
  187. package/src/data/table/column-header/useTableColumnResize.ts +29 -44
  188. package/src/data/table/details-panel-row/DataTableDetailsPanelRow.tsx +57 -0
  189. package/src/data/table/helpers/collectTableRowEntries.ts +36 -30
  190. package/src/data/table/helpers/table-focus.ts +63 -9
  191. package/src/data/table/hooks/__tests__/useTableItems.test.ts +58 -12
  192. package/src/data/table/hooks/__tests__/useTableSelection.test.ts +57 -44
  193. package/src/data/table/hooks/useColumnOptions.ts +19 -5
  194. package/src/data/table/hooks/useGridCache.ts +3 -2
  195. package/src/data/table/hooks/useTableDetailsPanel.tsx +185 -0
  196. package/src/data/table/hooks/useTableItems.ts +44 -52
  197. package/src/data/table/hooks/useTableKeyboardNav.ts +6 -2
  198. package/src/data/table/hooks/useTableSelection.ts +17 -6
  199. package/src/data/table/index.tsx +5 -3
  200. package/src/data/table/root/DataTable.types.ts +20 -9
  201. package/src/data/table/root/DataTableRoot.context.ts +5 -1
  202. package/src/data/table/root/DataTableRoot.legacy.tsx +297 -0
  203. package/src/data/table/root/DataTableRoot.tsx +484 -219
  204. package/src/data/table/root/agent-feature-gap.md +96 -0
  205. package/src/data/table/sub-row-toggle/DataTableSubRowToggle.tsx +39 -0
  206. package/src/data/table/tr/DataTableTr.tsx +14 -13
  207. package/src/utils/components/dismissablelayer/DismissableLayer.tsx +1 -1
  208. package/src/utils/components/floating/Floating.tsx +56 -13
  209. package/src/utils/components/floating-menu/Menu.tsx +4 -1
  210. package/src/utils/helpers/create-strict-context.tsx +1 -1
  211. package/src/utils/hooks/useControllableState.ts +11 -8
  212. package/src/utils/hooks/useValueAsRef.ts +1 -1
  213. package/src/utils-external/hooks/useId.ts +1 -1
  214. package/cjs/data/drag-and-drop-old/drag-handler/DataDragAndDropDragHandler.js.map +0 -1
  215. package/cjs/data/drag-and-drop-old/item/DataDragAndDropItem.d.ts +0 -27
  216. package/cjs/data/drag-and-drop-old/item/DataDragAndDropItem.js.map +0 -1
  217. package/cjs/data/drag-and-drop-old/root/DataDragAndDrop.context.d.ts +0 -5
  218. package/cjs/data/drag-and-drop-old/root/DataDragAndDrop.context.js +0 -6
  219. package/cjs/data/drag-and-drop-old/root/DataDragAndDrop.context.js.map +0 -1
  220. package/cjs/data/drag-and-drop-old/root/DataDragAndDropRoot.d.ts +0 -24
  221. package/cjs/data/drag-and-drop-old/root/DataDragAndDropRoot.js.map +0 -1
  222. package/cjs/data/table/hooks/useTableExpansion.d.ts +0 -27
  223. package/cjs/data/table/hooks/useTableExpansion.js.map +0 -1
  224. package/cjs/data/table/root/DataTableAuto.d.ts +0 -182
  225. package/cjs/data/table/root/DataTableAuto.js +0 -206
  226. package/cjs/data/table/root/DataTableAuto.js.map +0 -1
  227. package/esm/data/drag-and-drop-old/drag-handler/DataDragAndDropDragHandler.js.map +0 -1
  228. package/esm/data/drag-and-drop-old/item/DataDragAndDropItem.d.ts +0 -27
  229. package/esm/data/drag-and-drop-old/item/DataDragAndDropItem.js.map +0 -1
  230. package/esm/data/drag-and-drop-old/root/DataDragAndDrop.context.d.ts +0 -5
  231. package/esm/data/drag-and-drop-old/root/DataDragAndDrop.context.js +0 -3
  232. package/esm/data/drag-and-drop-old/root/DataDragAndDrop.context.js.map +0 -1
  233. package/esm/data/drag-and-drop-old/root/DataDragAndDropRoot.d.ts +0 -24
  234. package/esm/data/drag-and-drop-old/root/DataDragAndDropRoot.js.map +0 -1
  235. package/esm/data/table/hooks/useTableExpansion.d.ts +0 -27
  236. package/esm/data/table/hooks/useTableExpansion.js.map +0 -1
  237. package/esm/data/table/root/DataTableAuto.d.ts +0 -182
  238. package/esm/data/table/root/DataTableAuto.js +0 -170
  239. package/esm/data/table/root/DataTableAuto.js.map +0 -1
  240. package/src/data/table/hooks/useTableExpansion.tsx +0 -146
  241. package/src/data/table/root/DataTableAuto.test.tsx +0 -244
  242. package/src/data/table/root/DataTableAuto.tsx +0 -612
@@ -42,7 +42,7 @@ describe("useTableSelection", () => {
42
42
  test("returns empty selectedKeys and no prop getters", () => {
43
43
  const { result } = renderHook(() =>
44
44
  useTableSelection({
45
- selectionMode: "none",
45
+ selection: { selectionMode: "none" },
46
46
  visibleRowIds,
47
47
  }),
48
48
  );
@@ -56,7 +56,7 @@ describe("useTableSelection", () => {
56
56
  test("returns getRowRadioProps", () => {
57
57
  const { result } = renderHook(() =>
58
58
  useTableSelection({
59
- selectionMode: "single",
59
+ selection: { selectionMode: "single" },
60
60
  visibleRowIds,
61
61
  }),
62
62
  );
@@ -69,9 +69,8 @@ describe("useTableSelection", () => {
69
69
  const onChange = vi.fn();
70
70
  const { result } = renderHook(() =>
71
71
  useTableSelection({
72
- selectionMode: "single",
72
+ selection: { selectionMode: "single", onSelectionChange: onChange },
73
73
  visibleRowIds,
74
- onSelectionChange: onChange,
75
74
  }),
76
75
  );
77
76
 
@@ -88,9 +87,8 @@ describe("useTableSelection", () => {
88
87
  test("toggling the same row keeps it selected", () => {
89
88
  const { result } = renderHook(() =>
90
89
  useTableSelection({
91
- selectionMode: "single",
90
+ selection: { selectionMode: "single", defaultSelectedKeys: ["a"] },
92
91
  visibleRowIds,
93
- defaultSelectedKeys: ["a"],
94
92
  }),
95
93
  );
96
94
 
@@ -106,9 +104,8 @@ describe("useTableSelection", () => {
106
104
  test("selecting a new row replaces the previous", () => {
107
105
  const { result } = renderHook(() =>
108
106
  useTableSelection({
109
- selectionMode: "single",
107
+ selection: { selectionMode: "single", defaultSelectedKeys: ["a"] },
110
108
  visibleRowIds,
111
- defaultSelectedKeys: ["a"],
112
109
  }),
113
110
  );
114
111
 
@@ -124,9 +121,8 @@ describe("useTableSelection", () => {
124
121
  test("disabled rows have disabled prop", () => {
125
122
  const { result } = renderHook(() =>
126
123
  useTableSelection({
127
- selectionMode: "single",
124
+ selection: { selectionMode: "single", disabledSelectionKeys: ["b"] },
128
125
  visibleRowIds,
129
- disabledSelectionKeys: ["b"],
130
126
  }),
131
127
  );
132
128
 
@@ -138,9 +134,8 @@ describe("useTableSelection", () => {
138
134
  const { result, rerender } = renderHook(
139
135
  ({ selectedKeys }) =>
140
136
  useTableSelection({
141
- selectionMode: "single",
137
+ selection: { selectionMode: "single", selectedKeys },
142
138
  visibleRowIds,
143
- selectedKeys,
144
139
  }),
145
140
  { initialProps: { selectedKeys: ["a"] as (string | number)[] } },
146
141
  );
@@ -156,7 +151,7 @@ describe("useTableSelection", () => {
156
151
  test("returns getTheadCheckboxProps and getRowCheckboxProps", () => {
157
152
  const { result } = renderHook(() =>
158
153
  useTableSelection({
159
- selectionMode: "multiple",
154
+ selection: { selectionMode: "multiple" },
160
155
  visibleRowIds,
161
156
  }),
162
157
  );
@@ -169,7 +164,7 @@ describe("useTableSelection", () => {
169
164
  test("selecting individual rows", () => {
170
165
  const { result } = renderHook(() =>
171
166
  useTableSelection({
172
- selectionMode: "multiple",
167
+ selection: { selectionMode: "multiple" },
173
168
  visibleRowIds,
174
169
  }),
175
170
  );
@@ -194,9 +189,11 @@ describe("useTableSelection", () => {
194
189
  test("deselecting a row", () => {
195
190
  const { result } = renderHook(() =>
196
191
  useTableSelection({
197
- selectionMode: "multiple",
192
+ selection: {
193
+ selectionMode: "multiple",
194
+ defaultSelectedKeys: ["a", "b"],
195
+ },
198
196
  visibleRowIds,
199
- defaultSelectedKeys: ["a", "b"],
200
197
  }),
201
198
  );
202
199
 
@@ -212,7 +209,7 @@ describe("useTableSelection", () => {
212
209
  test("select all via thead checkbox", () => {
213
210
  const { result } = renderHook(() =>
214
211
  useTableSelection({
215
- selectionMode: "multiple",
212
+ selection: { selectionMode: "multiple" },
216
213
  visibleRowIds,
217
214
  }),
218
215
  );
@@ -229,7 +226,7 @@ describe("useTableSelection", () => {
229
226
  test("select all via thead includes hidden descendants for visible parents", () => {
230
227
  const { result } = renderHook(() =>
231
228
  useTableSelection({
232
- selectionMode: "multiple",
229
+ selection: { selectionMode: "multiple" },
233
230
  visibleRowIds: ["a"],
234
231
  childRowIdsById,
235
232
  }),
@@ -247,9 +244,11 @@ describe("useTableSelection", () => {
247
244
  test("deselect all when all are selected", () => {
248
245
  const { result } = renderHook(() =>
249
246
  useTableSelection({
250
- selectionMode: "multiple",
247
+ selection: {
248
+ selectionMode: "multiple",
249
+ defaultSelectedKeys: ["a", "b", "c"],
250
+ },
251
251
  visibleRowIds,
252
- defaultSelectedKeys: ["a", "b", "c"],
253
252
  }),
254
253
  );
255
254
 
@@ -265,10 +264,12 @@ describe("useTableSelection", () => {
265
264
  test("deselect all clears hidden descendants for visible parents but preserves unrelated keys", () => {
266
265
  const { result } = renderHook(() =>
267
266
  useTableSelection({
268
- selectionMode: "multiple",
267
+ selection: {
268
+ selectionMode: "multiple",
269
+ defaultSelectedKeys: ["a", "a1", "a2", "a2a", "external"],
270
+ },
269
271
  visibleRowIds: ["a"],
270
272
  childRowIdsById,
271
- defaultSelectedKeys: ["a", "a1", "a2", "a2a", "external"],
272
273
  }),
273
274
  );
274
275
 
@@ -284,9 +285,11 @@ describe("useTableSelection", () => {
284
285
  test("select all skips disabled keys", () => {
285
286
  const { result } = renderHook(() =>
286
287
  useTableSelection({
287
- selectionMode: "multiple",
288
+ selection: {
289
+ selectionMode: "multiple",
290
+ disabledSelectionKeys: ["b"],
291
+ },
288
292
  visibleRowIds,
289
- disabledSelectionKeys: ["b"],
290
293
  }),
291
294
  );
292
295
 
@@ -302,10 +305,12 @@ describe("useTableSelection", () => {
302
305
  test("deselect all preserves disabled-but-selected rows", () => {
303
306
  const { result } = renderHook(() =>
304
307
  useTableSelection({
305
- selectionMode: "multiple",
308
+ selection: {
309
+ selectionMode: "multiple",
310
+ defaultSelectedKeys: ["a", "b", "c"],
311
+ disabledSelectionKeys: ["b"],
312
+ },
306
313
  visibleRowIds,
307
- defaultSelectedKeys: ["a", "b", "c"],
308
- disabledSelectionKeys: ["b"],
309
314
  }),
310
315
  );
311
316
 
@@ -321,9 +326,8 @@ describe("useTableSelection", () => {
321
326
  test("thead checkbox shows indeterminate when partially selected", () => {
322
327
  const { result } = renderHook(() =>
323
328
  useTableSelection({
324
- selectionMode: "multiple",
329
+ selection: { selectionMode: "multiple", defaultSelectedKeys: ["a"] },
325
330
  visibleRowIds,
326
- defaultSelectedKeys: ["a"],
327
331
  }),
328
332
  );
329
333
 
@@ -335,9 +339,11 @@ describe("useTableSelection", () => {
335
339
  test("thead checkbox shows checked when all selected", () => {
336
340
  const { result } = renderHook(() =>
337
341
  useTableSelection({
338
- selectionMode: "multiple",
342
+ selection: {
343
+ selectionMode: "multiple",
344
+ defaultSelectedKeys: ["a", "b", "c"],
345
+ },
339
346
  visibleRowIds,
340
- defaultSelectedKeys: ["a", "b", "c"],
341
347
  }),
342
348
  );
343
349
 
@@ -349,10 +355,12 @@ describe("useTableSelection", () => {
349
355
  test("thead checkbox shows checked when all selectable rows are selected", () => {
350
356
  const { result } = renderHook(() =>
351
357
  useTableSelection({
352
- selectionMode: "multiple",
358
+ selection: {
359
+ selectionMode: "multiple",
360
+ defaultSelectedKeys: ["a", "c"],
361
+ disabledSelectionKeys: ["b"],
362
+ },
353
363
  visibleRowIds,
354
- defaultSelectedKeys: ["a", "c"],
355
- disabledSelectionKeys: ["b"],
356
364
  }),
357
365
  );
358
366
 
@@ -364,9 +372,11 @@ describe("useTableSelection", () => {
364
372
  test("deselecting one row when all rows are selected", () => {
365
373
  const { result } = renderHook(() =>
366
374
  useTableSelection({
367
- selectionMode: "multiple",
375
+ selection: {
376
+ selectionMode: "multiple",
377
+ defaultSelectedKeys: ["a", "b", "c"],
378
+ },
368
379
  visibleRowIds,
369
- defaultSelectedKeys: ["a", "b", "c"],
370
380
  }),
371
381
  );
372
382
 
@@ -382,9 +392,11 @@ describe("useTableSelection", () => {
382
392
  test("disabled rows have disabled prop", () => {
383
393
  const { result } = renderHook(() =>
384
394
  useTableSelection({
385
- selectionMode: "multiple",
395
+ selection: {
396
+ selectionMode: "multiple",
397
+ disabledSelectionKeys: ["b"],
398
+ },
386
399
  visibleRowIds,
387
- disabledSelectionKeys: ["b"],
388
400
  }),
389
401
  );
390
402
 
@@ -395,9 +407,11 @@ describe("useTableSelection", () => {
395
407
  test("thead checkbox disabled when all rows disabled", () => {
396
408
  const { result } = renderHook(() =>
397
409
  useTableSelection({
398
- selectionMode: "multiple",
410
+ selection: {
411
+ selectionMode: "multiple",
412
+ disabledSelectionKeys: ["a", "b", "c"],
413
+ },
399
414
  visibleRowIds,
400
- disabledSelectionKeys: ["a", "b", "c"],
401
415
  }),
402
416
  );
403
417
 
@@ -407,10 +421,9 @@ describe("useTableSelection", () => {
407
421
  test("parent rows show indeterminate when visible descendants are partially selected", () => {
408
422
  const { result } = renderHook(() =>
409
423
  useTableSelection({
410
- selectionMode: "multiple",
424
+ selection: { selectionMode: "multiple", defaultSelectedKeys: ["a1"] },
411
425
  visibleRowIds: ["a", "a1", "a2"],
412
426
  childRowIdsById,
413
- defaultSelectedKeys: ["a1"],
414
427
  }),
415
428
  );
416
429
 
@@ -423,7 +436,7 @@ describe("useTableSelection", () => {
423
436
  test("toggling a parent row selects and deselects its descendants", () => {
424
437
  const { result } = renderHook(() =>
425
438
  useTableSelection({
426
- selectionMode: "multiple",
439
+ selection: { selectionMode: "multiple" },
427
440
  visibleRowIds: ["a", "a1", "a2"],
428
441
  childRowIdsById,
429
442
  }),
@@ -449,7 +462,7 @@ describe("useTableSelection", () => {
449
462
  test("toggling a collapsed parent selects and deselects hidden descendants", () => {
450
463
  const { result } = renderHook(() =>
451
464
  useTableSelection({
452
- selectionMode: "multiple",
465
+ selection: { selectionMode: "multiple" },
453
466
  visibleRowIds: ["a"],
454
467
  childRowIdsById,
455
468
  }),
@@ -1,3 +1,4 @@
1
+ import { useMemo } from "react";
1
2
  import type {
2
3
  ColumnDefinition,
3
4
  ColumnDefinitions,
@@ -28,19 +29,32 @@ function useColumnOptions<T>(
28
29
 
29
30
  const hasSelection = selectionMode !== "none";
30
31
 
31
- return {
32
- stickySelection: selectionMode !== "none" && stickyColumns?.first === "1",
33
- columns: columnDefinitions.map((colDef, index) => {
32
+ const columns = useMemo(() => {
33
+ return columnDefinitions.map((colDef, index) => {
34
34
  const isFirstSticky =
35
35
  stickyColumns?.first === "1" && index === 0 && !hasSelection;
36
36
  const isLastSticky =
37
37
  stickyColumns?.last === "1" && index === columnDefinitions.length - 1;
38
38
 
39
39
  return {
40
- isSticky: isFirstSticky ? "start" : isLastSticky ? "end" : false,
40
+ isSticky: isFirstSticky
41
+ ? ("start" as const)
42
+ : isLastSticky
43
+ ? ("end" as const)
44
+ : (false as const),
41
45
  colDef,
42
46
  };
43
- }),
47
+ });
48
+ }, [
49
+ columnDefinitions,
50
+ hasSelection,
51
+ stickyColumns?.first,
52
+ stickyColumns?.last,
53
+ ]);
54
+
55
+ return {
56
+ stickySelection: selectionMode !== "none" && stickyColumns?.first === "1",
57
+ columns,
44
58
  };
45
59
  }
46
60
 
@@ -14,7 +14,7 @@ function useGridCache(tableRef: HTMLTableElement | null, enabled: boolean) {
14
14
  });
15
15
 
16
16
  const [activeCell, setActiveCell] = useState<Element | null>(null);
17
- const activeCellRef = useValueAsRef(activeCell).current;
17
+ const activeCellRef = useValueAsRef(activeCell);
18
18
  const observerRef = useRef<MutationObserver | null>(null);
19
19
 
20
20
  useEffect(() => {
@@ -24,7 +24,8 @@ function useGridCache(tableRef: HTMLTableElement | null, enabled: boolean) {
24
24
 
25
25
  observerRef.current = new MutationObserver(() => {
26
26
  gridCacheRef.current.dirty = true;
27
- if (activeCellRef && !activeCellRef.isConnected) {
27
+
28
+ if (activeCellRef.current && !activeCellRef.current.isConnected) {
28
29
  setActiveCell(null);
29
30
  }
30
31
  });
@@ -0,0 +1,185 @@
1
+ import React, { useCallback } from "react";
2
+ import { createStrictContext } from "../../../utils/helpers";
3
+ import { useControllableState } from "../../../utils/hooks";
4
+ import { useTableItemsContext } from "./useTableItems";
5
+
6
+ type DetailsPanelProps<T> = {
7
+ /**
8
+ * Renders a details panel below the row when expanded.
9
+ * When provided, an expand toggle column is added automatically.
10
+ */
11
+ getContent?: (rowData: T) => React.ReactNode;
12
+ /**
13
+ * Determines whether a row can be expanded to show details panel content.
14
+ * @default () => true
15
+ */
16
+ isRowExpandable?: (rowData: T) => boolean;
17
+ /**
18
+ * Controlled list of expanded row IDs.
19
+ * Use with `onDetailsPanelChange` for controlled usage, or `defaultDetailsPanelRowIds` for uncontrolled.
20
+ */
21
+ expandedRowIds?: (string | number)[];
22
+ /**
23
+ * Initial list of expanded row IDs for uncontrolled usage.
24
+ * @default []
25
+ */
26
+ defaultExpandedRowIds?: (string | number)[];
27
+ /**
28
+ * Called when the list of expanded row IDs changes.
29
+ *
30
+ *
31
+ * TODO:
32
+ * - Docs: This pattern is called "Master / Detail" in general terms
33
+ */
34
+ onExpandedRowIdsChange?: (ids: (string | number)[]) => void;
35
+ /**
36
+ * Returns the height (in px) or `"auto"` for a row's details panel.
37
+ * When a number is returned, the panel scrolls within that fixed height.
38
+ * @default "auto"
39
+ */
40
+ getHeight?: (rowData: T) => number | "auto";
41
+ /**
42
+ * Shows an expand-all toggle button in the expand column header.
43
+ * @default false
44
+ */
45
+ showExpandAll?: boolean;
46
+ };
47
+
48
+ type DataTableDetailsPanelContextT = {
49
+ isExpanded: (id: string | number) => boolean;
50
+ isDetailsPanelExpandable: (id: string | number) => boolean;
51
+ toggleExpansion: (id: string | number) => void;
52
+ toggleAll: () => void;
53
+ isAllExpanded: boolean;
54
+ getDetailsPanelContent?: (row: unknown) => React.ReactNode;
55
+ getDetailsPanelHeight?: (row: unknown) => number | "auto";
56
+ showExpandAll: boolean;
57
+ enableDetailsPanel: boolean;
58
+ };
59
+
60
+ const {
61
+ Provider: DataTableDetailsPanelContextProvider,
62
+ useContext: useDataTableDetailsPanel,
63
+ } = createStrictContext<DataTableDetailsPanelContextT>({
64
+ name: "DataTableDetailsPanelContext",
65
+ errorMessage:
66
+ "useDataTableDetailsPanel must be used within a DataTableDetailsPanelProvider.",
67
+ });
68
+
69
+ function DataTableDetailsPanelProvider<T>({
70
+ children,
71
+ detailsPanel = {},
72
+ }: { detailsPanel?: DetailsPanelProps<T> } & { children: React.ReactNode }) {
73
+ const {
74
+ expandedRowIds,
75
+ defaultExpandedRowIds = [],
76
+ onExpandedRowIdsChange,
77
+ getContent,
78
+ isRowExpandable,
79
+ getHeight,
80
+ showExpandAll = false,
81
+ } = detailsPanel;
82
+
83
+ const [expandedIds, setExpandedIds] = useControllableState({
84
+ value: expandedRowIds,
85
+ defaultValue: defaultExpandedRowIds,
86
+ onChange: onExpandedRowIdsChange,
87
+ });
88
+
89
+ /* TODO: False is just fallback until auto and root is merged */
90
+ const tableItemsContext = useTableItemsContext(false);
91
+
92
+ const { itemDetails } = tableItemsContext ?? {
93
+ itemDetails: new Map<
94
+ string | number,
95
+ { rowData: T; id: string | number; level: number }
96
+ >(),
97
+ };
98
+
99
+ const expandableIds = React.useMemo(() => {
100
+ if (!getContent) {
101
+ return new Set<string | number>();
102
+ }
103
+
104
+ const ids = new Set<string | number>();
105
+
106
+ for (const { rowData, id, level } of itemDetails.values()) {
107
+ /* We only allow Master - Details pattern on top level rows */
108
+ if (level > 0) {
109
+ continue;
110
+ }
111
+
112
+ if (!isRowExpandable || isRowExpandable(rowData)) {
113
+ ids.add(id);
114
+ }
115
+ }
116
+
117
+ return ids;
118
+ }, [getContent, isRowExpandable, itemDetails]);
119
+
120
+ const isDetailsPanelExpandableById = useCallback(
121
+ (id: string | number) => expandableIds.has(id),
122
+ [expandableIds],
123
+ );
124
+
125
+ const isExpanded = useCallback(
126
+ (id: string | number) =>
127
+ isDetailsPanelExpandableById(id) && expandedIds.includes(id),
128
+ [expandedIds, isDetailsPanelExpandableById],
129
+ );
130
+
131
+ const toggleExpansion = useCallback(
132
+ (id: string | number) => {
133
+ if (!isDetailsPanelExpandableById(id)) {
134
+ return;
135
+ }
136
+
137
+ setExpandedIds((currentExpandedIds) =>
138
+ currentExpandedIds.includes(id)
139
+ ? currentExpandedIds.filter((expandedId) => expandedId !== id)
140
+ : [...currentExpandedIds, id],
141
+ );
142
+ },
143
+ [isDetailsPanelExpandableById, setExpandedIds],
144
+ );
145
+
146
+ const isAllExpanded =
147
+ expandableIds.size > 0 &&
148
+ Array.from(expandableIds).every((key) => expandedIds.includes(key));
149
+
150
+ const toggleAll = useCallback(() => {
151
+ setExpandedIds(isAllExpanded ? [] : Array.from(expandableIds));
152
+ }, [expandableIds, isAllExpanded, setExpandedIds]);
153
+
154
+ return (
155
+ <DataTableDetailsPanelContextProvider
156
+ isExpanded={isExpanded}
157
+ isDetailsPanelExpandable={isDetailsPanelExpandableById}
158
+ toggleExpansion={toggleExpansion}
159
+ toggleAll={toggleAll}
160
+ isAllExpanded={isAllExpanded}
161
+ getDetailsPanelContent={
162
+ getContent as ((row: unknown) => React.ReactNode) | undefined
163
+ }
164
+ getDetailsPanelHeight={
165
+ getHeight as ((row: unknown) => number | "auto") | undefined
166
+ }
167
+ showExpandAll={showExpandAll}
168
+ enableDetailsPanel={!!getContent}
169
+ >
170
+ {children}
171
+ </DataTableDetailsPanelContextProvider>
172
+ );
173
+ }
174
+
175
+ function getDataTableDetailsPanelId(tableId: string, rowId: string | number) {
176
+ return `${tableId}-expansion-${rowId}`;
177
+ }
178
+
179
+ export {
180
+ DataTableDetailsPanelProvider,
181
+ getDataTableDetailsPanelId,
182
+ useDataTableDetailsPanel,
183
+ };
184
+
185
+ export type { DetailsPanelProps };