@salt-ds/lab 1.0.0-alpha.93 → 1.0.0-alpha.94

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 (131) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/css/salt-lab.css +163 -122
  3. package/dist-cjs/index.js +6 -8
  4. package/dist-cjs/index.js.map +1 -1
  5. package/dist-cjs/toolbar-next/ToolbarContentNext.css.js +6 -0
  6. package/dist-cjs/toolbar-next/ToolbarContentNext.css.js.map +1 -0
  7. package/dist-cjs/toolbar-next/ToolbarContentNext.js +32 -0
  8. package/dist-cjs/toolbar-next/ToolbarContentNext.js.map +1 -0
  9. package/dist-cjs/toolbar-next/ToolbarNext.css.js +6 -0
  10. package/dist-cjs/toolbar-next/ToolbarNext.css.js.map +1 -0
  11. package/dist-cjs/toolbar-next/ToolbarNext.js +394 -0
  12. package/dist-cjs/toolbar-next/ToolbarNext.js.map +1 -0
  13. package/dist-cjs/toolbar-next/ToolbarNextOverflow.css.js +6 -0
  14. package/dist-cjs/toolbar-next/ToolbarNextOverflow.css.js.map +1 -0
  15. package/dist-cjs/toolbar-next/ToolbarNextOverflow.js +705 -0
  16. package/dist-cjs/toolbar-next/ToolbarNextOverflow.js.map +1 -0
  17. package/dist-cjs/toolbar-next/ToolbarNextOverflowFloatingBoundary.js +165 -0
  18. package/dist-cjs/toolbar-next/ToolbarNextOverflowFloatingBoundary.js.map +1 -0
  19. package/dist-cjs/toolbar-next/TooltrayNext.css.js +6 -0
  20. package/dist-cjs/toolbar-next/TooltrayNext.css.js.map +1 -0
  21. package/dist-cjs/toolbar-next/TooltrayNext.js +55 -0
  22. package/dist-cjs/toolbar-next/TooltrayNext.js.map +1 -0
  23. package/dist-cjs/toolbar-next/toolbarNextKeyboardUtils.js +391 -0
  24. package/dist-cjs/toolbar-next/toolbarNextKeyboardUtils.js.map +1 -0
  25. package/dist-cjs/toolbar-next/toolbarNextUtils.js +215 -0
  26. package/dist-cjs/toolbar-next/toolbarNextUtils.js.map +1 -0
  27. package/dist-cjs/toolbar-next/useToolbarNextKeyboardNavigation.js +334 -0
  28. package/dist-cjs/toolbar-next/useToolbarNextKeyboardNavigation.js.map +1 -0
  29. package/dist-cjs/toolbar-next/useToolbarNextOverflow.js +743 -0
  30. package/dist-cjs/toolbar-next/useToolbarNextOverflow.js.map +1 -0
  31. package/dist-es/index.js +3 -4
  32. package/dist-es/index.js.map +1 -1
  33. package/dist-es/toolbar-next/ToolbarContentNext.css.js +4 -0
  34. package/dist-es/toolbar-next/ToolbarContentNext.css.js.map +1 -0
  35. package/dist-es/toolbar-next/ToolbarContentNext.js +30 -0
  36. package/dist-es/toolbar-next/ToolbarContentNext.js.map +1 -0
  37. package/dist-es/toolbar-next/ToolbarNext.css.js +4 -0
  38. package/dist-es/toolbar-next/ToolbarNext.css.js.map +1 -0
  39. package/dist-es/toolbar-next/ToolbarNext.js +392 -0
  40. package/dist-es/toolbar-next/ToolbarNext.js.map +1 -0
  41. package/dist-es/toolbar-next/ToolbarNextOverflow.css.js +4 -0
  42. package/dist-es/toolbar-next/ToolbarNextOverflow.css.js.map +1 -0
  43. package/dist-es/toolbar-next/ToolbarNextOverflow.js +700 -0
  44. package/dist-es/toolbar-next/ToolbarNextOverflow.js.map +1 -0
  45. package/dist-es/toolbar-next/ToolbarNextOverflowFloatingBoundary.js +159 -0
  46. package/dist-es/toolbar-next/ToolbarNextOverflowFloatingBoundary.js.map +1 -0
  47. package/dist-es/toolbar-next/TooltrayNext.css.js +4 -0
  48. package/dist-es/toolbar-next/TooltrayNext.css.js.map +1 -0
  49. package/dist-es/toolbar-next/TooltrayNext.js +53 -0
  50. package/dist-es/toolbar-next/TooltrayNext.js.map +1 -0
  51. package/dist-es/toolbar-next/toolbarNextKeyboardUtils.js +372 -0
  52. package/dist-es/toolbar-next/toolbarNextKeyboardUtils.js.map +1 -0
  53. package/dist-es/toolbar-next/toolbarNextUtils.js +211 -0
  54. package/dist-es/toolbar-next/toolbarNextUtils.js.map +1 -0
  55. package/dist-es/toolbar-next/useToolbarNextKeyboardNavigation.js +332 -0
  56. package/dist-es/toolbar-next/useToolbarNextKeyboardNavigation.js.map +1 -0
  57. package/dist-es/toolbar-next/useToolbarNextOverflow.js +741 -0
  58. package/dist-es/toolbar-next/useToolbarNextOverflow.js.map +1 -0
  59. package/dist-types/index.d.ts +1 -1
  60. package/dist-types/toolbar-next/ToolbarContentNext.d.ts +11 -0
  61. package/dist-types/toolbar-next/ToolbarNext.d.ts +12 -0
  62. package/dist-types/toolbar-next/ToolbarNextOverflow.d.ts +34 -0
  63. package/dist-types/toolbar-next/ToolbarNextOverflowFloatingBoundary.d.ts +16 -0
  64. package/dist-types/toolbar-next/TooltrayNext.d.ts +37 -0
  65. package/dist-types/toolbar-next/index.d.ts +3 -0
  66. package/dist-types/toolbar-next/toolbarNextKeyboardUtils.d.ts +39 -0
  67. package/dist-types/toolbar-next/toolbarNextUtils.d.ts +42 -0
  68. package/dist-types/toolbar-next/useToolbarNextKeyboardNavigation.d.ts +41 -0
  69. package/dist-types/toolbar-next/useToolbarNextOverflow.d.ts +37 -0
  70. package/package.json +2 -2
  71. package/dist-cjs/tree/Tree.css.js +0 -6
  72. package/dist-cjs/tree/Tree.css.js.map +0 -1
  73. package/dist-cjs/tree/Tree.js +0 -303
  74. package/dist-cjs/tree/Tree.js.map +0 -1
  75. package/dist-cjs/tree/TreeContext.js +0 -31
  76. package/dist-cjs/tree/TreeContext.js.map +0 -1
  77. package/dist-cjs/tree/TreeNode.css.js +0 -6
  78. package/dist-cjs/tree/TreeNode.css.js.map +0 -1
  79. package/dist-cjs/tree/TreeNode.js +0 -103
  80. package/dist-cjs/tree/TreeNode.js.map +0 -1
  81. package/dist-cjs/tree/TreeNodeExpansionIcon.css.js +0 -6
  82. package/dist-cjs/tree/TreeNodeExpansionIcon.css.js.map +0 -1
  83. package/dist-cjs/tree/TreeNodeExpansionIcon.js +0 -62
  84. package/dist-cjs/tree/TreeNodeExpansionIcon.js.map +0 -1
  85. package/dist-cjs/tree/TreeNodeLabel.css.js +0 -6
  86. package/dist-cjs/tree/TreeNodeLabel.css.js.map +0 -1
  87. package/dist-cjs/tree/TreeNodeLabel.js +0 -26
  88. package/dist-cjs/tree/TreeNodeLabel.js.map +0 -1
  89. package/dist-cjs/tree/TreeNodeTrigger.css.js +0 -6
  90. package/dist-cjs/tree/TreeNodeTrigger.css.js.map +0 -1
  91. package/dist-cjs/tree/TreeNodeTrigger.js +0 -153
  92. package/dist-cjs/tree/TreeNodeTrigger.js.map +0 -1
  93. package/dist-cjs/tree/treeModel.js +0 -61
  94. package/dist-cjs/tree/treeModel.js.map +0 -1
  95. package/dist-cjs/tree/useTree.js +0 -337
  96. package/dist-cjs/tree/useTree.js.map +0 -1
  97. package/dist-es/tree/Tree.css.js +0 -4
  98. package/dist-es/tree/Tree.css.js.map +0 -1
  99. package/dist-es/tree/Tree.js +0 -301
  100. package/dist-es/tree/Tree.js.map +0 -1
  101. package/dist-es/tree/TreeContext.js +0 -26
  102. package/dist-es/tree/TreeContext.js.map +0 -1
  103. package/dist-es/tree/TreeNode.css.js +0 -4
  104. package/dist-es/tree/TreeNode.css.js.map +0 -1
  105. package/dist-es/tree/TreeNode.js +0 -101
  106. package/dist-es/tree/TreeNode.js.map +0 -1
  107. package/dist-es/tree/TreeNodeExpansionIcon.css.js +0 -4
  108. package/dist-es/tree/TreeNodeExpansionIcon.css.js.map +0 -1
  109. package/dist-es/tree/TreeNodeExpansionIcon.js +0 -60
  110. package/dist-es/tree/TreeNodeExpansionIcon.js.map +0 -1
  111. package/dist-es/tree/TreeNodeLabel.css.js +0 -4
  112. package/dist-es/tree/TreeNodeLabel.css.js.map +0 -1
  113. package/dist-es/tree/TreeNodeLabel.js +0 -24
  114. package/dist-es/tree/TreeNodeLabel.js.map +0 -1
  115. package/dist-es/tree/TreeNodeTrigger.css.js +0 -4
  116. package/dist-es/tree/TreeNodeTrigger.css.js.map +0 -1
  117. package/dist-es/tree/TreeNodeTrigger.js +0 -151
  118. package/dist-es/tree/TreeNodeTrigger.js.map +0 -1
  119. package/dist-es/tree/treeModel.js +0 -57
  120. package/dist-es/tree/treeModel.js.map +0 -1
  121. package/dist-es/tree/useTree.js +0 -335
  122. package/dist-es/tree/useTree.js.map +0 -1
  123. package/dist-types/tree/Tree.d.ts +0 -36
  124. package/dist-types/tree/TreeContext.d.ts +0 -77
  125. package/dist-types/tree/TreeNode.d.ts +0 -25
  126. package/dist-types/tree/TreeNodeExpansionIcon.d.ts +0 -4
  127. package/dist-types/tree/TreeNodeLabel.d.ts +0 -4
  128. package/dist-types/tree/TreeNodeTrigger.d.ts +0 -8
  129. package/dist-types/tree/index.d.ts +0 -4
  130. package/dist-types/tree/treeModel.d.ts +0 -24
  131. package/dist-types/tree/useTree.d.ts +0 -68
@@ -0,0 +1,705 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var react$1 = require('@floating-ui/react');
5
+ var core = require('@salt-ds/core');
6
+ var styles = require('@salt-ds/styles');
7
+ var window = require('@salt-ds/window');
8
+ var clsx = require('clsx');
9
+ var computeScrollIntoView = require('compute-scroll-into-view');
10
+ var react = require('react');
11
+ var ReactDOM = require('react-dom');
12
+ var ToolbarContentNext = require('./ToolbarContentNext.js');
13
+ var ToolbarNextOverflow = require('./ToolbarNextOverflow.css.js');
14
+ var ToolbarNextOverflowFloatingBoundary = require('./ToolbarNextOverflowFloatingBoundary.js');
15
+ var toolbarNextKeyboardUtils = require('./toolbarNextKeyboardUtils.js');
16
+ var toolbarNextUtils = require('./toolbarNextUtils.js');
17
+ var useToolbarNextKeyboardNavigation = require('./useToolbarNextKeyboardNavigation.js');
18
+
19
+ const withBaseName = core.makePrefixer("saltToolbarNextOverflow");
20
+ const toolbarNextStatefulFocusRootSelector = [
21
+ ".saltDateInput-focused",
22
+ ".saltInput-focused"
23
+ ].join(", ");
24
+ const toolbarNextOverflowFocusScrollRootSelector = [
25
+ ".saltComboBox",
26
+ ".saltDateInput",
27
+ ".saltDropdown",
28
+ ".saltInput",
29
+ ".saltSwitch"
30
+ ].join(", ");
31
+ function createToolbarNextFocusEvent(eventName, target, relatedTarget) {
32
+ var _a;
33
+ const FocusEventCtor = (_a = target.ownerDocument.defaultView) == null ? void 0 : _a.FocusEvent;
34
+ const eventInit = {
35
+ bubbles: eventName === "focusout",
36
+ relatedTarget
37
+ };
38
+ return FocusEventCtor ? new FocusEventCtor(eventName, eventInit) : new Event(eventName, eventInit);
39
+ }
40
+ function notifyToolbarNextReparentedFocusLoss(mountNode) {
41
+ const activeElement = mountNode.ownerDocument.activeElement;
42
+ if (mountNode.contains(activeElement)) {
43
+ return;
44
+ }
45
+ const staleFocusTargets = Array.from(
46
+ mountNode.querySelectorAll(
47
+ toolbarNextStatefulFocusRootSelector
48
+ )
49
+ ).map(
50
+ (root) => root.querySelector(toolbarNextKeyboardUtils.toolbarNextFocusableSelector)
51
+ ).filter((target) => target != null);
52
+ for (const target of staleFocusTargets) {
53
+ const relatedTarget = activeElement instanceof Element ? activeElement : null;
54
+ target.dispatchEvent(
55
+ createToolbarNextFocusEvent("blur", target, relatedTarget)
56
+ );
57
+ target.dispatchEvent(
58
+ createToolbarNextFocusEvent("focusout", target, relatedTarget)
59
+ );
60
+ }
61
+ }
62
+ function getToolbarNextOverflowFocusScrollTarget(target) {
63
+ const itemRoot = target.closest(`[${toolbarNextKeyboardUtils.TOOLBAR_NEXT_ITEM_ATTR}]`);
64
+ const controlRoot = target.closest(
65
+ toolbarNextOverflowFocusScrollRootSelector
66
+ );
67
+ return controlRoot && (itemRoot == null ? void 0 : itemRoot.contains(controlRoot)) ? controlRoot : target;
68
+ }
69
+ function getToolbarNextOverflowPanelInlinePadding(target) {
70
+ var _a;
71
+ const panelContent = target.closest(
72
+ `[${toolbarNextKeyboardUtils.TOOLBAR_NEXT_SCOPE_ROOT_ATTR}]`
73
+ );
74
+ const styles = (_a = panelContent == null ? void 0 : panelContent.ownerDocument.defaultView) == null ? void 0 : _a.getComputedStyle(panelContent);
75
+ return {
76
+ left: Number.parseFloat((styles == null ? void 0 : styles.paddingLeft) ?? "0") || 0,
77
+ right: Number.parseFloat((styles == null ? void 0 : styles.paddingRight) ?? "0") || 0
78
+ };
79
+ }
80
+ function scrollToolbarNextOverflowTargetIntoView(panel, target) {
81
+ if (!panel || !panel.contains(target)) {
82
+ return;
83
+ }
84
+ const scrollTarget = getToolbarNextOverflowFocusScrollTarget(target);
85
+ const actions = computeScrollIntoView.compute(scrollTarget, {
86
+ block: "nearest",
87
+ boundary: panel,
88
+ inline: "nearest",
89
+ scrollMode: "if-needed"
90
+ });
91
+ for (const { el, left, top } of actions) {
92
+ if (el === panel) {
93
+ const targetRect = scrollTarget.getBoundingClientRect();
94
+ const panelRect = panel.getBoundingClientRect();
95
+ const viewportLeft = panelRect.left + panel.clientLeft;
96
+ const viewportRight = viewportLeft + panel.clientWidth;
97
+ const padding = getToolbarNextOverflowPanelInlinePadding(scrollTarget);
98
+ const nextLeft = targetRect.left < viewportLeft + padding.left ? left - padding.left : targetRect.right > viewportRight - padding.right ? left + padding.right : left;
99
+ el.scrollLeft = Math.max(0, nextLeft);
100
+ } else {
101
+ el.scrollLeft = left;
102
+ }
103
+ el.scrollTop = top;
104
+ }
105
+ }
106
+ function canSeedOverflowFocusMemory(focusMemory, group) {
107
+ return (focusMemory == null ? void 0 : focusMemory.type) === "item" && group.items.some((item) => item.id === focusMemory.itemId);
108
+ }
109
+ function ToolbarNextOverflowItemOwner({
110
+ host,
111
+ item
112
+ }) {
113
+ const targetWindow = window.useWindow();
114
+ const [mountNode, setMountNode] = react.useState(null);
115
+ const mainToolbarTabIndexMemoryRef = react.useRef(
116
+ /* @__PURE__ */ new WeakMap()
117
+ );
118
+ const lastOverflowBoundaryKeyRef = react.useRef(null);
119
+ const currentOverflowBoundaryKey = ToolbarNextOverflowFloatingBoundary.getToolbarNextOverflowBoundaryKey(host);
120
+ if (host) {
121
+ lastOverflowBoundaryKeyRef.current = currentOverflowBoundaryKey;
122
+ }
123
+ const boundaryKey = host ? currentOverflowBoundaryKey : lastOverflowBoundaryKeyRef.current;
124
+ core.useIsomorphicLayoutEffect(() => {
125
+ const nextMountNode = targetWindow == null ? void 0 : targetWindow.document.createElement("div");
126
+ if (!nextMountNode) {
127
+ return;
128
+ }
129
+ nextMountNode.className = withBaseName("contentHost");
130
+ setMountNode(nextMountNode);
131
+ return () => {
132
+ var _a;
133
+ (_a = nextMountNode.parentElement) == null ? void 0 : _a.removeChild(nextMountNode);
134
+ };
135
+ }, [targetWindow]);
136
+ core.useIsomorphicLayoutEffect(() => {
137
+ var _a, _b;
138
+ if (!mountNode) {
139
+ return;
140
+ }
141
+ if (host) {
142
+ if (mountNode.parentElement !== host) {
143
+ host.appendChild(mountNode);
144
+ notifyToolbarNextReparentedFocusLoss(mountNode);
145
+ }
146
+ const isMainToolbarHost = ((_a = host.closest(`[${toolbarNextKeyboardUtils.TOOLBAR_NEXT_SCOPE_ROOT_ATTR}]`)) == null ? void 0 : _a.getAttribute(toolbarNextKeyboardUtils.TOOLBAR_NEXT_SCOPE_ROOT_ATTR)) === "main";
147
+ if (isMainToolbarHost) {
148
+ const focusableElements = Array.from(
149
+ mountNode.querySelectorAll(toolbarNextKeyboardUtils.toolbarNextFocusableSelector)
150
+ );
151
+ for (const element of focusableElements) {
152
+ const rememberedTabIndex = mainToolbarTabIndexMemoryRef.current.get(element);
153
+ if (rememberedTabIndex !== void 0) {
154
+ if (rememberedTabIndex == null) {
155
+ element.removeAttribute("tabindex");
156
+ } else {
157
+ element.setAttribute("tabindex", rememberedTabIndex);
158
+ }
159
+ }
160
+ }
161
+ for (const element of focusableElements) {
162
+ mainToolbarTabIndexMemoryRef.current.set(
163
+ element,
164
+ element.getAttribute("tabindex")
165
+ );
166
+ }
167
+ }
168
+ return;
169
+ }
170
+ notifyToolbarNextReparentedFocusLoss(mountNode);
171
+ (_b = mountNode.parentElement) == null ? void 0 : _b.removeChild(mountNode);
172
+ }, [host, mountNode]);
173
+ if (!mountNode) {
174
+ return null;
175
+ }
176
+ const clonedItem = react.cloneElement(
177
+ item.element,
178
+ {
179
+ [toolbarNextKeyboardUtils.TOOLBAR_NEXT_GROUP_KEY_ATTR]: item.overflowGroupKey,
180
+ [toolbarNextKeyboardUtils.TOOLBAR_NEXT_ITEM_ATTR]: item.id
181
+ }
182
+ );
183
+ const itemContent = /* @__PURE__ */ jsxRuntime.jsx(ToolbarNextOverflowFloatingBoundary.ToolbarNextOverflowFloatingComponentProvider, { boundaryKey, children: clonedItem });
184
+ return ReactDOM.createPortal(itemContent, mountNode);
185
+ }
186
+ function ToolbarNextOverflowOwners({
187
+ hostNodes,
188
+ items
189
+ }) {
190
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
191
+ ToolbarNextOverflowItemOwner,
192
+ {
193
+ host: hostNodes[item.id] ?? null,
194
+ item
195
+ },
196
+ item.id
197
+ )) });
198
+ }
199
+ function cloneDecorations(itemId, decorations, slot) {
200
+ return react.Children.toArray(decorations).flatMap((decoration) => {
201
+ if (!react.isValidElement(decoration)) {
202
+ return [];
203
+ }
204
+ return [
205
+ react.cloneElement(decoration, {
206
+ key: `${itemId}-${slot}-${String(
207
+ decoration.key ?? (typeof decoration.type === "string" ? decoration.type : "decoration")
208
+ )}`
209
+ })
210
+ ];
211
+ });
212
+ }
213
+ function ToolbarNextOverflowTriggerContent({
214
+ label,
215
+ named
216
+ }) {
217
+ const { OverflowIcon } = core.useIcon();
218
+ if (named) {
219
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: label });
220
+ }
221
+ return /* @__PURE__ */ jsxRuntime.jsx(OverflowIcon, { "aria-hidden": true });
222
+ }
223
+ function getOverflowTriggerLabel(group) {
224
+ return group.named ? `${group.label} overflow. Hidden controls.` : "Overflow. Hidden controls.";
225
+ }
226
+ function ToolbarNextOverflowMenu({
227
+ focusMemoryRef,
228
+ getItemHostRef,
229
+ group,
230
+ onItemFocus
231
+ }) {
232
+ var _a, _b;
233
+ const panelId = core.useId();
234
+ const [open, setOpen] = react.useState(false);
235
+ const triggerRef = react.useRef(null);
236
+ const panelRef = react.useRef(null);
237
+ const panelContentRef = react.useRef(null);
238
+ const [panelContentNode, setPanelContentNode] = react.useState(null);
239
+ const wasOpenRef = react.useRef(false);
240
+ const focusedOpenPanelRef = react.useRef(false);
241
+ const openModalityRef = react.useRef(null);
242
+ const floatingBoundary = ToolbarNextOverflowFloatingBoundary.useToolbarNextOverflowFloatingBoundary();
243
+ const {
244
+ focusEntryTarget,
245
+ handleScopeBlur,
246
+ handleScopeFocus,
247
+ handleScopeKeyDown,
248
+ handleScopePointerDown,
249
+ rememberedFocusRef
250
+ } = useToolbarNextKeyboardNavigation.useToolbarNextKeyboardNavigation({
251
+ includeTabIndexMinusOne: true,
252
+ items: group.items,
253
+ scopeRef: panelContentRef
254
+ });
255
+ const { refs, x, y, strategy, context, elements } = core.useFloatingUI({
256
+ open,
257
+ onOpenChange(nextOpen, _, reason) {
258
+ setOpen(nextOpen);
259
+ if (!nextOpen) {
260
+ openModalityRef.current = null;
261
+ }
262
+ if (!nextOpen && reason === "escape-key") {
263
+ toolbarNextKeyboardUtils.scheduleToolbarNextFocus(triggerRef.current);
264
+ }
265
+ },
266
+ placement: "bottom-end",
267
+ middleware: [
268
+ react$1.offset(1),
269
+ react$1.size({
270
+ apply({ elements: elements2, availableHeight }) {
271
+ Object.assign(elements2.floating.style, {
272
+ maxHeight: `${availableHeight}px`
273
+ });
274
+ }
275
+ }),
276
+ react$1.flip(),
277
+ react$1.shift({
278
+ padding: 8
279
+ })
280
+ ]
281
+ });
282
+ const { getFloatingProps, getReferenceProps } = react$1.useInteractions([
283
+ react$1.useClick(context),
284
+ react$1.useDismiss(context, {
285
+ escapeKey: false,
286
+ outsidePress(event) {
287
+ return !ToolbarNextOverflowFloatingBoundary.isTargetInsideOverflowBoundary(
288
+ panelContentRef.current,
289
+ floatingBoundary,
290
+ group.key,
291
+ event.target
292
+ );
293
+ }
294
+ })
295
+ ]);
296
+ const handleTriggerKeyDown = react.useCallback(
297
+ (event) => {
298
+ if (!open && ["Enter", " "].includes(event.key)) {
299
+ event.preventDefault();
300
+ openModalityRef.current = "keyboard";
301
+ setOpen(true);
302
+ return;
303
+ }
304
+ if (open && event.key === "Escape") {
305
+ event.preventDefault();
306
+ setOpen(false);
307
+ toolbarNextKeyboardUtils.scheduleToolbarNextFocus(triggerRef.current);
308
+ }
309
+ },
310
+ [open]
311
+ );
312
+ const handleTriggerPointerDown = react.useCallback(
313
+ (event) => {
314
+ if (!open && event.button === 0) {
315
+ openModalityRef.current = "pointer";
316
+ }
317
+ },
318
+ [open]
319
+ );
320
+ const handleTriggerMouseDown = react.useCallback(
321
+ (event) => {
322
+ if (!open && event.button === 0) {
323
+ openModalityRef.current = "pointer";
324
+ }
325
+ },
326
+ [open]
327
+ );
328
+ const handlePanelKeyDown = react.useCallback((event) => {
329
+ var _a2;
330
+ if (event.key === "Tab") {
331
+ const panelContent = panelContentRef.current;
332
+ const target = event.target;
333
+ if (panelContent && target instanceof HTMLElement && toolbarNextKeyboardUtils.shouldToolbarNextPreserveNativeTab(target)) {
334
+ const focusableElements = toolbarNextKeyboardUtils.getDocumentFocusableElements(
335
+ panelContent.ownerDocument
336
+ );
337
+ const currentIndex = focusableElements.indexOf(target);
338
+ const nextFocusTarget = focusableElements[currentIndex + (event.shiftKey ? -1 : 1)];
339
+ if (currentIndex !== -1 && nextFocusTarget && panelContent.contains(nextFocusTarget)) {
340
+ return;
341
+ }
342
+ }
343
+ }
344
+ if (event.key === "Tab" && !event.shiftKey) {
345
+ const toolbarRoot = (_a2 = triggerRef.current) == null ? void 0 : _a2.closest(
346
+ `[${toolbarNextKeyboardUtils.TOOLBAR_NEXT_SCOPE_ROOT_ATTR}]`
347
+ );
348
+ const nextFocusTarget = toolbarRoot ? toolbarNextKeyboardUtils.getToolbarNextTabMoveTarget(toolbarRoot, false) : null;
349
+ if (nextFocusTarget) {
350
+ event.preventDefault();
351
+ event.stopPropagation();
352
+ setOpen(false);
353
+ toolbarNextKeyboardUtils.scheduleToolbarNextFocus(nextFocusTarget);
354
+ }
355
+ return;
356
+ }
357
+ if (event.key === "Tab" && event.shiftKey) {
358
+ event.preventDefault();
359
+ event.stopPropagation();
360
+ setOpen(false);
361
+ toolbarNextKeyboardUtils.scheduleToolbarNextFocus(triggerRef.current);
362
+ return;
363
+ }
364
+ if (event.key === "Escape") {
365
+ event.preventDefault();
366
+ event.stopPropagation();
367
+ setOpen(false);
368
+ toolbarNextKeyboardUtils.scheduleToolbarNextFocus(triggerRef.current);
369
+ }
370
+ }, []);
371
+ const handleTriggerRef = core.useForkRef(
372
+ triggerRef,
373
+ refs.setReference
374
+ );
375
+ const handlePanelRef = core.useForkRef(panelRef, refs.setFloating);
376
+ const handlePanelContentRef = core.useForkRef(
377
+ panelContentRef,
378
+ setPanelContentNode
379
+ );
380
+ const handlePanelFocus = react.useCallback(
381
+ (event) => {
382
+ handleScopeFocus(event);
383
+ const panelContent = panelContentRef.current;
384
+ const target = event.target;
385
+ if (!panelContent || !(target instanceof HTMLElement)) {
386
+ return;
387
+ }
388
+ const focusMemory = toolbarNextKeyboardUtils.getToolbarNextFocusMemory(panelContent, target, {
389
+ includeTabIndexMinusOne: true
390
+ });
391
+ if ((focusMemory == null ? void 0 : focusMemory.type) !== "item") {
392
+ return;
393
+ }
394
+ scrollToolbarNextOverflowTargetIntoView(panelRef.current, target);
395
+ onItemFocus == null ? void 0 : onItemFocus(focusMemory.itemId, focusMemory.controlIndex);
396
+ },
397
+ [handleScopeFocus, onItemFocus]
398
+ );
399
+ const { Component: FloatingComponent } = core.useFloatingComponent();
400
+ react.useEffect(() => {
401
+ if (open && !wasOpenRef.current) {
402
+ const externalFocusMemory = focusMemoryRef == null ? void 0 : focusMemoryRef.current;
403
+ if (canSeedOverflowFocusMemory(externalFocusMemory, group)) {
404
+ rememberedFocusRef.current = externalFocusMemory;
405
+ }
406
+ if (openModalityRef.current !== "pointer") {
407
+ focusEntryTarget();
408
+ }
409
+ }
410
+ wasOpenRef.current = open;
411
+ }, [focusEntryTarget, focusMemoryRef, group, open, rememberedFocusRef]);
412
+ react.useEffect(() => {
413
+ if (!open || !panelContentNode) {
414
+ return;
415
+ }
416
+ const handleFocusIn = (event) => {
417
+ handlePanelFocus(event);
418
+ };
419
+ const handleFocusOut = (event) => {
420
+ if (ToolbarNextOverflowFloatingBoundary.isTargetInsideOverflowBoundary(
421
+ panelContentRef.current,
422
+ floatingBoundary,
423
+ group.key,
424
+ event.relatedTarget
425
+ )) {
426
+ return;
427
+ }
428
+ handleScopeBlur(event);
429
+ };
430
+ const handleKeyDownCapture = (event) => {
431
+ handleScopeKeyDown(event);
432
+ };
433
+ const handlePointerDownCapture = (event) => {
434
+ handleScopePointerDown(event);
435
+ };
436
+ const handleKeyDown = (event) => {
437
+ if (!event.defaultPrevented) {
438
+ handlePanelKeyDown(event);
439
+ }
440
+ };
441
+ panelContentNode.addEventListener("focusin", handleFocusIn);
442
+ panelContentNode.addEventListener("focusout", handleFocusOut);
443
+ panelContentNode.addEventListener("keydown", handleKeyDownCapture, true);
444
+ panelContentNode.addEventListener(
445
+ "pointerdown",
446
+ handlePointerDownCapture,
447
+ true
448
+ );
449
+ panelContentNode.addEventListener("keydown", handleKeyDown);
450
+ return () => {
451
+ panelContentNode.removeEventListener("focusin", handleFocusIn);
452
+ panelContentNode.removeEventListener("focusout", handleFocusOut);
453
+ panelContentNode.removeEventListener(
454
+ "keydown",
455
+ handleKeyDownCapture,
456
+ true
457
+ );
458
+ panelContentNode.removeEventListener(
459
+ "pointerdown",
460
+ handlePointerDownCapture,
461
+ true
462
+ );
463
+ panelContentNode.removeEventListener("keydown", handleKeyDown);
464
+ };
465
+ }, [
466
+ handlePanelFocus,
467
+ handlePanelKeyDown,
468
+ handleScopeBlur,
469
+ handleScopeKeyDown,
470
+ handleScopePointerDown,
471
+ floatingBoundary,
472
+ group.key,
473
+ open,
474
+ panelContentNode
475
+ ]);
476
+ core.useIsomorphicLayoutEffect(() => {
477
+ if (!open) {
478
+ focusedOpenPanelRef.current = false;
479
+ return;
480
+ }
481
+ if (!panelContentNode || focusedOpenPanelRef.current || openModalityRef.current === "pointer") {
482
+ return;
483
+ }
484
+ const getPanelFocusables = () => toolbarNextKeyboardUtils.getToolbarNextScopeFocusableElements(panelContentNode, {
485
+ includeTabIndexMinusOne: true
486
+ });
487
+ const focusEntryWhenReady = () => {
488
+ const panelFocusables = getPanelFocusables();
489
+ if (panelFocusables.length === 0) {
490
+ return false;
491
+ }
492
+ focusedOpenPanelRef.current = true;
493
+ focusEntryTarget();
494
+ return true;
495
+ };
496
+ if (focusEntryWhenReady()) {
497
+ return;
498
+ }
499
+ const panelWindow = panelContentNode.ownerDocument.defaultView;
500
+ const mutationObserverCtor = panelWindow == null ? void 0 : panelWindow.MutationObserver;
501
+ const resizeObserverCtor = panelWindow == null ? void 0 : panelWindow.ResizeObserver;
502
+ let mutationObserver = null;
503
+ let resizeObserver = null;
504
+ mutationObserver = mutationObserverCtor != null ? new mutationObserverCtor(() => {
505
+ if (focusEntryWhenReady()) {
506
+ mutationObserver == null ? void 0 : mutationObserver.disconnect();
507
+ resizeObserver == null ? void 0 : resizeObserver.disconnect();
508
+ }
509
+ }) : null;
510
+ resizeObserver = resizeObserverCtor != null ? new resizeObserverCtor(() => {
511
+ if (focusEntryWhenReady()) {
512
+ mutationObserver == null ? void 0 : mutationObserver.disconnect();
513
+ resizeObserver == null ? void 0 : resizeObserver.disconnect();
514
+ }
515
+ }) : null;
516
+ mutationObserver == null ? void 0 : mutationObserver.observe(panelContentNode, {
517
+ childList: true,
518
+ subtree: true
519
+ });
520
+ resizeObserver == null ? void 0 : resizeObserver.observe(panelContentNode);
521
+ return () => {
522
+ mutationObserver == null ? void 0 : mutationObserver.disconnect();
523
+ resizeObserver == null ? void 0 : resizeObserver.disconnect();
524
+ };
525
+ }, [focusEntryTarget, open, panelContentNode]);
526
+ return /* @__PURE__ */ jsxRuntime.jsxs(
527
+ "div",
528
+ {
529
+ className: withBaseName("menu"),
530
+ "data-overflowgroup": group.overflowGroup,
531
+ children: [
532
+ /* @__PURE__ */ jsxRuntime.jsx(
533
+ core.Button,
534
+ {
535
+ appearance: "transparent",
536
+ "aria-controls": panelId,
537
+ "aria-expanded": open,
538
+ "aria-label": getOverflowTriggerLabel(group),
539
+ className: withBaseName("trigger"),
540
+ ...{
541
+ [toolbarNextKeyboardUtils.TOOLBAR_NEXT_GROUP_KEY_ATTR]: group.key,
542
+ [toolbarNextKeyboardUtils.TOOLBAR_NEXT_OVERFLOW_TRIGGER_ATTR]: ""
543
+ },
544
+ ...getReferenceProps({
545
+ onKeyDown: handleTriggerKeyDown,
546
+ onMouseDown: handleTriggerMouseDown,
547
+ onPointerDown: handleTriggerPointerDown
548
+ }),
549
+ ref: handleTriggerRef,
550
+ sentiment: "neutral",
551
+ children: /* @__PURE__ */ jsxRuntime.jsx(
552
+ ToolbarNextOverflowTriggerContent,
553
+ {
554
+ label: group.label,
555
+ named: group.named
556
+ }
557
+ )
558
+ }
559
+ ),
560
+ /* @__PURE__ */ jsxRuntime.jsx(
561
+ FloatingComponent,
562
+ {
563
+ ...getFloatingProps({
564
+ role: "presentation"
565
+ }),
566
+ className: withBaseName("panel"),
567
+ focusManagerProps: context ? {
568
+ context,
569
+ initialFocus: -1,
570
+ returnFocus: false,
571
+ modal: false,
572
+ closeOnFocusOut: false
573
+ } : void 0,
574
+ id: panelId,
575
+ left: x ?? 0,
576
+ open,
577
+ position: strategy,
578
+ ref: handlePanelRef,
579
+ top: y ?? 0,
580
+ width: (_a = elements.floating) == null ? void 0 : _a.offsetWidth,
581
+ height: (_b = elements.floating) == null ? void 0 : _b.offsetHeight,
582
+ children: /* @__PURE__ */ jsxRuntime.jsx(
583
+ "div",
584
+ {
585
+ "aria-label": `${group.label} overflow`,
586
+ "aria-orientation": "horizontal",
587
+ className: withBaseName("panelContent"),
588
+ ...{ [toolbarNextKeyboardUtils.TOOLBAR_NEXT_SCOPE_ROOT_ATTR]: group.key },
589
+ role: "toolbar",
590
+ ref: handlePanelContentRef,
591
+ children: group.items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
592
+ "div",
593
+ {
594
+ className: withBaseName("panelItem"),
595
+ children: [
596
+ index > 0 && item.leadingDecorations.length > 0 && cloneDecorations(item.id, item.leadingDecorations, "leading"),
597
+ /* @__PURE__ */ jsxRuntime.jsx(
598
+ "div",
599
+ {
600
+ className: withBaseName("itemHost"),
601
+ ref: open ? getItemHostRef(item.id, "overflow") : null
602
+ }
603
+ ),
604
+ cloneDecorations(item.id, item.trailingDecorations, "trailing")
605
+ ]
606
+ },
607
+ `${group.id}-${item.id}`
608
+ ))
609
+ }
610
+ )
611
+ }
612
+ )
613
+ ]
614
+ }
615
+ );
616
+ }
617
+ function ToolbarNextOverflowContent({
618
+ content,
619
+ focusMemoryRef,
620
+ getItemHostRef,
621
+ getItemRef,
622
+ getNamedTriggerRef,
623
+ getContentRef,
624
+ onItemFocus,
625
+ overflowGroups,
626
+ overflowedIds
627
+ }) {
628
+ const targetWindow = window.useWindow();
629
+ styles.useComponentCssInjection({
630
+ testId: "salt-toolbar-next-overflow",
631
+ css: ToolbarNextOverflow,
632
+ window: targetWindow
633
+ });
634
+ const { className, ...contentProps } = content.props;
635
+ const handleContentRef = core.useForkRef(content.ref, getContentRef(content.key));
636
+ const overflowGroupByKey = new Map(
637
+ overflowGroups.map((group) => [group.key, group])
638
+ );
639
+ const renderSlots = toolbarNextUtils.buildContentOverflowRenderSlots(
640
+ content.items,
641
+ overflowedIds,
642
+ new Set(overflowGroups.map((group) => group.key))
643
+ );
644
+ return /* @__PURE__ */ jsxRuntime.jsx(
645
+ ToolbarContentNext.ToolbarContentNext,
646
+ {
647
+ ...contentProps,
648
+ "data-implicit": content.implicit || void 0,
649
+ className: clsx.clsx(className, withBaseName("content")),
650
+ position: content.position,
651
+ ref: handleContentRef,
652
+ children: renderSlots.map(
653
+ ({
654
+ item,
655
+ overflowed,
656
+ showLeadingDecorations,
657
+ showTrailingDecorations,
658
+ triggerGroupKey
659
+ }) => {
660
+ const triggerGroup = triggerGroupKey != null ? overflowGroupByKey.get(triggerGroupKey) : void 0;
661
+ return /* @__PURE__ */ jsxRuntime.jsxs(
662
+ "div",
663
+ {
664
+ className: withBaseName("slot"),
665
+ "data-align": item.align,
666
+ "data-priority": item.overflowPriority,
667
+ ref: triggerGroup ? getNamedTriggerRef(item.id) : getItemRef(item.id),
668
+ children: [
669
+ showLeadingDecorations ? cloneDecorations(item.id, item.leadingDecorations, "leading") : null,
670
+ !overflowed ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: withBaseName("item"), children: /* @__PURE__ */ jsxRuntime.jsx(
671
+ "div",
672
+ {
673
+ className: withBaseName("itemHost"),
674
+ ref: getItemHostRef(item.id, "main")
675
+ }
676
+ ) }) : null,
677
+ triggerGroup ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: withBaseName("item"), children: /* @__PURE__ */ jsxRuntime.jsx(
678
+ ToolbarNextOverflowMenu,
679
+ {
680
+ focusMemoryRef,
681
+ getItemHostRef,
682
+ group: triggerGroup,
683
+ onItemFocus
684
+ }
685
+ ) }) : null,
686
+ showTrailingDecorations ? cloneDecorations(
687
+ item.id,
688
+ item.trailingDecorations,
689
+ "trailing"
690
+ ) : null
691
+ ]
692
+ },
693
+ triggerGroup ? `${content.key}-${triggerGroup.id}-anchor-${item.id}` : item.id
694
+ );
695
+ }
696
+ )
697
+ }
698
+ );
699
+ }
700
+
701
+ exports.ToolbarNextOverflowContent = ToolbarNextOverflowContent;
702
+ exports.ToolbarNextOverflowMenu = ToolbarNextOverflowMenu;
703
+ exports.ToolbarNextOverflowOwners = ToolbarNextOverflowOwners;
704
+ exports.ToolbarNextOverflowTriggerContent = ToolbarNextOverflowTriggerContent;
705
+ //# sourceMappingURL=ToolbarNextOverflow.js.map