@astryxdesign/core 0.1.7 → 0.1.8-canary.c5fa19b

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 (190) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/README.md +30 -19
  3. package/dist/Avatar/Avatar.d.ts +10 -5
  4. package/dist/Avatar/Avatar.d.ts.map +1 -1
  5. package/dist/Avatar/Avatar.js +12 -8
  6. package/dist/Avatar/AvatarSizeContext.d.ts +1 -1
  7. package/dist/Avatar/AvatarSizeContext.js +1 -1
  8. package/dist/Avatar/AvatarStatusDot.d.ts +2 -2
  9. package/dist/Avatar/AvatarStatusDot.js +2 -2
  10. package/dist/AvatarGroup/AvatarGroup.d.ts +2 -2
  11. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  12. package/dist/AvatarGroup/AvatarGroup.js +2 -2
  13. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
  14. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  15. package/dist/AvatarGroup/AvatarGroupOverflow.js +16 -14
  16. package/dist/Carousel/Carousel.d.ts +3 -2
  17. package/dist/Carousel/Carousel.d.ts.map +1 -1
  18. package/dist/Carousel/Carousel.js +32 -2
  19. package/dist/Chat/ChatMessage.d.ts +1 -1
  20. package/dist/Chat/ChatMessage.d.ts.map +1 -1
  21. package/dist/Chat/ChatMessage.js +1 -1
  22. package/dist/Citation/Citation.d.ts.map +1 -1
  23. package/dist/Citation/Citation.js +10 -4
  24. package/dist/Collapsible/Collapsible.d.ts +11 -1
  25. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  26. package/dist/Collapsible/Collapsible.js +36 -4
  27. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  28. package/dist/ContextMenu/ContextMenu.js +4 -3
  29. package/dist/ContextMenu/index.d.ts +3 -0
  30. package/dist/ContextMenu/index.d.ts.map +1 -1
  31. package/dist/ContextMenu/index.js +7 -1
  32. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  33. package/dist/DropdownMenu/DropdownMenu.js +8 -4
  34. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +89 -0
  35. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -0
  36. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +170 -0
  37. package/dist/DropdownMenu/DropdownMenuContext.d.ts +17 -1
  38. package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
  39. package/dist/DropdownMenu/DropdownMenuContext.js +18 -0
  40. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +69 -0
  41. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -0
  42. package/dist/DropdownMenu/DropdownMenuRadioGroup.js +70 -0
  43. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +69 -0
  44. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -0
  45. package/dist/DropdownMenu/DropdownMenuRadioItem.js +178 -0
  46. package/dist/DropdownMenu/index.d.ts +5 -1
  47. package/dist/DropdownMenu/index.d.ts.map +1 -1
  48. package/dist/DropdownMenu/index.js +10 -1
  49. package/dist/DropdownMenu/menuItemRoles.d.ts +13 -0
  50. package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -0
  51. package/dist/DropdownMenu/menuItemRoles.js +15 -0
  52. package/dist/Icon/Icon.d.ts +43 -13
  53. package/dist/Icon/Icon.d.ts.map +1 -1
  54. package/dist/Icon/Icon.js +62 -27
  55. package/dist/Outline/Outline.d.ts +69 -3
  56. package/dist/Outline/Outline.d.ts.map +1 -1
  57. package/dist/Outline/Outline.js +129 -26
  58. package/dist/Outline/useScrollSpy.d.ts +27 -7
  59. package/dist/Outline/useScrollSpy.d.ts.map +1 -1
  60. package/dist/Outline/useScrollSpy.js +202 -70
  61. package/dist/TabList/Tab.d.ts.map +1 -1
  62. package/dist/TabList/Tab.js +2 -2
  63. package/dist/TabList/TabList.d.ts.map +1 -1
  64. package/dist/TabList/TabList.js +2 -0
  65. package/dist/TabList/TabMenu.d.ts.map +1 -1
  66. package/dist/TabList/TabMenu.js +1 -1
  67. package/dist/Table/Table.d.ts +1 -1
  68. package/dist/Table/Table.js +1 -1
  69. package/dist/Table/index.d.ts +2 -0
  70. package/dist/Table/index.d.ts.map +1 -1
  71. package/dist/Table/index.js +1 -0
  72. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  73. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +24 -2
  74. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  75. package/dist/Table/plugins/sortable/useTableSortable.js +18 -7
  76. package/dist/Table/plugins/tree/index.d.ts +5 -0
  77. package/dist/Table/plugins/tree/index.d.ts.map +1 -0
  78. package/dist/Table/plugins/tree/index.js +4 -0
  79. package/dist/Table/plugins/tree/useTableTreeData.d.ts +38 -0
  80. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -0
  81. package/dist/Table/plugins/tree/useTableTreeData.js +358 -0
  82. package/dist/Table/plugins/tree/useTableTreeState.d.ts +51 -0
  83. package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -0
  84. package/dist/Table/plugins/tree/useTableTreeState.js +175 -0
  85. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  86. package/dist/Table/useBaseTablePlugins.js +6 -3
  87. package/dist/Toolbar/Toolbar.d.ts.map +1 -1
  88. package/dist/Toolbar/Toolbar.js +8 -1
  89. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  90. package/dist/TreeList/TreeListItem.js +5 -14
  91. package/dist/astryx.css +24 -4
  92. package/dist/astryx.umd.js +54 -54
  93. package/dist/astryx.umd.js.map +4 -4
  94. package/dist/theme/Theme.js +1 -1
  95. package/dist/theme/defineTheme.d.ts +1 -1
  96. package/dist/theme/defineTheme.js +1 -1
  97. package/dist/theme/hct.d.ts +0 -1
  98. package/dist/theme/hct.d.ts.map +1 -1
  99. package/dist/theme/hct.js +0 -3
  100. package/docs.mjs +32 -461
  101. package/locales/en.json +200 -172
  102. package/locales/pseudo.json +21 -0
  103. package/package.json +3 -1
  104. package/scripts/postinstall.mjs +93 -0
  105. package/src/Avatar/Avatar.doc.mjs +6 -6
  106. package/src/Avatar/Avatar.tsx +16 -11
  107. package/src/Avatar/AvatarSizeContext.ts +1 -1
  108. package/src/Avatar/AvatarStatusDot.tsx +2 -2
  109. package/src/AvatarGroup/AvatarGroup.doc.mjs +1 -1
  110. package/src/AvatarGroup/AvatarGroup.test.tsx +17 -3
  111. package/src/AvatarGroup/AvatarGroup.tsx +3 -3
  112. package/src/AvatarGroup/AvatarGroupOverflow.doc.mjs +4 -4
  113. package/src/AvatarGroup/AvatarGroupOverflow.tsx +21 -5
  114. package/src/Carousel/Carousel.doc.mjs +1 -0
  115. package/src/Carousel/Carousel.test.tsx +96 -1
  116. package/src/Carousel/Carousel.tsx +29 -2
  117. package/src/Chat/Chat.doc.mjs +1 -1
  118. package/src/Chat/ChatMessage.tsx +4 -2
  119. package/src/CheckboxInput/CheckboxInput.doc.mjs +1 -1
  120. package/src/Citation/Citation.test.tsx +51 -0
  121. package/src/Citation/Citation.tsx +8 -2
  122. package/src/Collapsible/Collapsible.doc.mjs +7 -0
  123. package/src/Collapsible/Collapsible.test.tsx +80 -0
  124. package/src/Collapsible/Collapsible.tsx +58 -5
  125. package/src/ContextMenu/ContextMenu.test.tsx +75 -1
  126. package/src/ContextMenu/ContextMenu.tsx +10 -5
  127. package/src/ContextMenu/index.ts +15 -0
  128. package/src/DropdownMenu/DropdownMenu.doc.mjs +23 -0
  129. package/src/DropdownMenu/DropdownMenu.tsx +11 -6
  130. package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +95 -0
  131. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +237 -0
  132. package/src/DropdownMenu/DropdownMenuContext.tsx +29 -1
  133. package/src/DropdownMenu/DropdownMenuItem.doc.mjs +7 -1
  134. package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +80 -0
  135. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +119 -0
  136. package/src/DropdownMenu/DropdownMenuRadioItem.doc.mjs +80 -0
  137. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +232 -0
  138. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +163 -0
  139. package/src/DropdownMenu/index.ts +23 -3
  140. package/src/DropdownMenu/menuItemRoles.ts +22 -0
  141. package/src/Field/Field.doc.mjs +1 -1
  142. package/src/Field/FieldLabel.doc.mjs +1 -1
  143. package/src/Icon/Icon.doc.mjs +12 -0
  144. package/src/Icon/Icon.test.tsx +142 -0
  145. package/src/Icon/Icon.tsx +98 -30
  146. package/src/Item/Item.doc.mjs +1 -1
  147. package/src/NumberInput/NumberInput.doc.mjs +2 -2
  148. package/src/Outline/Outline.doc.mjs +123 -3
  149. package/src/Outline/Outline.test.tsx +735 -0
  150. package/src/Outline/Outline.tsx +184 -33
  151. package/src/Outline/useScrollSpy.ts +248 -72
  152. package/src/Selector/SelectorOption.doc.mjs +1 -1
  153. package/src/SideNav/SideNavItem.doc.mjs +2 -2
  154. package/src/Switch/Switch.doc.mjs +1 -1
  155. package/src/TabList/Tab.tsx +5 -1
  156. package/src/TabList/TabList.doc.mjs +3 -3
  157. package/src/TabList/TabList.test.tsx +66 -0
  158. package/src/TabList/TabList.tsx +8 -0
  159. package/src/TabList/TabMenu.tsx +4 -1
  160. package/src/Table/Table.doc.mjs +2 -0
  161. package/src/Table/Table.tsx +1 -1
  162. package/src/Table/index.ts +7 -0
  163. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +90 -1
  164. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +37 -5
  165. package/src/Table/plugins/sortable/useTableSortable.test.tsx +95 -9
  166. package/src/Table/plugins/sortable/useTableSortable.tsx +23 -7
  167. package/src/Table/plugins/tree/index.ts +12 -0
  168. package/src/Table/plugins/tree/useTableTreeData-perf.test.tsx +163 -0
  169. package/src/Table/plugins/tree/useTableTreeData.test.tsx +594 -0
  170. package/src/Table/plugins/tree/useTableTreeData.tsx +495 -0
  171. package/src/Table/plugins/tree/useTableTreeState.test.tsx +636 -0
  172. package/src/Table/plugins/tree/useTableTreeState.tsx +253 -0
  173. package/src/Table/useBaseTablePlugins.ts +6 -2
  174. package/src/Table/useTableTreeData.doc.mjs +75 -0
  175. package/src/Table/useTableTreeState.doc.mjs +98 -0
  176. package/src/TextArea/TextArea.doc.mjs +1 -1
  177. package/src/TextInput/TextInput.doc.mjs +1 -1
  178. package/src/Toolbar/Toolbar.tsx +10 -3
  179. package/src/TreeList/TreeList.test.tsx +32 -1
  180. package/src/TreeList/TreeListItem.tsx +19 -10
  181. package/src/docs-script.test.mjs +18 -13
  182. package/src/postinstall.test.mjs +71 -0
  183. package/src/theme/Theme.doc.mjs +4 -4
  184. package/src/theme/Theme.tsx +1 -1
  185. package/src/theme/defineTheme.ts +1 -1
  186. package/src/theme/hct.ts +0 -4
  187. package/dist/TreeList/treeListItem.markers.stylex.d.ts +0 -16
  188. package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +0 -1
  189. package/dist/TreeList/treeListItem.markers.stylex.js +0 -22
  190. package/src/TreeList/treeListItem.markers.stylex.ts +0 -20
@@ -10,15 +10,38 @@
10
10
  *
11
11
  * Drives the active outline item from scroll position. On each scroll
12
12
  * (rAF-throttled) it reads live heading positions and marks the last heading
13
- * whose top has passed its activation line (its own scroll-margin-top, i.e.
14
- * where it lands when navigated to). This is stable — it never compares stale
15
- * cached positions — so the indicator moves monotonically instead of jumping.
16
- * Defaults to the first item at the top and the last item at the bottom so
17
- * short final sections still activate.
13
+ * whose top has passed its activation line. This is stable — it never compares
14
+ * stale cached positions — so the indicator moves monotonically instead of
15
+ * jumping. Defaults to the first item at the top and the last item at the
16
+ * bottom so short final sections still activate.
17
+ *
18
+ * The activation line and the scroll landing are the same number, computed once
19
+ * in `getRestingTop`: scroll-root top + `offset` (a fixed header overlaying the
20
+ * root) + the heading's own `scroll-margin-top`. A heading therefore activates
21
+ * exactly where navigating to it puts it. `offset` and `scroll-margin-top`
22
+ * compose — the header, then the breathing room below it — they do not
23
+ * duplicate each other.
24
+ *
25
+ * It also owns the single navigation path (`scrollTo`), shared by click and
26
+ * keyboard activation: it announces the jump, suppresses scroll-spy for the
27
+ * duration of the programmatic scroll (so the indicator doesn't chase it), and
28
+ * resolves when the scroll settles — via `scrollend` where supported, or a
29
+ * timeout fallback where it is not.
30
+ *
31
+ * The scroll root is the `scrollContainerRef` element when provided, otherwise
32
+ * the nearest scrollable ancestor of the outline, otherwise the viewport.
18
33
  *
19
34
  * SYNC: When modified, update /packages/core/src/Outline/Outline.tsx
20
35
  */
21
36
  import { useCallback, useEffect, useRef, useState } from 'react';
37
+ /**
38
+ * How long to wait for a programmatic smooth scroll to settle when the
39
+ * `scrollend` event never arrives — either because the browser does not
40
+ * support it (Safari at time of writing) or because the target was already in
41
+ * position, so no scroll happened at all and no events were emitted.
42
+ */
43
+ const SCROLL_SETTLE_TIMEOUT_MS = 1200;
44
+
22
45
  /** Keys that scroll the viewport — used to detect a manual scroll intent. */
23
46
  const SCROLL_KEYS = new Set(['ArrowUp', 'ArrowDown', 'PageUp', 'PageDown', 'Home', 'End', ' ', 'Spacebar']);
24
47
  function getScrollableAncestor(element) {
@@ -35,20 +58,69 @@ function getScrollableAncestor(element) {
35
58
  return null;
36
59
  }
37
60
 
61
+ /** The element's own `scroll-margin-top` in px (0 when unset). */
62
+ function getScrollMarginTop(element) {
63
+ return Number.parseFloat(window.getComputedStyle(element).scrollMarginTop) || 0;
64
+ }
65
+
66
+ /** The top of the scroll root in viewport coordinates (0 for the viewport). */
67
+ function getRootTop(scrollRoot) {
68
+ return scrollRoot != null ? scrollRoot.getBoundingClientRect().top : 0;
69
+ }
70
+
71
+ /**
72
+ * Where a heading comes to rest, in viewport coordinates: below the fixed
73
+ * header (`offset`) and below its own `scroll-margin-top` breathing room.
74
+ *
75
+ * This is the single source of truth shared by the activation line and the
76
+ * scroll landing — the two must agree, or a heading activates somewhere other
77
+ * than where navigating to it puts it.
78
+ */
79
+ function getRestingTop(target, scrollRoot, offset) {
80
+ return getRootTop(scrollRoot) + offset + getScrollMarginTop(target);
81
+ }
82
+
83
+ /**
84
+ * Bring `target` to rest at the top of the scroll root, below any fixed header.
85
+ *
86
+ * With no `offset`, this is the CSS-native path: `scrollIntoView` already
87
+ * honors the heading's `scroll-margin-top`, and it walks *every* scrollable
88
+ * ancestor, so the browser does it better than we can.
89
+ *
90
+ * An `offset` describes a fixed header overlaying the top of the scroll root —
91
+ * which the browser cannot know about, so `scrollIntoView` would park the
92
+ * heading underneath it, hidden. Compute the landing explicitly instead, from
93
+ * the same {@link getRestingTop} the activation line uses.
94
+ */
95
+ function scrollToTarget(target, scrollRoot, scrollTarget, offset) {
96
+ if (offset === 0) {
97
+ target.scrollIntoView({
98
+ behavior: 'smooth',
99
+ block: 'start'
100
+ });
101
+ return;
102
+ }
103
+ const delta = target.getBoundingClientRect().top - getRestingTop(target, scrollRoot, offset);
104
+ scrollTarget.scrollBy({
105
+ top: delta,
106
+ behavior: 'smooth'
107
+ });
108
+ }
109
+
38
110
  /**
39
111
  * Resolve the active heading id from current scroll position.
40
112
  *
41
- * A heading is "passed" once its top reaches its activation line — the scroll
42
- * root's top plus the heading's own scroll-margin-top. The active heading is
43
- * the last passed one (headings are in document order). When none have passed
44
- * (scrolled above the first), the first item is active; at the bottom, the
45
- * last item is active.
113
+ * A heading is "passed" once its top reaches its activation line — exactly
114
+ * where navigating to it would land it ({@link getRestingTop}): the scroll
115
+ * root's top, plus `offset` (a fixed header overlaying the scroll root), plus
116
+ * the heading's own scroll-margin-top. The active heading is the last passed
117
+ * one (headings are in document order). When none have passed (scrolled above
118
+ * the first), the first item is active; at the bottom, the last item is active.
46
119
  */
47
- function resolveActiveId(items, scrollRoot) {
120
+ function resolveActiveId(items, scrollRoot, offset) {
48
121
  if (items.length === 0) {
49
122
  return undefined;
50
123
  }
51
- const rootTop = scrollRoot != null ? scrollRoot.getBoundingClientRect().top : 0;
52
124
  const atBottom = scrollRoot != null ? scrollRoot.scrollTop + scrollRoot.clientHeight >= scrollRoot.scrollHeight - 2 : window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 2;
53
125
  if (atBottom) {
54
126
  return items[items.length - 1].id;
@@ -59,9 +131,10 @@ function resolveActiveId(items, scrollRoot) {
59
131
  if (element == null) {
60
132
  continue;
61
133
  }
134
+
135
+ // 1px of tolerance absorbs sub-pixel rounding after a scroll lands.
62
136
  const top = element.getBoundingClientRect().top;
63
- const marginTop = Number.parseFloat(window.getComputedStyle(element).scrollMarginTop) || 0;
64
- if (top <= rootTop + marginTop + 1) {
137
+ if (top <= getRestingTop(element, scrollRoot, offset) + 1) {
65
138
  activeId = item.id;
66
139
  } else {
67
140
  break;
@@ -73,17 +146,23 @@ export function useScrollSpy({
73
146
  activeId,
74
147
  items,
75
148
  onActiveIdChange,
76
- rootRef
149
+ rootRef,
150
+ offset = 0,
151
+ scrollContainerRef,
152
+ hasScrollOnClick = true,
153
+ onNavigateStart,
154
+ onNavigateEnd
77
155
  }) {
78
156
  const isControlled = activeId !== undefined;
79
157
  const [uncontrolledActiveId, setUncontrolledActiveId] = useState(items[0]?.id);
80
158
  const activeIdRef = useRef(activeId);
81
- // While true, scroll-spy ignores scroll updates because a click is driving a
82
- // programmatic scroll. Released when that scroll settles or the user scrolls.
159
+ // While true, scroll-spy ignores scroll updates because a navigation is
160
+ // driving a programmatic scroll. Released when it settles or the user scrolls.
83
161
  const suppressRef = useRef(false);
84
- const releaseSuppressionRef = useRef(null);
85
- // Latest scroll-position resolver, so the click handler can resume tracking
86
- // when the user scrolls during a programmatic scroll.
162
+ // The navigation currently in flight, if any.
163
+ const navigationRef = useRef(null);
164
+ // Latest scroll-position resolver, so a navigation can resume tracking when
165
+ // the user scrolls during the programmatic scroll.
87
166
  const syncRef = useRef(null);
88
167
  // Keep latest items/callback in refs so the scroll listener effect doesn't
89
168
  // re-subscribe on every render (items is a fresh array each render).
@@ -93,11 +172,20 @@ export function useScrollSpy({
93
172
  onActiveIdChangeRef.current = onActiveIdChange;
94
173
  const itemIds = items.map(item => item.id).join('\n');
95
174
  activeIdRef.current = isControlled ? activeId : uncontrolledActiveId;
175
+
176
+ /**
177
+ * The element whose scroll position drives the outline: the explicit
178
+ * container when scoped, else the nearest scrollable ancestor, else null
179
+ * (meaning the viewport).
180
+ */
181
+ const getScrollRoot = useCallback(() => {
182
+ return scrollContainerRef?.current ?? getScrollableAncestor(rootRef.current);
183
+ }, [rootRef, scrollContainerRef]);
96
184
  useEffect(() => {
97
185
  if (isControlled || typeof window === 'undefined') {
98
186
  return;
99
187
  }
100
- const scrollRoot = getScrollableAncestor(rootRef.current);
188
+ const scrollRoot = getScrollRoot();
101
189
  const scrollTarget = scrollRoot ?? window;
102
190
  let frame = 0;
103
191
  const update = () => {
@@ -105,7 +193,7 @@ export function useScrollSpy({
105
193
  if (suppressRef.current) {
106
194
  return;
107
195
  }
108
- const nextActiveId = resolveActiveId(itemsRef.current, scrollRoot);
196
+ const nextActiveId = resolveActiveId(itemsRef.current, scrollRoot, offset);
109
197
  if (nextActiveId != null && nextActiveId !== activeIdRef.current) {
110
198
  activeIdRef.current = nextActiveId;
111
199
  setUncontrolledActiveId(nextActiveId);
@@ -133,12 +221,12 @@ export function useScrollSpy({
133
221
  cancelAnimationFrame(frame);
134
222
  }
135
223
  };
136
- }, [isControlled, itemIds, rootRef]);
224
+ }, [isControlled, itemIds, offset, getScrollRoot]);
137
225
 
138
- // Tear down any pending suppression listeners when the Outline unmounts.
226
+ // Tear down any in-flight navigation's listeners when the Outline unmounts.
139
227
  useEffect(() => {
140
228
  return () => {
141
- releaseSuppressionRef.current?.();
229
+ navigationRef.current?.teardown();
142
230
  };
143
231
  }, []);
144
232
  const setActiveId = nextActiveId => {
@@ -147,68 +235,112 @@ export function useScrollSpy({
147
235
  }
148
236
  onActiveIdChange?.(nextActiveId);
149
237
  };
150
- const lockActiveId = useCallback(clickedId => {
151
- if (typeof window === 'undefined') {
152
- setUncontrolledActiveId(clickedId);
153
- activeIdRef.current = clickedId;
154
- onActiveIdChangeRef.current?.(clickedId);
155
- return;
238
+
239
+ // Defined in render (not memoized) so it always closes over the current props
240
+ // — it only ever runs from an event handler, never during render.
241
+ const scrollTo = id => {
242
+ const target = typeof document !== 'undefined' ? document.getElementById(id) : null;
243
+ if (target == null) {
244
+ return false;
156
245
  }
157
246
 
158
- // Freeze the indicator during the programmatic smooth scroll instead of
159
- // moving it immediately — it lands on the clicked item once the scroll
160
- // settles, so it doesn't chase the scroll through intervening sections.
161
- suppressRef.current = true;
162
- // Replace any in-flight handlers from a previous click.
163
- releaseSuppressionRef.current?.();
247
+ // A second navigation replaces the first: end the old one (balancing its
248
+ // onNavigateStart) without resuming tracking, since we are about to
249
+ // suppress it again anyway.
250
+ navigationRef.current?.supersede();
251
+ onNavigateStart?.(id);
252
+ if (isControlled) {
253
+ // The consumer owns the active state — notify only.
254
+ setActiveId(id);
255
+ } else {
256
+ // Freeze the indicator during the programmatic scroll instead of moving
257
+ // it immediately: it lands on the target once the scroll settles, so it
258
+ // doesn't chase the scroll through intervening sections.
259
+ suppressRef.current = true;
260
+ }
261
+ const scrollRoot = getScrollRoot();
262
+ const scrollTarget = scrollRoot ?? window;
164
263
  let settleTimer = 0;
264
+ let isSettled = false;
165
265
  const cleanup = () => {
166
- window.removeEventListener('scrollend', onSettle);
167
- window.removeEventListener('wheel', onManual);
168
- window.removeEventListener('touchmove', onManual);
266
+ scrollTarget.removeEventListener('scrollend', onSettle);
267
+ scrollTarget.removeEventListener('wheel', onManual);
268
+ scrollTarget.removeEventListener('touchmove', onManual);
169
269
  window.removeEventListener('keydown', onKeyDown);
170
270
  if (settleTimer !== 0) {
171
271
  clearTimeout(settleTimer);
172
272
  settleTimer = 0;
173
273
  }
174
- releaseSuppressionRef.current = null;
175
- };
176
- // Programmatic scroll finished: move the indicator to the clicked item.
177
- const onSettle = () => {
178
- cleanup();
179
- suppressRef.current = false;
180
- setUncontrolledActiveId(clickedId);
181
- activeIdRef.current = clickedId;
182
- onActiveIdChangeRef.current?.(clickedId);
274
+ navigationRef.current = null;
183
275
  };
184
- // User scrolled mid-flight: hand control back to scroll-position tracking.
185
- const onManual = () => {
276
+
277
+ /**
278
+ * End the navigation exactly once. `didArrive` is false when the user took
279
+ * over with a manual scroll mid-flight. `onNavigateEnd` fires either way,
280
+ * so every `onNavigateStart` is balanced and a consumer's "navigating"
281
+ * state can never leak.
282
+ */
283
+ const finish = (didArrive, shouldResume = true) => {
284
+ if (isSettled) {
285
+ return;
286
+ }
287
+ isSettled = true;
186
288
  cleanup();
187
- suppressRef.current = false;
188
- syncRef.current?.();
289
+ if (!isControlled) {
290
+ suppressRef.current = false;
291
+ if (didArrive) {
292
+ setUncontrolledActiveId(id);
293
+ activeIdRef.current = id;
294
+ onActiveIdChangeRef.current?.(id);
295
+ } else if (shouldResume) {
296
+ // Hand control back to scroll-position tracking.
297
+ syncRef.current?.();
298
+ }
299
+ }
300
+ onNavigateEnd?.(id);
189
301
  };
302
+ const onSettle = () => finish(true);
303
+ const onManual = () => finish(false);
190
304
  const onKeyDown = event => {
191
- if (SCROLL_KEYS.has(event.key)) {
192
- onManual();
305
+ // A key the outline itself consumed (arrow roving focus, Space
306
+ // activation) is prevented, so the browser will not scroll — it is not a
307
+ // manual scroll intent and must not cancel the navigation it just began.
308
+ if (!event.defaultPrevented && SCROLL_KEYS.has(event.key)) {
309
+ finish(false);
193
310
  }
194
311
  };
195
- window.addEventListener('scrollend', onSettle, {
196
- once: true
197
- });
198
- window.addEventListener('wheel', onManual, {
199
- passive: true
200
- });
201
- window.addEventListener('touchmove', onManual, {
202
- passive: true
203
- });
204
- window.addEventListener('keydown', onKeyDown);
205
- // Fallback when scrollend is unsupported or no scroll is needed.
206
- settleTimer = window.setTimeout(onSettle, 1200);
207
- releaseSuppressionRef.current = cleanup;
208
- }, []);
312
+ if (hasScrollOnClick) {
313
+ // Arm settle detection *before* scrolling so an instant jump (a target
314
+ // already in position, or prefers-reduced-motion collapsing the smooth
315
+ // scroll) cannot land before anyone is listening.
316
+ scrollTarget.addEventListener('scrollend', onSettle, {
317
+ once: true
318
+ });
319
+ scrollTarget.addEventListener('wheel', onManual, {
320
+ passive: true
321
+ });
322
+ scrollTarget.addEventListener('touchmove', onManual, {
323
+ passive: true
324
+ });
325
+ window.addEventListener('keydown', onKeyDown);
326
+ settleTimer = window.setTimeout(onSettle, SCROLL_SETTLE_TIMEOUT_MS);
327
+ navigationRef.current = {
328
+ supersede: () => finish(false, false),
329
+ teardown: cleanup
330
+ };
331
+ scrollToTarget(target, scrollRoot, scrollTarget, offset);
332
+ } else {
333
+ // The consumer owns scrolling — there is no scroll to wait for, so the
334
+ // navigation is already at rest. Resolving immediately (instead of
335
+ // waiting on the settle timeout) keeps onNavigateEnd usable for arrival
336
+ // effects even when hasScrollOnClick is false.
337
+ finish(true);
338
+ }
339
+ return true;
340
+ };
209
341
  return {
210
342
  activeId: isControlled ? activeId : uncontrolledActiveId,
211
343
  setActiveId,
212
- lockActiveId
344
+ scrollTo
213
345
  };
214
346
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Tab.d.ts","sourceRoot":"","sources":["../../src/TabList/Tab.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAAc,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAYzD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAK5C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAKrD,MAAM,WAAW,QAAS,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC5D;;;;OAIG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAoID;;;;;;;;;;;GAWG;AACH,wBAAgB,GAAG,CAAC,EAClB,EAAE,EACF,GAAG,EACH,KAAK,EACL,KAAK,EACL,aAAqB,EACrB,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,UAAU,EACV,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,SAAS,EACb,EAAE,QAAQ,qBA2GV;yBAzHe,GAAG"}
1
+ {"version":3,"file":"Tab.d.ts","sourceRoot":"","sources":["../../src/TabList/Tab.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAAc,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAYzD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAK5C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAKrD,MAAM,WAAW,QAAS,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC5D;;;;OAIG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAwID;;;;;;;;;;;GAWG;AACH,wBAAgB,GAAG,CAAC,EAClB,EAAE,EACF,GAAG,EACH,KAAK,EACL,KAAK,EACL,aAAqB,EACrB,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,UAAU,EACV,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,SAAS,EACb,EAAE,QAAQ,qBA2GV;yBAzHe,GAAG"}
@@ -206,10 +206,10 @@ export function Tab({
206
206
  selected: isSelected ? 'selected' : null
207
207
  }), {
208
208
  0: {
209
- className: "x10l6tqk xqmqy1e xnp31yv xmz3bnw x36qwtl xjspbzw x47corl xnpjden xuedmi6 xlr8y92 xjbqb8w xg01cxk"
209
+ className: "x10l6tqk xyi47jn xnp31yv xmz3bnw x36qwtl xjspbzw x47corl xnpjden xuedmi6 xlr8y92 xjbqb8w xg01cxk"
210
210
  },
211
211
  1: {
212
- className: "x10l6tqk xqmqy1e xnp31yv xmz3bnw x36qwtl xjspbzw x47corl xnpjden xuedmi6 xlr8y92 x1ewilqj x1hc1fzr"
212
+ className: "x10l6tqk xyi47jn xnp31yv xmz3bnw x36qwtl xjspbzw x47corl xnpjden xuedmi6 xlr8y92 x1ewilqj x1hc1fzr"
213
213
  }
214
214
  }[!!isSelected << 0])
215
215
  });
@@ -1 +1 @@
1
- {"version":3,"file":"TabList.d.ts","sourceRoot":"","sources":["../../src/TabList/TabList.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,EAAuB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGlE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAC,kBAAkB,EAAE,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAKtE,OAAO,EAAC,cAAc,EAAC,MAAM,mCAAmC,CAAC;AAWjE,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;IAC5E,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;;OAIG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAoBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,EACtB,GAAG,EACH,KAAK,EACL,QAAQ,EACR,IAAI,EAAE,QAAQ,EACd,MAAc,EACd,UAAkB,EAClB,WAA0B,EAC1B,MAAM,EACN,SAAS,EACT,KAAK,EACL,QAAQ,EACR,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,kBAAkB,EAChC,kBAAkB,EAAE,gBAAgB,EACpC,CAAC,cAAc,CAAC,EAAE,aAAa,EAC/B,GAAG,SAAS,EACb,EAAE,YAAY,qBAmGd;yBAtHe,OAAO"}
1
+ {"version":3,"file":"TabList.d.ts","sourceRoot":"","sources":["../../src/TabList/TabList.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,EAAuB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGlE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAC,kBAAkB,EAAE,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAKtE,OAAO,EAAC,cAAc,EAAC,MAAM,mCAAmC,CAAC;AAWjE,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;IAC5E,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;;OAIG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AA4BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,EACtB,GAAG,EACH,KAAK,EACL,QAAQ,EACR,IAAI,EAAE,QAAQ,EACd,MAAc,EACd,UAAkB,EAClB,WAA0B,EAC1B,MAAM,EACN,SAAS,EACT,KAAK,EACL,QAAQ,EACR,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,kBAAkB,EAChC,kBAAkB,EAAE,gBAAgB,EACpC,CAAC,cAAc,CAAC,EAAE,aAAa,EAC/B,GAAG,SAAS,EACb,EAAE,YAAY,qBAmGd;yBAtHe,OAAO"}
@@ -53,6 +53,8 @@ const styles = {
53
53
  kt9PQ7: "x92x3c3",
54
54
  kfdmCh: "x1q0q8m5",
55
55
  kL6WhQ: "xw8gpjh",
56
+ kGO01o: "xy143xn",
57
+ "--_tab-indicator-bottom": "xficto1",
56
58
  $$css: true
57
59
  }
58
60
  };
@@ -1 +1 @@
1
- {"version":3,"file":"TabMenu.d.ts","sourceRoot":"","sources":["../../src/TabList/TabMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAA6B,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGxE,OAAO,EAAiB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAiBtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,SAAS,CAAC,iBAAiB,CAAC,EAC5B,QAAQ,GAAG,WAAW,GAAG,OAAO,CACjC;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AA8KD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,EACtB,GAAG,EACH,KAAK,EACL,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,YAAY,qBAqLd;yBA5Le,OAAO"}
1
+ {"version":3,"file":"TabMenu.d.ts","sourceRoot":"","sources":["../../src/TabList/TabMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAA6B,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGxE,OAAO,EAAiB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAiBtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,SAAS,CAAC,iBAAiB,CAAC,EAC5B,QAAQ,GAAG,WAAW,GAAG,OAAO,CACjC;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAiLD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,EACtB,GAAG,EACH,KAAK,EACL,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,YAAY,qBAqLd;yBA5Le,OAAO"}
@@ -240,7 +240,7 @@ export function TabMenu({
240
240
  ...mergeProps(themeProps('tab-indicator', {
241
241
  selected: 'selected'
242
242
  }), {
243
- className: "x10l6tqk xqmqy1e xnp31yv xmz3bnw x36qwtl xjspbzw x47corl xnpjden xuedmi6 xlr8y92 xowkcby x1hc1fzr"
243
+ className: "x10l6tqk xyi47jn xnp31yv xmz3bnw x36qwtl xjspbzw x47corl xnpjden xuedmi6 xlr8y92 xowkcby x1hc1fzr"
244
244
  })
245
245
  })]
246
246
  }), popover.render(/*#__PURE__*/_jsxs("div", {
@@ -88,7 +88,7 @@ export interface TableProps<T extends Record<string, unknown>> extends Omit<Base
88
88
  * columns={[
89
89
  * { key: 'name', header: 'Name', width: proportional(1), renderCell: (u) => (
90
90
  * <HStack gap={2} align="center">
91
- * <Avatar name={u.name} size="small" />
91
+ * <Avatar name={u.name} size="md" />
92
92
  * <Text weight="semibold">{u.name}</Text>
93
93
  * </HStack>
94
94
  * )},
@@ -186,7 +186,7 @@ function TableInner({
186
186
  * columns={[
187
187
  * { key: 'name', header: 'Name', width: proportional(1), renderCell: (u) => (
188
188
  * <HStack gap={2} align="center">
189
- * <Avatar name={u.name} size="small" />
189
+ * <Avatar name={u.name} size="md" />
190
190
  * <Text weight="semibold">{u.name}</Text>
191
191
  * </HStack>
192
192
  * )},
@@ -26,6 +26,7 @@ export { useTableStickyColumns } from './plugins/stickyColumns';
26
26
  export { useTableGroupedRows } from './plugins/groupedRows';
27
27
  export { useTableRowIndex } from './plugins/rowIndex';
28
28
  export { useTableRowExpansion, useTableRowExpansionState, } from './plugins/rowExpansion';
29
+ export { useTableTreeData, useTableTreeState } from './plugins/tree';
29
30
  export { resolveContextActions } from './tableContextMenu';
30
31
  export { useTableFiltering, useTableFilterState, toSearchFilters, } from './plugins/filtering';
31
32
  export { useBaseTablePlugins } from './useBaseTablePlugins';
@@ -51,5 +52,6 @@ export type { UseTableStickyColumnsConfig } from './plugins/stickyColumns';
51
52
  export type { UseTableRowExpansionConfig } from './plugins/rowExpansion';
52
53
  export type { UseTableRowIndexConfig } from './plugins/rowIndex';
53
54
  export type { UseTableGroupedRowsConfig, UseTableGroupedRowsResult, } from './plugins/groupedRows';
55
+ export type { TableTreeRowMeta, UseTableTreeDataConfig, UseTableTreeStateConfig, UseTableTreeStateResult, } from './plugins/tree';
54
56
  export type { UseTableFilteringConfig, TableFilterState, TableFilterVariant, TableFilterValue, TableFilterFieldRef, } from './plugins/filtering';
55
57
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Table/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Table/index.ts"],"names":[],"mappings":"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"}
@@ -29,6 +29,7 @@ export { useTableStickyColumns } from "./plugins/stickyColumns/index.js";
29
29
  export { useTableGroupedRows } from "./plugins/groupedRows/index.js";
30
30
  export { useTableRowIndex } from "./plugins/rowIndex/index.js";
31
31
  export { useTableRowExpansion, useTableRowExpansionState } from "./plugins/rowExpansion/index.js";
32
+ export { useTableTreeData, useTableTreeState } from "./plugins/tree/index.js";
32
33
  export { resolveContextActions } from "./tableContextMenu.js";
33
34
  export { useTableFiltering, useTableFilterState, toSearchFilters } from "./plugins/filtering/index.js";
34
35
  export { useBaseTablePlugins } from "./useBaseTablePlugins.js";
@@ -1 +1 @@
1
- {"version":3,"file":"useTableRowExpansion.d.ts","sourceRoot":"","sources":["../../../../src/Table/plugins/rowExpansion/useTableRowExpansion.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,WAAW,EAKZ,MAAM,aAAa,CAAC;AAMrB;;;;;;;GAOG;AACH,MAAM,WAAW,0BAA0B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3E,0CAA0C;IAC1C,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,gDAAgD;IAChD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,kDAAkD;IAClD,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC/B,sEAAsE;IACtE,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC/B,uFAAuF;IACvF,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;IAC3C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC;IAC1C,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,+BAA+B,CAC9C,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEjC,mCAAmC;IACnC,QAAQ,EAAE,CAAC,EAAE,CAAC;IACd,qEAAqE;IACrE,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9B,kDAAkD;IAClD,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC/B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;IAC3C,qDAAqD;IACrD,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,+CAA+C;IAC/C,eAAe,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;CACpE;AAED,MAAM,WAAW,+BAA+B,CAC9C,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEjC,qEAAqE;IACrE,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,4DAA4D;IAC5D,eAAe,EAAE,0BAA0B,CAAC,CAAC,CAAC,CAAC;CAChD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC3E,QAAQ,EACR,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,YAAY,EACZ,eAAe,GAChB,EAAE,+BAA+B,CAAC,CAAC,CAAC,GAAG,+BAA+B,CAAC,CAAC,CAAC,CAyHzE;AAuGD,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpE,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,GACpC,WAAW,CAAC,CAAC,CAAC,CAwOhB"}
1
+ {"version":3,"file":"useTableRowExpansion.d.ts","sourceRoot":"","sources":["../../../../src/Table/plugins/rowExpansion/useTableRowExpansion.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,WAAW,EAKZ,MAAM,aAAa,CAAC;AAMrB;;;;;;;GAOG;AACH,MAAM,WAAW,0BAA0B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3E,0CAA0C;IAC1C,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,gDAAgD;IAChD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,kDAAkD;IAClD,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC/B,sEAAsE;IACtE,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC/B,uFAAuF;IACvF,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;IAC3C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC;IAC1C,2DAA2D;IAC3D,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,+BAA+B,CAC9C,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEjC,mCAAmC;IACnC,QAAQ,EAAE,CAAC,EAAE,CAAC;IACd,qEAAqE;IACrE,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9B,kDAAkD;IAClD,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC/B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;IAC3C,qDAAqD;IACrD,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,+CAA+C;IAC/C,eAAe,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;CACpE;AAED,MAAM,WAAW,+BAA+B,CAC9C,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEjC,qEAAqE;IACrE,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,4DAA4D;IAC5D,eAAe,EAAE,0BAA0B,CAAC,CAAC,CAAC,CAAC;CAChD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC3E,QAAQ,EACR,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,YAAY,EACZ,eAAe,GAChB,EAAE,+BAA+B,CAAC,CAAC,CAAC,GAAG,+BAA+B,CAAC,CAAC,CAAC,CA+IzE;AAuGD,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpE,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,GACpC,WAAW,CAAC,CAAC,CAAC,CAkPhB"}
@@ -72,12 +72,19 @@ export function useTableRowExpansionState({
72
72
  const isExpandable = useCallback(item => getIsItemExpandable ? getIsItemExpandable(item) : getChildren(item).length > 0, [getIsItemExpandable, getChildren]);
73
73
  const depthMap = useMemo(() => {
74
74
  const map = new Map();
75
+ // Ancestor keys on the current walk path — guards against cyclic data.
76
+ const path = new Set();
75
77
  function walk(items, depth) {
76
78
  for (const item of items) {
77
79
  const key = getRowKey(item);
80
+ if (path.has(key)) {
81
+ continue; // cyclic edge — skip
82
+ }
78
83
  map.set(key, depth);
79
84
  if (expandedKeys.has(key)) {
85
+ path.add(key);
80
86
  walk(getChildren(item), depth + 1);
87
+ path.delete(key);
81
88
  }
82
89
  }
83
90
  }
@@ -86,12 +93,19 @@ export function useTableRowExpansionState({
86
93
  }, [baseData, getChildren, getRowKey, expandedKeys]);
87
94
  const data = useMemo(() => {
88
95
  const result = [];
96
+ // Ancestor keys on the current walk path — guards against cyclic data.
97
+ const path = new Set();
89
98
  function walk(items) {
90
99
  for (const item of items) {
91
- result.push(item);
92
100
  const key = getRowKey(item);
101
+ if (path.has(key)) {
102
+ continue; // cyclic edge — skip
103
+ }
104
+ result.push(item);
93
105
  if (expandedKeys.has(key)) {
106
+ path.add(key);
94
107
  walk(getChildren(item));
108
+ path.delete(key);
95
109
  }
96
110
  }
97
111
  }
@@ -102,11 +116,19 @@ export function useTableRowExpansionState({
102
116
  // Every expandable key across the whole tree (drives expand-all).
103
117
  const allExpandableKeys = useMemo(() => {
104
118
  const keys = [];
119
+ // Ancestor keys on the current walk path — guards against cyclic data.
120
+ const path = new Set();
105
121
  function walk(items) {
106
122
  for (const item of items) {
123
+ const key = getRowKey(item);
124
+ if (path.has(key)) {
125
+ continue; // cyclic edge — skip
126
+ }
107
127
  if (isExpandable(item)) {
108
- keys.push(getRowKey(item));
128
+ keys.push(key);
129
+ path.add(key);
109
130
  walk(getChildren(item));
131
+ path.delete(key);
110
132
  }
111
133
  }
112
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useTableSortable.d.ts","sourceRoot":"","sources":["../../../../src/Table/plugins/sortable/useTableSortable.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACV,WAAW,EAIZ,MAAM,aAAa,CAAC;AAMrB;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,YAAY,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM;IAC9D,2EAA2E;IAC3E,OAAO,EAAE,QAAQ,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,IACzD,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;AAM7B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,sBAAsB,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM;IACtE,iEAAiE;IACjE,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IAE/B;;;OAGG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IAEvD;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAmND;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAC9B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAChC,MAAM,EAAE,sBAAsB,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CA2F1D"}
1
+ {"version":3,"file":"useTableSortable.d.ts","sourceRoot":"","sources":["../../../../src/Table/plugins/sortable/useTableSortable.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACV,WAAW,EAIZ,MAAM,aAAa,CAAC;AAMrB;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,YAAY,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM;IAC9D,2EAA2E;IAC3E,OAAO,EAAE,QAAQ,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,IACzD,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;AAM7B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,sBAAsB,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM;IACtE,iEAAiE;IACjE,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IAE/B;;;OAGG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IAEvD;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAmOD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAC9B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAChC,MAAM,EAAE,sBAAsB,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CA2F1D"}
@@ -4,7 +4,7 @@
4
4
 
5
5
  /**
6
6
  * @file useTableSortable.tsx
7
- * @input React, types, Icon, theme tokens
7
+ * @input React, types, Icon, theme tokens, i18n (useTranslator)
8
8
  * @output Exports useTableSortable hook and sort-related types
9
9
  * @position Sortable plugin; consumed by Table via plugins prop
10
10
  *
@@ -95,16 +95,26 @@ function getHeaderLabel(column) {
95
95
  }
96
96
  return column.key;
97
97
  }
98
- function buildAriaLabel(column, direction, rank, total) {
98
+ function buildAriaLabel(t, column, direction, rank, total) {
99
99
  const label = getHeaderLabel(column);
100
100
  if (direction == null) {
101
- return `Sort by ${label}`;
101
+ return t('@astryx.table.sort.sortBy', {
102
+ label
103
+ });
102
104
  }
103
- let ariaLabel = `Sort by ${label}, sorted ${direction}`;
105
+ const directionLabel = direction === 'ascending' ? t('@astryx.table.sort.direction.ascending') : t('@astryx.table.sort.direction.descending');
104
106
  if (rank != null && total > 1) {
105
- ariaLabel += `, priority ${rank} of ${total}`;
107
+ return t('@astryx.table.sort.sortedByWithPriority', {
108
+ label,
109
+ direction: directionLabel,
110
+ rank,
111
+ total
112
+ });
106
113
  }
107
- return ariaLabel;
114
+ return t('@astryx.table.sort.sortedBy', {
115
+ label,
116
+ direction: directionLabel
117
+ });
108
118
  }
109
119
  function getNextDirection(current, allowUnsortedState) {
110
120
  if (current == null) {
@@ -126,6 +136,7 @@ function SortHeaderButton({
126
136
  children,
127
137
  configRef
128
138
  }) {
139
+ const t = useTranslator();
129
140
  const config = configRef.current;
130
141
  const sortKey = resolveSortKey(column) ?? '';
131
142
  const entryIndex = config.sort.findIndex(e => e.sortKey === sortKey);
@@ -134,7 +145,7 @@ function SortHeaderButton({
134
145
  const isMultiSort = config.isMultiSortEnabled === true && config.sort.length > 1;
135
146
  const rank = isMultiSort && entryIndex >= 0 ? entryIndex + 1 : null;
136
147
  const iconName = direction === 'ascending' ? 'arrowUp' : direction === 'descending' ? 'arrowDown' : 'arrowsUpDown';
137
- const ariaLabel = buildAriaLabel(column, direction, rank, config.sort.length);
148
+ const ariaLabel = buildAriaLabel(t, column, direction, rank, config.sort.length);
138
149
  const handleClick = e => {
139
150
  const cfg = configRef.current;
140
151
  const isShift = e.shiftKey && cfg.isMultiSortEnabled;
@@ -0,0 +1,5 @@
1
+ export { useTableTreeData } from './useTableTreeData';
2
+ export type { TableTreeRowMeta, UseTableTreeDataConfig, } from './useTableTreeData';
3
+ export { useTableTreeState } from './useTableTreeState';
4
+ export type { UseTableTreeStateConfig, UseTableTreeStateResult, } from './useTableTreeState';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/Table/plugins/tree/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACpD,YAAY,EACV,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,YAAY,EACV,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC"}