@jobber/components 8.14.1 → 8.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/Autocomplete-es.js +1 -1
  2. package/dist/BottomSheet-cjs.js +109 -77
  3. package/dist/BottomSheet-es.js +103 -75
  4. package/dist/Card/index.cjs +2 -3
  5. package/dist/Card/index.mjs +2 -3
  6. package/dist/DataDump/index.cjs +2 -3
  7. package/dist/DataDump/index.mjs +2 -3
  8. package/dist/InputNumberExperimental-cjs.js +16 -17
  9. package/dist/InputNumberExperimental-es.js +2 -3
  10. package/dist/Menu/index.cjs +2 -3
  11. package/dist/Menu/index.mjs +2 -3
  12. package/dist/Menu-cjs.js +11 -56
  13. package/dist/Menu-es.js +4 -49
  14. package/dist/MenuSubmenuTrigger-cjs.js +1608 -1793
  15. package/dist/MenuSubmenuTrigger-es.js +1340 -1522
  16. package/dist/Modal/index.mjs +1 -1
  17. package/dist/NumberFieldInput-cjs.js +53 -54
  18. package/dist/NumberFieldInput-es.js +2 -3
  19. package/dist/Page/index.cjs +2 -3
  20. package/dist/Page/index.mjs +2 -3
  21. package/dist/{DrawerRoot-cjs.js → ScrollAreaViewport-cjs.js} +5488 -4449
  22. package/dist/{DrawerRoot-es.js → ScrollAreaViewport-es.js} +5423 -4393
  23. package/dist/{useValueChanged-cjs.js → clamp-cjs.js} +573 -321
  24. package/dist/{useValueChanged-es.js → clamp-es.js} +569 -322
  25. package/dist/floating-ui.react-es.js +1 -1
  26. package/dist/index.cjs +2 -3
  27. package/dist/index.mjs +2 -3
  28. package/dist/primitives/BottomSheet/BottomSheet.d.ts +15 -16
  29. package/dist/primitives/BottomSheet/BottomSheet.types.d.ts +27 -0
  30. package/dist/primitives/BottomSheet/BottomSheet.utils.d.ts +6 -0
  31. package/dist/primitives/BottomSheet/index.cjs +8 -3
  32. package/dist/primitives/BottomSheet/index.d.ts +1 -0
  33. package/dist/primitives/BottomSheet/index.mjs +8 -3
  34. package/dist/primitives/InputNumberExperimental/index.cjs +2 -3
  35. package/dist/primitives/InputNumberExperimental/index.mjs +2 -3
  36. package/dist/primitives/index.cjs +8 -9
  37. package/dist/primitives/index.mjs +8 -9
  38. package/dist/styles.css +62 -1
  39. package/dist/unstyledPrimitives/index.cjs +6373 -5868
  40. package/dist/unstyledPrimitives/index.d.ts +2 -0
  41. package/dist/unstyledPrimitives/index.mjs +6325 -5822
  42. package/dist/useRenderElement-cjs.js +30 -30
  43. package/dist/useRenderElement-es.js +31 -31
  44. package/package.json +2 -2
  45. package/dist/useBaseUiId-cjs.js +0 -275
  46. package/dist/useBaseUiId-es.js +0 -251
@@ -1,10 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var React = require('react');
4
- var DrawerRoot = require('./DrawerRoot-cjs.js');
4
+ var ScrollAreaViewport = require('./ScrollAreaViewport-cjs.js');
5
5
  var useRenderElement = require('./useRenderElement-cjs.js');
6
- var useValueChanged = require('./useValueChanged-cjs.js');
7
- var useBaseUiId = require('./useBaseUiId-cjs.js');
6
+ var clamp = require('./clamp-cjs.js');
8
7
  var jsxRuntime = require('react/jsx-runtime');
9
8
  var floatingUi_utils_dom = require('./floating-ui.utils.dom-cjs.js');
10
9
  var index_esm = require('./index.esm-cjs.js');
@@ -31,59 +30,8 @@ function _interopNamespaceDefault(e) {
31
30
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
32
31
  var ReactDOM__namespace = /*#__PURE__*/_interopNamespaceDefault(ReactDOM);
33
32
 
34
- /**
35
- * A button that closes the dialog.
36
- * Renders a `<button>` element.
37
- *
38
- * Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
39
- */
40
- const DialogClose = /*#__PURE__*/React__namespace.forwardRef(function DialogClose(componentProps, forwardedRef) {
41
- const {
42
- render,
43
- className,
44
- disabled = false,
45
- nativeButton = true,
46
- ...elementProps
47
- } = componentProps;
48
- const {
49
- store
50
- } = DrawerRoot.useDialogRootContext();
51
- const open = store.useState('open');
52
- function handleClick(event) {
53
- if (open) {
54
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.closePress, event.nativeEvent));
55
- }
56
- }
57
- const {
58
- getButtonProps,
59
- buttonRef
60
- } = useBaseUiId.useButton({
61
- disabled,
62
- native: nativeButton
63
- });
64
- const state = {
65
- disabled
66
- };
67
- return useRenderElement.useRenderElement('button', componentProps, {
68
- state,
69
- ref: [forwardedRef, buttonRef],
70
- props: [{
71
- onClick: handleClick
72
- }, elementProps, getButtonProps]
73
- });
74
- });
75
- if (process.env.NODE_ENV !== "production") DialogClose.displayName = "DialogClose";
76
-
77
- /**
78
- * A button that closes the drawer.
79
- * Renders a `<button>` element.
80
- *
81
- * Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
82
- */
83
- const DrawerClose = DialogClose;
84
-
85
33
  function resolveValue(value, pointerType) {
86
- if (pointerType != null && !useValueChanged.isMouseLikePointerType(pointerType)) {
34
+ if (pointerType != null && !clamp.isMouseLikePointerType(pointerType)) {
87
35
  return 0;
88
36
  }
89
37
  if (typeof value === 'function') {
@@ -108,134 +56,31 @@ function isClickLikeOpenEvent(openEventType, interactedInside) {
108
56
  return interactedInside || openEventType === 'click' || openEventType === 'mousedown';
109
57
  }
110
58
 
111
- /**
112
- * Opens or closes the floating element when clicking the reference element.
113
- * @see https://floating-ui.com/docs/useClick
114
- */
115
- function useClick(context, props = {}) {
116
- const store = 'rootStore' in context ? context.rootStore : context;
117
- const dataRef = store.context.dataRef;
118
- const {
119
- enabled = true,
120
- event: eventOption = 'click',
121
- toggle = true,
122
- ignoreMouse = false,
123
- stickIfOpen = true,
124
- touchOpenDelay = 0,
125
- reason = useValueChanged.triggerPress
126
- } = props;
127
- const pointerTypeRef = React__namespace.useRef(undefined);
128
- const frame = useValueChanged.useAnimationFrame();
129
- const touchOpenTimeout = useValueChanged.useTimeout();
130
- const reference = React__namespace.useMemo(() => ({
131
- onPointerDown(event) {
132
- pointerTypeRef.current = event.pointerType;
133
- },
134
- onMouseDown(event) {
135
- const pointerType = pointerTypeRef.current;
136
- const nativeEvent = event.nativeEvent;
137
- const open = store.select('open');
138
-
139
- // Ignore all buttons except for the "main" button.
140
- // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
141
- if (event.button !== 0 || eventOption === 'click' || useValueChanged.isMouseLikePointerType(pointerType, true) && ignoreMouse) {
142
- return;
143
- }
144
- const openEvent = dataRef.current.openEvent;
145
- const openEventType = openEvent?.type;
146
- const hasClickedOnInactiveTrigger = store.select('domReferenceElement') !== event.currentTarget;
147
- const nextOpen = open && hasClickedOnInactiveTrigger || !(open && toggle && (openEvent && stickIfOpen ? openEventType === 'click' || openEventType === 'mousedown' : true));
148
-
149
- // Animations sometimes won't run on a typeable element if using a rAF.
150
- // Focus is always set on these elements. For touch, we may delay opening.
151
- if (DrawerRoot.isTypeableElement(nativeEvent.target)) {
152
- const details = useValueChanged.createChangeEventDetails(reason, nativeEvent, nativeEvent.target);
153
- if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
154
- touchOpenTimeout.start(touchOpenDelay, () => {
155
- store.setOpen(true, details);
156
- });
157
- } else {
158
- store.setOpen(nextOpen, details);
159
- }
160
- return;
161
- }
162
-
163
- // Capture the currentTarget before the rAF.
164
- // as React sets it to null after the event handler completes.
165
- const eventCurrentTarget = event.currentTarget;
166
-
167
- // Wait until focus is set on the element. This is an alternative to
168
- // `event.preventDefault()` to avoid :focus-visible from appearing when using a pointer.
169
- frame.request(() => {
170
- const details = useValueChanged.createChangeEventDetails(reason, nativeEvent, eventCurrentTarget);
171
- if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
172
- touchOpenTimeout.start(touchOpenDelay, () => {
173
- store.setOpen(true, details);
174
- });
175
- } else {
176
- store.setOpen(nextOpen, details);
177
- }
178
- });
179
- },
180
- onClick(event) {
181
- if (eventOption === 'mousedown-only') {
182
- return;
183
- }
184
- const pointerType = pointerTypeRef.current;
185
- if (eventOption === 'mousedown' && pointerType) {
186
- pointerTypeRef.current = undefined;
187
- return;
188
- }
189
- if (useValueChanged.isMouseLikePointerType(pointerType, true) && ignoreMouse) {
190
- return;
191
- }
192
- const open = store.select('open');
193
- const openEvent = dataRef.current.openEvent;
194
- const hasClickedOnInactiveTrigger = store.select('domReferenceElement') !== event.currentTarget;
195
- const nextOpen = open && hasClickedOnInactiveTrigger || !(open && toggle && (openEvent && stickIfOpen ? useValueChanged.isClickLikeEvent(openEvent) : true));
196
- const details = useValueChanged.createChangeEventDetails(reason, event.nativeEvent, event.currentTarget);
197
- if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
198
- touchOpenTimeout.start(touchOpenDelay, () => {
199
- store.setOpen(true, details);
200
- });
201
- } else {
202
- store.setOpen(nextOpen, details);
203
- }
204
- },
205
- onKeyDown() {
206
- pointerTypeRef.current = undefined;
207
- }
208
- }), [dataRef, eventOption, ignoreMouse, store, stickIfOpen, toggle, frame, touchOpenTimeout, touchOpenDelay, reason]);
209
- return React__namespace.useMemo(() => enabled ? {
210
- reference
211
- } : useRenderElement.EMPTY_OBJECT, [enabled, reference]);
212
- }
213
-
214
59
  function useFloatingRootContext(options) {
215
60
  const {
216
61
  open = false,
217
62
  onOpenChange,
218
63
  elements = {}
219
64
  } = options;
220
- const floatingId = useValueChanged.useId();
221
- const nested = DrawerRoot.useFloatingParentNodeId() != null;
65
+ const floatingId = clamp.useId();
66
+ const nested = ScrollAreaViewport.useFloatingParentNodeId() != null;
222
67
  if (process.env.NODE_ENV !== 'production') {
223
68
  const optionDomReference = elements.reference;
224
69
  if (optionDomReference && !floatingUi_utils_dom.isElement(optionDomReference)) {
225
70
  console.error('Cannot pass a virtual element to the `elements.reference` option,', 'as it must be a real DOM element. Use `context.setPositionReference()`', 'instead.');
226
71
  }
227
72
  }
228
- const store = useRenderElement.useRefWithInit(() => new DrawerRoot.FloatingRootStore({
73
+ const store = useRenderElement.useRefWithInit(() => new ScrollAreaViewport.FloatingRootStore({
229
74
  open,
230
75
  onOpenChange,
231
76
  referenceElement: elements.reference ?? null,
232
77
  floatingElement: elements.floating ?? null,
233
- triggerElements: new DrawerRoot.PopupTriggerMap(),
78
+ triggerElements: new ScrollAreaViewport.PopupTriggerMap(),
234
79
  floatingId,
235
80
  nested,
236
81
  noEmit: false
237
82
  })).current;
238
- useValueChanged.useIsoLayoutEffect(() => {
83
+ clamp.useIsoLayoutEffect(() => {
239
84
  const valuesToSync = {
240
85
  open,
241
86
  floatingId
@@ -275,8 +120,8 @@ function useFloating(options = {}) {
275
120
  };
276
121
  const [positionReference, setPositionReferenceRaw] = React__namespace.useState(null);
277
122
  const domReferenceRef = React__namespace.useRef(null);
278
- const tree = DrawerRoot.useFloatingTree(externalTree);
279
- useValueChanged.useIsoLayoutEffect(() => {
123
+ const tree = ScrollAreaViewport.useFloatingTree(externalTree);
124
+ clamp.useIsoLayoutEffect(() => {
280
125
  if (rootContextElements.domReference) {
281
126
  domReferenceRef.current = rootContextElements.domReference;
282
127
  }
@@ -351,7 +196,7 @@ function useFloating(options = {}) {
351
196
  nodeId,
352
197
  rootStore: rootContext
353
198
  }), [position, refs, elements, nodeId, rootContext, open, floatingId]);
354
- useValueChanged.useIsoLayoutEffect(() => {
199
+ clamp.useIsoLayoutEffect(() => {
355
200
  rootContext.context.dataRef.current.floatingContext = context;
356
201
  const node = tree?.nodesRef.current.find(n => n.id === nodeId);
357
202
  if (node) {
@@ -367,7 +212,7 @@ function useFloating(options = {}) {
367
212
  }), [position, refs, elements, context, rootContext]);
368
213
  }
369
214
 
370
- const isMacSafari = useValueChanged.isMac && useValueChanged.isSafari;
215
+ const isMacSafari = clamp.isMac && clamp.isSafari;
371
216
  /**
372
217
  * Opens the floating element while the reference element has focus, like CSS
373
218
  * `:focus`.
@@ -386,7 +231,7 @@ function useFocus(context, props = {}) {
386
231
  const blockFocusRef = React__namespace.useRef(false);
387
232
  // Track which reference should be blocked from re-opening after Escape/press dismissal.
388
233
  const blockedReferenceRef = React__namespace.useRef(null);
389
- const timeout = useValueChanged.useTimeout();
234
+ const timeout = clamp.useTimeout();
390
235
  const keyboardModalityRef = React__namespace.useRef(true);
391
236
  React__namespace.useEffect(() => {
392
237
  const domReference = store.select('domReferenceElement');
@@ -400,7 +245,7 @@ function useFocus(context, props = {}) {
400
245
  // return to the tab/window.
401
246
  function onBlur() {
402
247
  const currentDomReference = store.select('domReferenceElement');
403
- if (!store.select('open') && floatingUi_utils_dom.isHTMLElement(currentDomReference) && currentDomReference === DrawerRoot.activeElement(useValueChanged.ownerDocument(currentDomReference))) {
248
+ if (!store.select('open') && floatingUi_utils_dom.isHTMLElement(currentDomReference) && currentDomReference === ScrollAreaViewport.activeElement(clamp.ownerDocument(currentDomReference))) {
404
249
  blockFocusRef.current = true;
405
250
  }
406
251
  }
@@ -428,7 +273,7 @@ function useFocus(context, props = {}) {
428
273
  return undefined;
429
274
  }
430
275
  function onOpenChangeLocal(details) {
431
- if (details.reason === useValueChanged.triggerPress || details.reason === useValueChanged.escapeKey) {
276
+ if (details.reason === clamp.triggerPress || details.reason === clamp.escapeKey) {
432
277
  const referenceElement = store.select('domReferenceElement');
433
278
  if (floatingUi_utils_dom.isElement(referenceElement)) {
434
279
  blockedReferenceRef.current = referenceElement;
@@ -455,33 +300,33 @@ function useFocus(context, props = {}) {
455
300
  blockFocusRef.current = false;
456
301
  blockedReferenceRef.current = null;
457
302
  }
458
- const target = DrawerRoot.getTarget(event.nativeEvent);
303
+ const target = ScrollAreaViewport.getTarget(event.nativeEvent);
459
304
  if (floatingUi_utils_dom.isElement(target)) {
460
305
  // Safari fails to match `:focus-visible` if focus was initially
461
306
  // outside the document.
462
307
  if (isMacSafari && !event.relatedTarget) {
463
- if (!keyboardModalityRef.current && !DrawerRoot.isTypeableElement(target)) {
308
+ if (!keyboardModalityRef.current && !ScrollAreaViewport.isTypeableElement(target)) {
464
309
  return;
465
310
  }
466
- } else if (!DrawerRoot.matchesFocusVisible(target)) {
311
+ } else if (!ScrollAreaViewport.matchesFocusVisible(target)) {
467
312
  return;
468
313
  }
469
314
  }
470
- const movedFromOtherEnabledTrigger = DrawerRoot.isTargetInsideEnabledTrigger(event.relatedTarget, store.context.triggerElements);
315
+ const movedFromOtherEnabledTrigger = ScrollAreaViewport.isTargetInsideEnabledTrigger(event.relatedTarget, store.context.triggerElements);
471
316
  const {
472
317
  nativeEvent,
473
318
  currentTarget
474
319
  } = event;
475
320
  const delayValue = typeof delay === 'function' ? delay() : delay;
476
321
  if (store.select('open') && movedFromOtherEnabledTrigger || delayValue === 0 || delayValue === undefined) {
477
- store.setOpen(true, useValueChanged.createChangeEventDetails(useValueChanged.triggerFocus, nativeEvent, currentTarget));
322
+ store.setOpen(true, clamp.createChangeEventDetails(clamp.triggerFocus, nativeEvent, currentTarget));
478
323
  return;
479
324
  }
480
325
  timeout.start(delayValue, () => {
481
326
  if (blockFocusRef.current) {
482
327
  return;
483
328
  }
484
- store.setOpen(true, useValueChanged.createChangeEventDetails(useValueChanged.triggerFocus, nativeEvent, currentTarget));
329
+ store.setOpen(true, clamp.createChangeEventDetails(clamp.triggerFocus, nativeEvent, currentTarget));
485
330
  });
486
331
  },
487
332
  onBlur(event) {
@@ -492,12 +337,12 @@ function useFocus(context, props = {}) {
492
337
 
493
338
  // Hit the non-modal focus management portal guard. Focus will be
494
339
  // moved into the floating element immediately after.
495
- const movedToFocusGuard = floatingUi_utils_dom.isElement(relatedTarget) && relatedTarget.hasAttribute(DrawerRoot.createAttribute('focus-guard')) && relatedTarget.getAttribute('data-type') === 'outside';
340
+ const movedToFocusGuard = floatingUi_utils_dom.isElement(relatedTarget) && relatedTarget.hasAttribute(ScrollAreaViewport.createAttribute('focus-guard')) && relatedTarget.getAttribute('data-type') === 'outside';
496
341
 
497
342
  // Wait for the window blur listener to fire.
498
343
  timeout.start(0, () => {
499
344
  const domReference = store.select('domReferenceElement');
500
- const activeEl = DrawerRoot.activeElement(domReference ? domReference.ownerDocument : document);
345
+ const activeEl = ScrollAreaViewport.activeElement(domReference ? domReference.ownerDocument : document);
501
346
 
502
347
  // Focus left the page, keep it open.
503
348
  if (!relatedTarget && activeEl === domReference) {
@@ -511,7 +356,7 @@ function useFocus(context, props = {}) {
511
356
  // as it will only point to the shadow host of the newly focused element
512
357
  // and not the element that actually has received focus if it is located
513
358
  // inside a shadow root.
514
- if (DrawerRoot.contains(dataRef.current.floatingContext?.refs.floating.current, activeEl) || DrawerRoot.contains(domReference, activeEl) || movedToFocusGuard) {
359
+ if (ScrollAreaViewport.contains(dataRef.current.floatingContext?.refs.floating.current, activeEl) || ScrollAreaViewport.contains(domReference, activeEl) || movedToFocusGuard) {
515
360
  return;
516
361
  }
517
362
 
@@ -519,10 +364,10 @@ function useFocus(context, props = {}) {
519
364
  // the floating element. The focus handler of that trigger will
520
365
  // handle the open state.
521
366
  const nextFocusedElement = relatedTarget ?? activeEl;
522
- if (DrawerRoot.isTargetInsideEnabledTrigger(nextFocusedElement, store.context.triggerElements)) {
367
+ if (ScrollAreaViewport.isTargetInsideEnabledTrigger(nextFocusedElement, store.context.triggerElements)) {
523
368
  return;
524
369
  }
525
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.triggerFocus, nativeEvent));
370
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.triggerFocus, nativeEvent));
526
371
  });
527
372
  }
528
373
  }), [dataRef, store, timeout, delay]);
@@ -532,7 +377,7 @@ function useFocus(context, props = {}) {
532
377
  } : {}, [enabled, reference]);
533
378
  }
534
379
 
535
- const interactiveSelector = `button,a,[role="button"],select,[tabindex]:not([tabindex="-1"]),${DrawerRoot.TYPEABLE_SELECTOR}`;
380
+ const interactiveSelector = `button,a,[role="button"],select,[tabindex]:not([tabindex="-1"]),${ScrollAreaViewport.TYPEABLE_SELECTOR}`;
536
381
  function isInteractiveElement(element) {
537
382
  return element ? Boolean(element.closest(interactiveSelector)) : false;
538
383
  }
@@ -547,8 +392,8 @@ class HoverInteraction {
547
392
  this.pointerEventsReferenceElement = null;
548
393
  this.pointerEventsFloatingElement = null;
549
394
  this.restTimeoutPending = false;
550
- this.openChangeTimeout = new useValueChanged.Timeout();
551
- this.restTimeout = new useValueChanged.Timeout();
395
+ this.openChangeTimeout = new clamp.Timeout();
396
+ this.restTimeout = new clamp.Timeout();
552
397
  this.handleCloseOptions = undefined;
553
398
  }
554
399
  static create() {
@@ -595,7 +440,7 @@ function useHoverInteractionSharedState(store) {
595
440
  if (!data.hoverInteractionState) {
596
441
  data.hoverInteractionState = instance;
597
442
  }
598
- useValueChanged.useOnMount(data.hoverInteractionState.disposeEffect);
443
+ clamp.useOnMount(data.hoverInteractionState.disposeEffect);
599
444
  return data.hoverInteractionState;
600
445
  }
601
446
 
@@ -615,22 +460,22 @@ function useHoverFloatingInteraction(context, parameters = {}) {
615
460
  closeDelay: closeDelayProp = 0
616
461
  } = parameters;
617
462
  const instance = useHoverInteractionSharedState(store);
618
- const tree = DrawerRoot.useFloatingTree();
619
- const parentId = DrawerRoot.useFloatingParentNodeId();
620
- const isClickLikeOpenEvent$1 = useValueChanged.useStableCallback(() => {
463
+ const tree = ScrollAreaViewport.useFloatingTree();
464
+ const parentId = ScrollAreaViewport.useFloatingParentNodeId();
465
+ const isClickLikeOpenEvent$1 = clamp.useStableCallback(() => {
621
466
  return isClickLikeOpenEvent(dataRef.current.openEvent?.type, instance.interactedInside);
622
467
  });
623
- const isHoverOpen = useValueChanged.useStableCallback(() => {
468
+ const isHoverOpen = clamp.useStableCallback(() => {
624
469
  const type = dataRef.current.openEvent?.type;
625
470
  return type?.includes('mouse') && type !== 'mousedown';
626
471
  });
627
- const isRelatedTargetInsideEnabledTrigger = useValueChanged.useStableCallback(target => {
628
- return DrawerRoot.isTargetInsideEnabledTrigger(target, store.context.triggerElements);
472
+ const isRelatedTargetInsideEnabledTrigger = clamp.useStableCallback(target => {
473
+ return ScrollAreaViewport.isTargetInsideEnabledTrigger(target, store.context.triggerElements);
629
474
  });
630
475
  const closeWithDelay = React__namespace.useCallback(event => {
631
476
  const closeDelay = getDelay(closeDelayProp, 'close', instance.pointerType);
632
477
  const close = () => {
633
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.triggerHover, event));
478
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.triggerHover, event));
634
479
  tree?.events.emit('floating.closed', event);
635
480
  };
636
481
  if (closeDelay) {
@@ -640,18 +485,18 @@ function useHoverFloatingInteraction(context, parameters = {}) {
640
485
  close();
641
486
  }
642
487
  }, [closeDelayProp, store, instance, tree]);
643
- const clearPointerEvents = useValueChanged.useStableCallback(() => {
488
+ const clearPointerEvents = clamp.useStableCallback(() => {
644
489
  clearSafePolygonPointerEventsMutation(instance);
645
490
  });
646
- const handleInteractInside = useValueChanged.useStableCallback(event => {
647
- const target = DrawerRoot.getTarget(event);
491
+ const handleInteractInside = clamp.useStableCallback(event => {
492
+ const target = ScrollAreaViewport.getTarget(event);
648
493
  if (!isInteractiveElement(target)) {
649
494
  instance.interactedInside = false;
650
495
  return;
651
496
  }
652
497
  instance.interactedInside = target?.closest('[aria-haspopup]') != null;
653
498
  });
654
- useValueChanged.useIsoLayoutEffect(() => {
499
+ clamp.useIsoLayoutEffect(() => {
655
500
  if (!open) {
656
501
  instance.pointerType = undefined;
657
502
  instance.restTimeoutPending = false;
@@ -662,14 +507,14 @@ function useHoverFloatingInteraction(context, parameters = {}) {
662
507
  React__namespace.useEffect(() => {
663
508
  return clearPointerEvents;
664
509
  }, [clearPointerEvents]);
665
- useValueChanged.useIsoLayoutEffect(() => {
510
+ clamp.useIsoLayoutEffect(() => {
666
511
  if (!enabled) {
667
512
  return undefined;
668
513
  }
669
514
  if (open && instance.handleCloseOptions?.blockPointerEvents && isHoverOpen() && floatingUi_utils_dom.isElement(domReferenceElement) && floatingElement) {
670
515
  const ref = domReferenceElement;
671
516
  const floatingEl = floatingElement;
672
- const doc = useValueChanged.ownerDocument(floatingElement);
517
+ const doc = clamp.ownerDocument(floatingElement);
673
518
  const parentFloating = tree?.nodesRef.current.find(node => node.id === parentId)?.context?.elements.floating;
674
519
  if (parentFloating) {
675
520
  parentFloating.style.pointerEvents = '';
@@ -686,7 +531,7 @@ function useHoverFloatingInteraction(context, parameters = {}) {
686
531
  }
687
532
  return undefined;
688
533
  }, [enabled, open, domReferenceElement, floatingElement, instance, isHoverOpen, tree, parentId, clearPointerEvents]);
689
- const childClosedTimeout = useValueChanged.useTimeout();
534
+ const childClosedTimeout = clamp.useTimeout();
690
535
  React__namespace.useEffect(() => {
691
536
  if (!enabled) {
692
537
  return undefined;
@@ -698,7 +543,7 @@ function useHoverFloatingInteraction(context, parameters = {}) {
698
543
  clearPointerEvents();
699
544
  }
700
545
  function onFloatingMouseLeave(event) {
701
- if (tree && parentId && DrawerRoot.getNodeChildren(tree.nodesRef.current, parentId).length > 0) {
546
+ if (tree && parentId && ScrollAreaViewport.getNodeChildren(tree.nodesRef.current, parentId).length > 0) {
702
547
  tree.events.on('floating.closed', onNodeClosed);
703
548
  return;
704
549
  }
@@ -719,13 +564,13 @@ function useHoverFloatingInteraction(context, parameters = {}) {
719
564
  }
720
565
  }
721
566
  function onNodeClosed(event) {
722
- if (!tree || !parentId || DrawerRoot.getNodeChildren(tree.nodesRef.current, parentId).length > 0) {
567
+ if (!tree || !parentId || ScrollAreaViewport.getNodeChildren(tree.nodesRef.current, parentId).length > 0) {
723
568
  return;
724
569
  }
725
570
  // Allow the mouseenter event to fire in case child was closed because mouse moved into parent.
726
571
  childClosedTimeout.start(0, () => {
727
572
  tree.events.off('floating.closed', onNodeClosed);
728
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.triggerHover, event));
573
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.triggerHover, event));
729
574
  tree.events.emit('floating.closed', event);
730
575
  });
731
576
  }
@@ -772,28 +617,28 @@ function useHoverReferenceInteraction(context, props = {}) {
772
617
  isActiveTrigger = true,
773
618
  getHandleCloseContext
774
619
  } = props;
775
- const tree = DrawerRoot.useFloatingTree(externalTree);
620
+ const tree = ScrollAreaViewport.useFloatingTree(externalTree);
776
621
  const instance = useHoverInteractionSharedState(store);
777
- const handleCloseRef = useValueChanged.useValueAsRef(handleClose);
778
- const delayRef = useValueChanged.useValueAsRef(delay);
779
- const restMsRef = useValueChanged.useValueAsRef(restMs);
780
- const enabledRef = useValueChanged.useValueAsRef(enabled);
622
+ const handleCloseRef = clamp.useValueAsRef(handleClose);
623
+ const delayRef = clamp.useValueAsRef(delay);
624
+ const restMsRef = clamp.useValueAsRef(restMs);
625
+ const enabledRef = clamp.useValueAsRef(enabled);
781
626
  if (isActiveTrigger) {
782
627
  // eslint-disable-next-line no-underscore-dangle
783
628
  instance.handleCloseOptions = handleCloseRef.current?.__options;
784
629
  }
785
- const isClickLikeOpenEvent$1 = useValueChanged.useStableCallback(() => {
630
+ const isClickLikeOpenEvent$1 = clamp.useStableCallback(() => {
786
631
  return isClickLikeOpenEvent(dataRef.current.openEvent?.type, instance.interactedInside);
787
632
  });
788
- const isRelatedTargetInsideEnabledTrigger = useValueChanged.useStableCallback(target => {
789
- return DrawerRoot.isTargetInsideEnabledTrigger(target, store.context.triggerElements);
633
+ const isRelatedTargetInsideEnabledTrigger = clamp.useStableCallback(target => {
634
+ return ScrollAreaViewport.isTargetInsideEnabledTrigger(target, store.context.triggerElements);
790
635
  });
791
- const isOverInactiveTrigger = useValueChanged.useStableCallback((currentDomReference, currentTarget, target) => {
636
+ const isOverInactiveTrigger = clamp.useStableCallback((currentDomReference, currentTarget, target) => {
792
637
  const allTriggers = store.context.triggerElements;
793
638
 
794
639
  // Fast path for normal usage where handlers are attached directly to triggers.
795
640
  if (allTriggers.hasElement(currentTarget)) {
796
- return !currentDomReference || !DrawerRoot.contains(currentDomReference, currentTarget);
641
+ return !currentDomReference || !ScrollAreaViewport.contains(currentDomReference, currentTarget);
797
642
  }
798
643
 
799
644
  // Fallback for delegated/wrapper usage where currentTarget may be outside the trigger map.
@@ -801,31 +646,31 @@ function useHoverReferenceInteraction(context, props = {}) {
801
646
  return false;
802
647
  }
803
648
  const targetElement = target;
804
- return allTriggers.hasMatchingElement(trigger => DrawerRoot.contains(trigger, targetElement)) && (!currentDomReference || !DrawerRoot.contains(currentDomReference, targetElement));
649
+ return allTriggers.hasMatchingElement(trigger => ScrollAreaViewport.contains(trigger, targetElement)) && (!currentDomReference || !ScrollAreaViewport.contains(currentDomReference, targetElement));
805
650
  });
806
651
  const closeWithDelay = React__namespace.useCallback((event, runElseBranch = true) => {
807
652
  const closeDelay = getDelay(delayRef.current, 'close', instance.pointerType);
808
653
  if (closeDelay) {
809
654
  instance.openChangeTimeout.start(closeDelay, () => {
810
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.triggerHover, event));
655
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.triggerHover, event));
811
656
  tree?.events.emit('floating.closed', event);
812
657
  });
813
658
  } else if (runElseBranch) {
814
659
  instance.openChangeTimeout.clear();
815
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.triggerHover, event));
660
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.triggerHover, event));
816
661
  tree?.events.emit('floating.closed', event);
817
662
  }
818
663
  }, [delayRef, store, instance, tree]);
819
- const cleanupMouseMoveHandler = useValueChanged.useStableCallback(() => {
664
+ const cleanupMouseMoveHandler = clamp.useStableCallback(() => {
820
665
  if (!instance.handler) {
821
666
  return;
822
667
  }
823
- const doc = useValueChanged.ownerDocument(store.select('domReferenceElement'));
668
+ const doc = clamp.ownerDocument(store.select('domReferenceElement'));
824
669
  doc.removeEventListener('mousemove', instance.handler);
825
670
  instance.handler = undefined;
826
671
  });
827
672
  React__namespace.useEffect(() => cleanupMouseMoveHandler, [cleanupMouseMoveHandler]);
828
- const clearPointerEvents = useValueChanged.useStableCallback(() => {
673
+ const clearPointerEvents = clamp.useStableCallback(() => {
829
674
  clearSafePolygonPointerEventsMutation(instance);
830
675
  });
831
676
 
@@ -860,7 +705,7 @@ function useHoverReferenceInteraction(context, props = {}) {
860
705
  function onMouseEnter(event) {
861
706
  instance.openChangeTimeout.clear();
862
707
  instance.blockMouseMove = false;
863
- if (mouseOnly && !useValueChanged.isMouseLikePointerType(instance.pointerType)) {
708
+ if (mouseOnly && !clamp.isMouseLikePointerType(instance.pointerType)) {
864
709
  return;
865
710
  }
866
711
 
@@ -879,15 +724,15 @@ function useHoverReferenceInteraction(context, props = {}) {
879
724
 
880
725
  // When moving between triggers while already open, open immediately without delay
881
726
  if (isOverInactive && isOpen) {
882
- store.setOpen(true, useValueChanged.createChangeEventDetails(useValueChanged.triggerHover, event, triggerNode));
727
+ store.setOpen(true, clamp.createChangeEventDetails(clamp.triggerHover, event, triggerNode));
883
728
  } else if (openDelay) {
884
729
  instance.openChangeTimeout.start(openDelay, () => {
885
730
  if (shouldOpen) {
886
- store.setOpen(true, useValueChanged.createChangeEventDetails(useValueChanged.triggerHover, event, triggerNode));
731
+ store.setOpen(true, clamp.createChangeEventDetails(clamp.triggerHover, event, triggerNode));
887
732
  }
888
733
  });
889
734
  } else if (shouldOpen) {
890
- store.setOpen(true, useValueChanged.createChangeEventDetails(useValueChanged.triggerHover, event, triggerNode));
735
+ store.setOpen(true, clamp.createChangeEventDetails(clamp.triggerHover, event, triggerNode));
891
736
  }
892
737
  }
893
738
  function onMouseLeave(event) {
@@ -897,7 +742,7 @@ function useHoverReferenceInteraction(context, props = {}) {
897
742
  }
898
743
  cleanupMouseMoveHandler();
899
744
  const domReferenceElement = store.select('domReferenceElement');
900
- const doc = useValueChanged.ownerDocument(domReferenceElement);
745
+ const doc = clamp.ownerDocument(domReferenceElement);
901
746
  instance.restTimeout.clear();
902
747
  instance.restTimeoutPending = false;
903
748
  const handleCloseContextBase = dataRef.current.floatingContext ?? getHandleCloseContext?.();
@@ -927,7 +772,7 @@ function useHoverReferenceInteraction(context, props = {}) {
927
772
  instance.handler(event);
928
773
  return;
929
774
  }
930
- const shouldClose = instance.pointerType === 'touch' ? !DrawerRoot.contains(store.select('floatingElement'), event.relatedTarget) : true;
775
+ const shouldClose = instance.pointerType === 'touch' ? !ScrollAreaViewport.contains(store.select('floatingElement'), event.relatedTarget) : true;
931
776
  if (shouldClose) {
932
777
  closeWithDelay(event);
933
778
  }
@@ -965,7 +810,7 @@ function useHoverReferenceInteraction(context, props = {}) {
965
810
  const currentDomReference = store.select('domReferenceElement');
966
811
  const currentOpen = store.select('open');
967
812
  const isOverInactive = isOverInactiveTrigger(currentDomReference, trigger, event.target);
968
- if (mouseOnly && !useValueChanged.isMouseLikePointerType(instance.pointerType)) {
813
+ if (mouseOnly && !clamp.isMouseLikePointerType(instance.pointerType)) {
969
814
  return;
970
815
  }
971
816
  const restMsValue = getRestMs(restMsRef.current);
@@ -986,7 +831,7 @@ function useHoverReferenceInteraction(context, props = {}) {
986
831
  }
987
832
  const latestOpen = store.select('open');
988
833
  if (!instance.blockMouseMove && (!latestOpen || isOverInactive)) {
989
- store.setOpen(true, useValueChanged.createChangeEventDetails(useValueChanged.triggerHover, nativeEvent, trigger));
834
+ store.setOpen(true, clamp.createChangeEventDetails(clamp.triggerHover, nativeEvent, trigger));
990
835
  }
991
836
  }
992
837
  if (instance.pointerType === 'touch') {
@@ -1016,23 +861,23 @@ function doSwitch(orientation, vertical, horizontal) {
1016
861
  }
1017
862
  }
1018
863
  function isMainOrientationKey(key, orientation) {
1019
- const vertical = key === DrawerRoot.ARROW_UP || key === DrawerRoot.ARROW_DOWN;
1020
- const horizontal = key === DrawerRoot.ARROW_LEFT || key === DrawerRoot.ARROW_RIGHT;
864
+ const vertical = key === ScrollAreaViewport.ARROW_UP || key === ScrollAreaViewport.ARROW_DOWN;
865
+ const horizontal = key === ScrollAreaViewport.ARROW_LEFT || key === ScrollAreaViewport.ARROW_RIGHT;
1021
866
  return doSwitch(orientation, vertical, horizontal);
1022
867
  }
1023
868
  function isMainOrientationToEndKey(key, orientation, rtl) {
1024
- const vertical = key === DrawerRoot.ARROW_DOWN;
1025
- const horizontal = rtl ? key === DrawerRoot.ARROW_LEFT : key === DrawerRoot.ARROW_RIGHT;
869
+ const vertical = key === ScrollAreaViewport.ARROW_DOWN;
870
+ const horizontal = rtl ? key === ScrollAreaViewport.ARROW_LEFT : key === ScrollAreaViewport.ARROW_RIGHT;
1026
871
  return doSwitch(orientation, vertical, horizontal) || key === 'Enter' || key === ' ' || key === '';
1027
872
  }
1028
873
  function isCrossOrientationOpenKey(key, orientation, rtl) {
1029
- const vertical = rtl ? key === DrawerRoot.ARROW_LEFT : key === DrawerRoot.ARROW_RIGHT;
1030
- const horizontal = key === DrawerRoot.ARROW_DOWN;
874
+ const vertical = rtl ? key === ScrollAreaViewport.ARROW_LEFT : key === ScrollAreaViewport.ARROW_RIGHT;
875
+ const horizontal = key === ScrollAreaViewport.ARROW_DOWN;
1031
876
  return doSwitch(orientation, vertical, horizontal);
1032
877
  }
1033
878
  function isCrossOrientationCloseKey(key, orientation, rtl, cols) {
1034
- const vertical = rtl ? key === DrawerRoot.ARROW_RIGHT : key === DrawerRoot.ARROW_LEFT;
1035
- const horizontal = key === DrawerRoot.ARROW_UP;
879
+ const vertical = rtl ? key === ScrollAreaViewport.ARROW_RIGHT : key === ScrollAreaViewport.ARROW_LEFT;
880
+ const horizontal = key === ScrollAreaViewport.ARROW_UP;
1036
881
  if (orientation === 'both' || orientation === 'horizontal' && cols && cols > 1) {
1037
882
  return key === ESCAPE;
1038
883
  }
@@ -1084,19 +929,19 @@ function useListNavigation(context, props) {
1084
929
  console.warn('In grid list navigation mode (`cols` > 1), the `orientation` should', 'be either "horizontal" or "both".');
1085
930
  }
1086
931
  }
1087
- const floatingFocusElement = DrawerRoot.getFloatingFocusElement(floatingElement);
1088
- const floatingFocusElementRef = useValueChanged.useValueAsRef(floatingFocusElement);
1089
- const parentId = DrawerRoot.useFloatingParentNodeId();
1090
- const tree = DrawerRoot.useFloatingTree(externalTree);
1091
- useValueChanged.useIsoLayoutEffect(() => {
932
+ const floatingFocusElement = ScrollAreaViewport.getFloatingFocusElement(floatingElement);
933
+ const floatingFocusElementRef = clamp.useValueAsRef(floatingFocusElement);
934
+ const parentId = ScrollAreaViewport.useFloatingParentNodeId();
935
+ const tree = ScrollAreaViewport.useFloatingTree(externalTree);
936
+ clamp.useIsoLayoutEffect(() => {
1092
937
  dataRef.current.orientation = orientation;
1093
938
  }, [dataRef, orientation]);
1094
- const typeableComboboxReference = DrawerRoot.isTypeableCombobox(domReferenceElement);
939
+ const typeableComboboxReference = ScrollAreaViewport.isTypeableCombobox(domReferenceElement);
1095
940
  const focusItemOnOpenRef = React__namespace.useRef(focusItemOnOpen);
1096
941
  const indexRef = React__namespace.useRef(selectedIndex ?? -1);
1097
942
  const keyRef = React__namespace.useRef(null);
1098
943
  const isPointerModalityRef = React__namespace.useRef(true);
1099
- const onNavigate = useValueChanged.useStableCallback(event => {
944
+ const onNavigate = clamp.useStableCallback(event => {
1100
945
  onNavigateProp(indexRef.current === -1 ? null : indexRef.current, event);
1101
946
  });
1102
947
  const previousOnNavigateRef = React__namespace.useRef(onNavigate);
@@ -1104,16 +949,16 @@ function useListNavigation(context, props) {
1104
949
  const previousOpenRef = React__namespace.useRef(open);
1105
950
  const forceSyncFocusRef = React__namespace.useRef(false);
1106
951
  const forceScrollIntoViewRef = React__namespace.useRef(false);
1107
- const disabledIndicesRef = useValueChanged.useValueAsRef(disabledIndices);
1108
- const latestOpenRef = useValueChanged.useValueAsRef(open);
1109
- const selectedIndexRef = useValueChanged.useValueAsRef(selectedIndex);
1110
- const resetOnPointerLeaveRef = useValueChanged.useValueAsRef(resetOnPointerLeave);
1111
- const focusItem = useValueChanged.useStableCallback(() => {
952
+ const disabledIndicesRef = clamp.useValueAsRef(disabledIndices);
953
+ const latestOpenRef = clamp.useValueAsRef(open);
954
+ const selectedIndexRef = clamp.useValueAsRef(selectedIndex);
955
+ const resetOnPointerLeaveRef = clamp.useValueAsRef(resetOnPointerLeave);
956
+ const focusItem = clamp.useStableCallback(() => {
1112
957
  function runFocus(item) {
1113
958
  if (virtual) {
1114
959
  tree?.events.emit('virtualfocus', item);
1115
960
  } else {
1116
- DrawerRoot.enqueueFocus(item, {
961
+ ScrollAreaViewport.enqueueFocus(item, {
1117
962
  sync: forceSyncFocusRef.current,
1118
963
  preventScroll: true
1119
964
  });
@@ -1149,7 +994,7 @@ function useListNavigation(context, props) {
1149
994
 
1150
995
  // Sync `selectedIndex` to be the `activeIndex` upon opening the floating
1151
996
  // element. Also, reset `activeIndex` upon closing the floating element.
1152
- useValueChanged.useIsoLayoutEffect(() => {
997
+ clamp.useIsoLayoutEffect(() => {
1153
998
  if (!enabled) {
1154
999
  return;
1155
1000
  }
@@ -1172,7 +1017,7 @@ function useListNavigation(context, props) {
1172
1017
 
1173
1018
  // Sync `activeIndex` to be the focused item while the floating element is
1174
1019
  // open.
1175
- useValueChanged.useIsoLayoutEffect(() => {
1020
+ clamp.useIsoLayoutEffect(() => {
1176
1021
  if (!enabled) {
1177
1022
  return;
1178
1023
  }
@@ -1210,14 +1055,14 @@ function useListNavigation(context, props) {
1210
1055
  runs += 1;
1211
1056
  } else {
1212
1057
  // initially focus the first non-disabled item
1213
- indexRef.current = keyRef.current == null || isMainOrientationToEndKey(keyRef.current, orientation, rtl) || nested ? DrawerRoot.getMinListIndex(listRef) : DrawerRoot.getMaxListIndex(listRef);
1058
+ indexRef.current = keyRef.current == null || isMainOrientationToEndKey(keyRef.current, orientation, rtl) || nested ? ScrollAreaViewport.getMinListIndex(listRef) : ScrollAreaViewport.getMaxListIndex(listRef);
1214
1059
  keyRef.current = null;
1215
1060
  onNavigate();
1216
1061
  }
1217
1062
  };
1218
1063
  waitForListPopulated();
1219
1064
  }
1220
- } else if (!DrawerRoot.isIndexOutOfListBounds(listRef, activeIndex)) {
1065
+ } else if (!ScrollAreaViewport.isIndexOutOfListBounds(listRef, activeIndex)) {
1221
1066
  indexRef.current = activeIndex;
1222
1067
  focusItem();
1223
1068
  forceScrollIntoViewRef.current = false;
@@ -1226,26 +1071,26 @@ function useListNavigation(context, props) {
1226
1071
 
1227
1072
  // Ensure the parent floating element has focus when a nested child closes
1228
1073
  // to allow arrow key navigation to work after the pointer leaves the child.
1229
- useValueChanged.useIsoLayoutEffect(() => {
1074
+ clamp.useIsoLayoutEffect(() => {
1230
1075
  if (!enabled || floatingElement || !tree || virtual || !previousMountedRef.current) {
1231
1076
  return;
1232
1077
  }
1233
1078
  const nodes = tree.nodesRef.current;
1234
1079
  const parent = nodes.find(node => node.id === parentId)?.context?.elements.floating;
1235
- const activeEl = DrawerRoot.activeElement(useValueChanged.ownerDocument(floatingElement));
1236
- const treeContainsActiveEl = nodes.some(node => node.context && DrawerRoot.contains(node.context.elements.floating, activeEl));
1080
+ const activeEl = ScrollAreaViewport.activeElement(clamp.ownerDocument(floatingElement));
1081
+ const treeContainsActiveEl = nodes.some(node => node.context && ScrollAreaViewport.contains(node.context.elements.floating, activeEl));
1237
1082
  if (parent && !treeContainsActiveEl && isPointerModalityRef.current) {
1238
1083
  parent.focus({
1239
1084
  preventScroll: true
1240
1085
  });
1241
1086
  }
1242
1087
  }, [enabled, floatingElement, tree, parentId, virtual]);
1243
- useValueChanged.useIsoLayoutEffect(() => {
1088
+ clamp.useIsoLayoutEffect(() => {
1244
1089
  previousOnNavigateRef.current = onNavigate;
1245
1090
  previousOpenRef.current = open;
1246
1091
  previousMountedRef.current = !!floatingElement;
1247
1092
  });
1248
- useValueChanged.useIsoLayoutEffect(() => {
1093
+ clamp.useIsoLayoutEffect(() => {
1249
1094
  if (!open) {
1250
1095
  keyRef.current = null;
1251
1096
  focusItemOnOpenRef.current = focusItemOnOpen;
@@ -1293,15 +1138,15 @@ function useListNavigation(context, props) {
1293
1138
  if (!resetOnPointerLeaveRef.current) {
1294
1139
  return;
1295
1140
  }
1296
- DrawerRoot.enqueueFocus(null, {
1141
+ ScrollAreaViewport.enqueueFocus(null, {
1297
1142
  sync: true
1298
1143
  });
1299
1144
  indexRef.current = -1;
1300
1145
  onNavigate(event);
1301
1146
  if (!virtual) {
1302
1147
  const floatingFocusEl = floatingFocusElementRef.current;
1303
- const activeEl = DrawerRoot.activeElement(useValueChanged.ownerDocument(floatingFocusEl));
1304
- if (floatingFocusEl && DrawerRoot.contains(floatingFocusEl, activeEl)) {
1148
+ const activeEl = ScrollAreaViewport.activeElement(clamp.ownerDocument(floatingFocusEl));
1149
+ if (floatingFocusEl && ScrollAreaViewport.contains(floatingFocusEl, activeEl)) {
1305
1150
  floatingFocusEl.focus({
1306
1151
  preventScroll: true
1307
1152
  });
@@ -1314,7 +1159,7 @@ function useListNavigation(context, props) {
1314
1159
  const getParentOrientation = React__namespace.useCallback(() => {
1315
1160
  return parentOrientation ?? tree?.nodesRef.current.find(node => node.id === parentId)?.context?.dataRef?.current.orientation;
1316
1161
  }, [parentId, tree, parentOrientation]);
1317
- const commonOnKeyDown = useValueChanged.useStableCallback(event => {
1162
+ const commonOnKeyDown = clamp.useStableCallback(event => {
1318
1163
  isPointerModalityRef.current = false;
1319
1164
  forceSyncFocusRef.current = true;
1320
1165
 
@@ -1336,9 +1181,9 @@ function useListNavigation(context, props) {
1336
1181
  // If the nested list's close key is also the parent navigation key,
1337
1182
  // let the parent navigate. Otherwise, stop propagating the event.
1338
1183
  if (!isMainOrientationKey(event.key, getParentOrientation())) {
1339
- useValueChanged.stopEvent(event);
1184
+ clamp.stopEvent(event);
1340
1185
  }
1341
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.listNavigation, event.nativeEvent));
1186
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.listNavigation, event.nativeEvent));
1342
1187
  if (floatingUi_utils_dom.isHTMLElement(domReferenceElement)) {
1343
1188
  if (virtual) {
1344
1189
  tree?.events.emit('virtualfocus', domReferenceElement);
@@ -1349,16 +1194,16 @@ function useListNavigation(context, props) {
1349
1194
  return;
1350
1195
  }
1351
1196
  const currentIndex = indexRef.current;
1352
- const minIndex = DrawerRoot.getMinListIndex(listRef, disabledIndices);
1353
- const maxIndex = DrawerRoot.getMaxListIndex(listRef, disabledIndices);
1197
+ const minIndex = ScrollAreaViewport.getMinListIndex(listRef, disabledIndices);
1198
+ const maxIndex = ScrollAreaViewport.getMaxListIndex(listRef, disabledIndices);
1354
1199
  if (!typeableComboboxReference) {
1355
1200
  if (event.key === 'Home') {
1356
- useValueChanged.stopEvent(event);
1201
+ clamp.stopEvent(event);
1357
1202
  indexRef.current = minIndex;
1358
1203
  onNavigate(event);
1359
1204
  }
1360
1205
  if (event.key === 'End') {
1361
- useValueChanged.stopEvent(event);
1206
+ clamp.stopEvent(event);
1362
1207
  indexRef.current = maxIndex;
1363
1208
  onNavigate(event);
1364
1209
  }
@@ -1374,11 +1219,11 @@ function useListNavigation(context, props) {
1374
1219
  }));
1375
1220
  // To calculate movements on the grid, we use hypothetical cell indices
1376
1221
  // as if every item was 1x1, then convert back to real indices.
1377
- const cellMap = DrawerRoot.createGridCellMap(sizes, cols);
1378
- const minGridIndex = cellMap.findIndex(index => index != null && !DrawerRoot.isListIndexDisabled(listRef, index, disabledIndices));
1222
+ const cellMap = ScrollAreaViewport.createGridCellMap(sizes, cols);
1223
+ const minGridIndex = cellMap.findIndex(index => index != null && !ScrollAreaViewport.isListIndexDisabled(listRef, index, disabledIndices));
1379
1224
  // last enabled index
1380
- const maxGridIndex = cellMap.reduce((foundIndex, index, cellIndex) => index != null && !DrawerRoot.isListIndexDisabled(listRef, index, disabledIndices) ? cellIndex : foundIndex, -1);
1381
- const index = cellMap[DrawerRoot.getGridNavigatedIndex({
1225
+ const maxGridIndex = cellMap.reduce((foundIndex, index, cellIndex) => index != null && !ScrollAreaViewport.isListIndexDisabled(listRef, index, disabledIndices) ? cellIndex : foundIndex, -1);
1226
+ const index = cellMap[ScrollAreaViewport.getGridNavigatedIndex({
1382
1227
  current: cellMap.map(itemIndex => itemIndex != null ? listRef.current[itemIndex] : null)
1383
1228
  }, {
1384
1229
  event,
@@ -1388,15 +1233,15 @@ function useListNavigation(context, props) {
1388
1233
  cols,
1389
1234
  // treat undefined (empty grid spaces) as disabled indices so we
1390
1235
  // don't end up in them
1391
- disabledIndices: DrawerRoot.getGridCellIndices([...((typeof disabledIndices !== 'function' ? disabledIndices : null) || listRef.current.map((_, listIndex) => DrawerRoot.isListIndexDisabled(listRef, listIndex, disabledIndices) ? listIndex : undefined)), undefined], cellMap),
1236
+ disabledIndices: ScrollAreaViewport.getGridCellIndices([...((typeof disabledIndices !== 'function' ? disabledIndices : null) || listRef.current.map((_, listIndex) => ScrollAreaViewport.isListIndexDisabled(listRef, listIndex, disabledIndices) ? listIndex : undefined)), undefined], cellMap),
1392
1237
  minIndex: minGridIndex,
1393
1238
  maxIndex: maxGridIndex,
1394
- prevIndex: DrawerRoot.getGridCellIndexOfCorner(indexRef.current > maxIndex ? minIndex : indexRef.current, sizes, cellMap, cols,
1239
+ prevIndex: ScrollAreaViewport.getGridCellIndexOfCorner(indexRef.current > maxIndex ? minIndex : indexRef.current, sizes, cellMap, cols,
1395
1240
  // use a corner matching the edge closest to the direction
1396
1241
  // we're moving in so we don't end up in the same item. Prefer
1397
1242
  // top/left over bottom/right.
1398
1243
  // eslint-disable-next-line no-nested-ternary
1399
- event.key === DrawerRoot.ARROW_DOWN ? 'bl' : event.key === (rtl ? DrawerRoot.ARROW_LEFT : DrawerRoot.ARROW_RIGHT) ? 'tr' : 'tl'),
1244
+ event.key === ScrollAreaViewport.ARROW_DOWN ? 'bl' : event.key === (rtl ? ScrollAreaViewport.ARROW_LEFT : ScrollAreaViewport.ARROW_RIGHT) ? 'tr' : 'tl'),
1400
1245
  stopEvent: true
1401
1246
  })];
1402
1247
  if (index != null) {
@@ -1408,10 +1253,10 @@ function useListNavigation(context, props) {
1408
1253
  }
1409
1254
  }
1410
1255
  if (isMainOrientationKey(event.key, orientation)) {
1411
- useValueChanged.stopEvent(event);
1256
+ clamp.stopEvent(event);
1412
1257
 
1413
1258
  // Reset the index if no item is focused.
1414
- if (open && !virtual && DrawerRoot.activeElement(event.currentTarget.ownerDocument) === event.currentTarget) {
1259
+ if (open && !virtual && ScrollAreaViewport.activeElement(event.currentTarget.ownerDocument) === event.currentTarget) {
1415
1260
  indexRef.current = isMainOrientationToEndKey(event.key, orientation, rtl) ? minIndex : maxIndex;
1416
1261
  onNavigate(event);
1417
1262
  return;
@@ -1427,13 +1272,13 @@ function useListNavigation(context, props) {
1427
1272
  indexRef.current = minIndex;
1428
1273
  }
1429
1274
  } else {
1430
- indexRef.current = DrawerRoot.findNonDisabledListIndex(listRef, {
1275
+ indexRef.current = ScrollAreaViewport.findNonDisabledListIndex(listRef, {
1431
1276
  startingIndex: currentIndex,
1432
1277
  disabledIndices
1433
1278
  });
1434
1279
  }
1435
1280
  } else {
1436
- indexRef.current = Math.min(maxIndex, DrawerRoot.findNonDisabledListIndex(listRef, {
1281
+ indexRef.current = Math.min(maxIndex, ScrollAreaViewport.findNonDisabledListIndex(listRef, {
1437
1282
  startingIndex: currentIndex,
1438
1283
  disabledIndices
1439
1284
  }));
@@ -1448,20 +1293,20 @@ function useListNavigation(context, props) {
1448
1293
  indexRef.current = maxIndex;
1449
1294
  }
1450
1295
  } else {
1451
- indexRef.current = DrawerRoot.findNonDisabledListIndex(listRef, {
1296
+ indexRef.current = ScrollAreaViewport.findNonDisabledListIndex(listRef, {
1452
1297
  startingIndex: currentIndex,
1453
1298
  decrement: true,
1454
1299
  disabledIndices
1455
1300
  });
1456
1301
  }
1457
1302
  } else {
1458
- indexRef.current = Math.max(minIndex, DrawerRoot.findNonDisabledListIndex(listRef, {
1303
+ indexRef.current = Math.max(minIndex, ScrollAreaViewport.findNonDisabledListIndex(listRef, {
1459
1304
  startingIndex: currentIndex,
1460
1305
  decrement: true,
1461
1306
  disabledIndices
1462
1307
  }));
1463
1308
  }
1464
- if (DrawerRoot.isIndexOutOfListBounds(listRef, indexRef.current)) {
1309
+ if (ScrollAreaViewport.isIndexOutOfListBounds(listRef, indexRef.current)) {
1465
1310
  indexRef.current = -1;
1466
1311
  }
1467
1312
  onNavigate(event);
@@ -1482,12 +1327,12 @@ function useListNavigation(context, props) {
1482
1327
  // If the event originated from within a nested element (e.g., a Dialog opened from
1483
1328
  // within the menu), don't close the menu. The nested element has its own focus
1484
1329
  // management and should handle the Tab key.
1485
- const target = DrawerRoot.getTarget(event.nativeEvent);
1486
- if (target && !DrawerRoot.contains(floatingFocusElementRef.current, target)) {
1330
+ const target = ScrollAreaViewport.getTarget(event.nativeEvent);
1331
+ if (target && !ScrollAreaViewport.contains(floatingFocusElementRef.current, target)) {
1487
1332
  return;
1488
1333
  }
1489
- useValueChanged.stopEvent(event);
1490
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.focusOut, event.nativeEvent));
1334
+ clamp.stopEvent(event);
1335
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.focusOut, event.nativeEvent));
1491
1336
  if (floatingUi_utils_dom.isHTMLElement(domReferenceElement)) {
1492
1337
  domReferenceElement.focus();
1493
1338
  }
@@ -1502,14 +1347,14 @@ function useListNavigation(context, props) {
1502
1347
  }, [ariaActiveDescendantProp, commonOnKeyDown, floatingFocusElementRef, orientation, typeableComboboxReference, store, open, virtual, domReferenceElement]);
1503
1348
  const trigger = React__namespace.useMemo(() => {
1504
1349
  function checkVirtualMouse(event) {
1505
- if (focusItemOnOpen === 'auto' && useValueChanged.isVirtualClick(event.nativeEvent)) {
1350
+ if (focusItemOnOpen === 'auto' && clamp.isVirtualClick(event.nativeEvent)) {
1506
1351
  focusItemOnOpenRef.current = !virtual;
1507
1352
  }
1508
1353
  }
1509
1354
  function checkVirtualPointer(event) {
1510
1355
  // `pointerdown` fires first, reset the state then perform the checks.
1511
1356
  focusItemOnOpenRef.current = focusItemOnOpen;
1512
- if (focusItemOnOpen === 'auto' && useValueChanged.isVirtualPointerEvent(event.nativeEvent)) {
1357
+ if (focusItemOnOpen === 'auto' && clamp.isVirtualPointerEvent(event.nativeEvent)) {
1513
1358
  focusItemOnOpenRef.current = true;
1514
1359
  }
1515
1360
  }
@@ -1537,12 +1382,12 @@ function useListNavigation(context, props) {
1537
1382
  }
1538
1383
  if (nested) {
1539
1384
  if (isParentCrossOpenKey) {
1540
- useValueChanged.stopEvent(event);
1385
+ clamp.stopEvent(event);
1541
1386
  if (currentOpen) {
1542
- indexRef.current = DrawerRoot.getMinListIndex(listRef, disabledIndicesRef.current);
1387
+ indexRef.current = ScrollAreaViewport.getMinListIndex(listRef, disabledIndicesRef.current);
1543
1388
  onNavigate(event);
1544
1389
  } else {
1545
- store.setOpen(true, useValueChanged.createChangeEventDetails(useValueChanged.listNavigation, event.nativeEvent, event.currentTarget));
1390
+ store.setOpen(true, clamp.createChangeEventDetails(clamp.listNavigation, event.nativeEvent, event.currentTarget));
1546
1391
  }
1547
1392
  }
1548
1393
  return undefined;
@@ -1551,9 +1396,9 @@ function useListNavigation(context, props) {
1551
1396
  if (selectedIndexRef.current != null) {
1552
1397
  indexRef.current = selectedIndexRef.current;
1553
1398
  }
1554
- useValueChanged.stopEvent(event);
1399
+ clamp.stopEvent(event);
1555
1400
  if (!currentOpen && openOnArrowKeyDown) {
1556
- store.setOpen(true, useValueChanged.createChangeEventDetails(useValueChanged.listNavigation, event.nativeEvent, event.currentTarget));
1401
+ store.setOpen(true, clamp.createChangeEventDetails(clamp.listNavigation, event.nativeEvent, event.currentTarget));
1557
1402
  } else {
1558
1403
  commonOnKeyDown(event);
1559
1404
  }
@@ -1608,11 +1453,11 @@ function useTypeahead(context, props) {
1608
1453
  resetMs = 750,
1609
1454
  selectedIndex = null
1610
1455
  } = props;
1611
- const timeout = useValueChanged.useTimeout();
1456
+ const timeout = clamp.useTimeout();
1612
1457
  const stringRef = React__namespace.useRef('');
1613
1458
  const prevIndexRef = React__namespace.useRef(selectedIndex ?? activeIndex ?? -1);
1614
1459
  const matchIndexRef = React__namespace.useRef(null);
1615
- useValueChanged.useIsoLayoutEffect(() => {
1460
+ clamp.useIsoLayoutEffect(() => {
1616
1461
  if (!open && selectedIndex !== null) {
1617
1462
  return;
1618
1463
  }
@@ -1622,13 +1467,13 @@ function useTypeahead(context, props) {
1622
1467
  stringRef.current = '';
1623
1468
  }
1624
1469
  }, [open, selectedIndex, timeout]);
1625
- useValueChanged.useIsoLayoutEffect(() => {
1470
+ clamp.useIsoLayoutEffect(() => {
1626
1471
  // Sync arrow key navigation but not typeahead navigation.
1627
1472
  if (open && stringRef.current === '') {
1628
1473
  prevIndexRef.current = selectedIndex ?? activeIndex ?? -1;
1629
1474
  }
1630
1475
  }, [open, selectedIndex, activeIndex]);
1631
- const setTypingChange = useValueChanged.useStableCallback(value => {
1476
+ const setTypingChange = clamp.useStableCallback(value => {
1632
1477
  if (value) {
1633
1478
  if (!dataRef.current.typing) {
1634
1479
  dataRef.current.typing = value;
@@ -1639,10 +1484,10 @@ function useTypeahead(context, props) {
1639
1484
  onTypingChange?.(value);
1640
1485
  }
1641
1486
  });
1642
- const onKeyDown = useValueChanged.useStableCallback(event => {
1487
+ const onKeyDown = clamp.useStableCallback(event => {
1643
1488
  function isVisible(index) {
1644
1489
  const element = elementsRef?.current[index];
1645
- return !element || DrawerRoot.isElementVisible(element);
1490
+ return !element || ScrollAreaViewport.isElementVisible(element);
1646
1491
  }
1647
1492
  function getMatchingIndex(list, string, startIndex = 0) {
1648
1493
  if (list.length === 0) {
@@ -1663,7 +1508,7 @@ function useTypeahead(context, props) {
1663
1508
  const listContent = listRef.current;
1664
1509
  if (stringRef.current.length > 0 && event.key === ' ') {
1665
1510
  // Space should continue the in-progress typeahead session.
1666
- useValueChanged.stopEvent(event);
1511
+ clamp.stopEvent(event);
1667
1512
  setTypingChange(true);
1668
1513
  }
1669
1514
  if (stringRef.current.length > 0 && stringRef.current[0] !== ' ') {
@@ -1679,7 +1524,7 @@ function useTypeahead(context, props) {
1679
1524
  return;
1680
1525
  }
1681
1526
  if (open && event.key !== ' ') {
1682
- useValueChanged.stopEvent(event);
1527
+ clamp.stopEvent(event);
1683
1528
  setTypingChange(true);
1684
1529
  }
1685
1530
 
@@ -1720,12 +1565,12 @@ function useTypeahead(context, props) {
1720
1565
  setTypingChange(false);
1721
1566
  }
1722
1567
  });
1723
- const onBlur = useValueChanged.useStableCallback(event => {
1568
+ const onBlur = clamp.useStableCallback(event => {
1724
1569
  const next = event.relatedTarget;
1725
1570
  const currentDomReferenceElement = store.select('domReferenceElement');
1726
1571
  const currentFloatingElement = store.select('floatingElement');
1727
- const withinReference = DrawerRoot.contains(currentDomReferenceElement, next);
1728
- const withinFloating = DrawerRoot.contains(currentFloatingElement, next);
1572
+ const withinReference = ScrollAreaViewport.contains(currentDomReferenceElement, next);
1573
+ const withinFloating = ScrollAreaViewport.contains(currentFloatingElement, next);
1729
1574
 
1730
1575
  // Keep the session if focus moves within the composite (reference <-> floating).
1731
1576
  if (withinReference || withinFloating) {
@@ -1797,7 +1642,7 @@ function safePolygon(options = {}) {
1797
1642
  const {
1798
1643
  blockPointerEvents = false
1799
1644
  } = options;
1800
- const timeout = new useValueChanged.Timeout();
1645
+ const timeout = new clamp.Timeout();
1801
1646
  const fn = ({
1802
1647
  x,
1803
1648
  y,
@@ -1845,10 +1690,10 @@ function safePolygon(options = {}) {
1845
1690
  clientX,
1846
1691
  clientY
1847
1692
  } = event;
1848
- const target = DrawerRoot.getTarget(event);
1693
+ const target = ScrollAreaViewport.getTarget(event);
1849
1694
  const isLeave = event.type === 'mouseleave';
1850
- const isOverFloatingEl = DrawerRoot.contains(floating, target);
1851
- const isOverReferenceEl = DrawerRoot.contains(domReference, target);
1695
+ const isOverFloatingEl = ScrollAreaViewport.contains(floating, target);
1696
+ const isOverReferenceEl = ScrollAreaViewport.contains(domReference, target);
1852
1697
  if (isOverFloatingEl) {
1853
1698
  hasLanded = true;
1854
1699
  if (!isLeave) {
@@ -1865,11 +1710,11 @@ function safePolygon(options = {}) {
1865
1710
 
1866
1711
  // Prevent overlapping floating element from being stuck in an open-close
1867
1712
  // loop: https://github.com/floating-ui/floating-ui/issues/1910
1868
- if (isLeave && floatingUi_utils_dom.isElement(event.relatedTarget) && DrawerRoot.contains(floating, event.relatedTarget)) {
1713
+ if (isLeave && floatingUi_utils_dom.isElement(event.relatedTarget) && ScrollAreaViewport.contains(floating, event.relatedTarget)) {
1869
1714
  return undefined;
1870
1715
  }
1871
1716
  function hasOpenChildNode() {
1872
- return Boolean(tree && DrawerRoot.getNodeChildren(tree.nodesRef.current, nodeId).length > 0);
1717
+ return Boolean(tree && ScrollAreaViewport.getNodeChildren(tree.nodesRef.current, nodeId).length > 0);
1873
1718
  }
1874
1719
  function closeIfNoOpenChild() {
1875
1720
  if (!hasOpenChildNode()) {
@@ -1995,1452 +1840,1460 @@ function safePolygon(options = {}) {
1995
1840
  return fn;
1996
1841
  }
1997
1842
 
1998
- /**
1999
- * A heading that labels the dialog.
2000
- * Renders an `<h2>` element.
2001
- *
2002
- * Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
2003
- */
2004
- const DialogTitle = /*#__PURE__*/React__namespace.forwardRef(function DialogTitle(componentProps, forwardedRef) {
2005
- const {
2006
- render,
2007
- className,
2008
- id: idProp,
2009
- ...elementProps
2010
- } = componentProps;
2011
- const {
2012
- store
2013
- } = DrawerRoot.useDialogRootContext();
2014
- const id = useBaseUiId.useBaseUiId(idProp);
2015
- store.useSyncedValueWithCleanup('titleElementId', id);
2016
- return useRenderElement.useRenderElement('h2', componentProps, {
2017
- ref: forwardedRef,
2018
- props: [{
2019
- id
2020
- }, elementProps]
2021
- });
2022
- });
2023
- if (process.env.NODE_ENV !== "production") DialogTitle.displayName = "DialogTitle";
1843
+ function getPseudoElementBounds(element) {
1844
+ const elementRect = element.getBoundingClientRect();
2024
1845
 
2025
- /**
2026
- * A button that opens the dialog.
2027
- * Renders a `<button>` element.
2028
- *
2029
- * Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
2030
- */
2031
- const DialogTrigger = /*#__PURE__*/React__namespace.forwardRef(function DialogTrigger(componentProps, forwardedRef) {
2032
- const {
2033
- render,
2034
- className,
2035
- disabled = false,
2036
- nativeButton = true,
2037
- id: idProp,
2038
- payload,
2039
- handle,
2040
- ...elementProps
2041
- } = componentProps;
2042
- const dialogRootContext = DrawerRoot.useDialogRootContext(true);
2043
- const store = handle?.store ?? dialogRootContext?.store;
2044
- if (!store) {
2045
- throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Dialog.Trigger> must be used within <Dialog.Root> or provided with a handle.' : useRenderElement.formatErrorMessage(79));
1846
+ // Avoid "Not implemented: window.getComputedStyle(elt, pseudoElt)"
1847
+ if (process.env.NODE_ENV !== 'production') {
1848
+ return elementRect;
1849
+ }
1850
+ const beforeStyles = window.getComputedStyle(element, '::before');
1851
+ const afterStyles = window.getComputedStyle(element, '::after');
1852
+ const hasPseudoElements = beforeStyles.content !== 'none' || afterStyles.content !== 'none';
1853
+ if (!hasPseudoElements) {
1854
+ return elementRect;
2046
1855
  }
2047
- const thisTriggerId = useBaseUiId.useBaseUiId(idProp);
2048
- const floatingContext = store.useState('floatingRootContext');
2049
- const isOpenedByThisTrigger = store.useState('isOpenedByTrigger', thisTriggerId);
2050
- const triggerElementRef = React__namespace.useRef(null);
2051
- const {
2052
- registerTrigger,
2053
- isMountedByThisTrigger
2054
- } = DrawerRoot.useTriggerDataForwarding(thisTriggerId, triggerElementRef, store, {
2055
- payload
2056
- });
2057
- const {
2058
- getButtonProps,
2059
- buttonRef
2060
- } = useBaseUiId.useButton({
2061
- disabled,
2062
- native: nativeButton
2063
- });
2064
- const click = useClick(floatingContext, {
2065
- enabled: floatingContext != null
2066
- });
2067
- const localInteractionProps = DrawerRoot.useInteractions([click]);
2068
- const state = {
2069
- disabled,
2070
- open: isOpenedByThisTrigger
2071
- };
2072
- const rootTriggerProps = store.useState('triggerProps', isMountedByThisTrigger);
2073
- return useRenderElement.useRenderElement('button', componentProps, {
2074
- state,
2075
- ref: [buttonRef, forwardedRef, registerTrigger, triggerElementRef],
2076
- props: [localInteractionProps.getReferenceProps(), rootTriggerProps, {
2077
- [DrawerRoot.CLICK_TRIGGER_IDENTIFIER]: '',
2078
- id: thisTriggerId
2079
- }, elementProps, getButtonProps],
2080
- stateAttributesMapping: DrawerRoot.triggerOpenStateMapping
2081
- });
2082
- });
2083
- if (process.env.NODE_ENV !== "production") DialogTrigger.displayName = "DialogTrigger";
2084
-
2085
- /**
2086
- * A heading that labels the drawer.
2087
- * Renders an `<h2>` element.
2088
- *
2089
- * Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
2090
- */
2091
- const DrawerTitle = DialogTitle;
2092
1856
 
2093
- /**
2094
- * A button that opens the drawer.
2095
- * Renders a `<button>` element.
2096
- *
2097
- * Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
2098
- */
2099
- const DrawerTrigger = DialogTrigger;
1857
+ // Get dimensions of pseudo-elements
1858
+ const beforeWidth = parseFloat(beforeStyles.width) || 0;
1859
+ const beforeHeight = parseFloat(beforeStyles.height) || 0;
1860
+ const afterWidth = parseFloat(afterStyles.width) || 0;
1861
+ const afterHeight = parseFloat(afterStyles.height) || 0;
2100
1862
 
2101
- const MenuPositionerContext = /*#__PURE__*/React__namespace.createContext(undefined);
2102
- if (process.env.NODE_ENV !== "production") MenuPositionerContext.displayName = "MenuPositionerContext";
2103
- function useMenuPositionerContext(optional) {
2104
- const context = React__namespace.useContext(MenuPositionerContext);
2105
- if (context === undefined && !optional) {
2106
- throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: MenuPositionerContext is missing. MenuPositioner parts must be placed within <Menu.Positioner>.' : useRenderElement.formatErrorMessage(33));
2107
- }
2108
- return context;
2109
- }
1863
+ // Calculate max dimensions including pseudo-elements
1864
+ const totalWidth = Math.max(elementRect.width, beforeWidth, afterWidth);
1865
+ const totalHeight = Math.max(elementRect.height, beforeHeight, afterHeight);
2110
1866
 
2111
- const MenuRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
2112
- if (process.env.NODE_ENV !== "production") MenuRootContext.displayName = "MenuRootContext";
2113
- function useMenuRootContext(optional) {
2114
- const context = React__namespace.useContext(MenuRootContext);
2115
- if (context === undefined && !optional) {
2116
- throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: MenuRootContext is missing. Menu parts must be placed within <Menu.Root>.' : useRenderElement.formatErrorMessage(36));
2117
- }
2118
- return context;
1867
+ // Calculate the differences to extend the bounds
1868
+ const widthDiff = totalWidth - elementRect.width;
1869
+ const heightDiff = totalHeight - elementRect.height;
1870
+ return {
1871
+ left: elementRect.left - widthDiff / 2,
1872
+ right: elementRect.right + widthDiff / 2,
1873
+ top: elementRect.top - heightDiff / 2,
1874
+ bottom: elementRect.bottom + heightDiff / 2
1875
+ };
2119
1876
  }
2120
1877
 
2121
- const ContextMenuRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
2122
- if (process.env.NODE_ENV !== "production") ContextMenuRootContext.displayName = "ContextMenuRootContext";
2123
- function useContextMenuRootContext(optional = true) {
2124
- const context = React__namespace.useContext(ContextMenuRootContext);
2125
- if (context === undefined && !optional) {
2126
- throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: ContextMenuRootContext is missing. ContextMenu parts must be placed within <ContextMenu.Root>.' : useRenderElement.formatErrorMessage(25));
1878
+ const CompositeListContext = /*#__PURE__*/React__namespace.createContext({
1879
+ register: () => {},
1880
+ unregister: () => {},
1881
+ subscribeMapChange: () => {
1882
+ return () => {};
1883
+ },
1884
+ elementsRef: {
1885
+ current: []
1886
+ },
1887
+ nextIndexRef: {
1888
+ current: 0
2127
1889
  }
2128
- return context;
1890
+ });
1891
+ if (process.env.NODE_ENV !== "production") CompositeListContext.displayName = "CompositeListContext";
1892
+ function useCompositeListContext() {
1893
+ return React__namespace.useContext(CompositeListContext);
2129
1894
  }
2130
1895
 
1896
+ /* eslint-disable no-bitwise */
2131
1897
  /**
2132
- * Returns common props shared by all menu item types.
2133
- * This hook extracts the shared logic for id, role, tabIndex, onKeyDown,
2134
- * onMouseMove, onClick, and onMouseUp handlers.
1898
+ * Provides context for a list of items in a composite component.
1899
+ * @internal
2135
1900
  */
2136
- function useMenuItemCommonProps(params) {
2137
- const {
2138
- closeOnClick,
2139
- highlighted,
2140
- id,
2141
- nodeId,
2142
- store,
2143
- typingRef,
2144
- itemRef,
2145
- itemMetadata
2146
- } = params;
1901
+ function CompositeList(props) {
2147
1902
  const {
2148
- events: menuEvents
2149
- } = store.useState('floatingTreeRoot');
2150
- const contextMenuContext = useContextMenuRootContext(true);
2151
- const isContextMenu = contextMenuContext !== undefined;
2152
- return React__namespace.useMemo(() => ({
2153
- id,
2154
- role: 'menuitem',
2155
- tabIndex: highlighted ? 0 : -1,
2156
- onKeyDown(event) {
2157
- if (event.key === ' ' && typingRef?.current) {
2158
- event.preventDefault();
2159
- }
2160
- },
2161
- onMouseMove(event) {
2162
- if (!nodeId) {
2163
- return;
2164
- }
1903
+ children,
1904
+ elementsRef,
1905
+ labelsRef,
1906
+ onMapChange: onMapChangeProp
1907
+ } = props;
1908
+ const onMapChange = clamp.useStableCallback(onMapChangeProp);
1909
+ const nextIndexRef = React__namespace.useRef(0);
1910
+ const listeners = useRenderElement.useRefWithInit(createListeners).current;
2165
1911
 
2166
- // Inform the floating tree that a menu item within this menu was hovered/moved over
2167
- // so unrelated descendant submenus can be closed.
2168
- menuEvents.emit('itemhover', {
2169
- nodeId,
2170
- target: event.currentTarget
1912
+ // We use a stable `map` to avoid O(n^2) re-allocation costs for large lists.
1913
+ // `mapTick` is our re-render trigger mechanism. We also need to update the
1914
+ // elements and label refs, but there's a lot of async work going on and sometimes
1915
+ // the effect that handles `onMapChange` gets called after those refs have been
1916
+ // filled, and we don't want to lose those values by setting their lengths to `0`.
1917
+ // We also need to have them at the proper length because floating-ui uses that
1918
+ // information for list navigation.
1919
+
1920
+ const map = useRenderElement.useRefWithInit(createMap).current;
1921
+ // `mapTick` uses a counter rather than objects for low precision-loss risk and better memory efficiency
1922
+ const [mapTick, setMapTick] = React__namespace.useState(0);
1923
+ const lastTickRef = React__namespace.useRef(mapTick);
1924
+ const register = clamp.useStableCallback((node, metadata) => {
1925
+ map.set(node, metadata ?? null);
1926
+ lastTickRef.current += 1;
1927
+ setMapTick(lastTickRef.current);
1928
+ });
1929
+ const unregister = clamp.useStableCallback(node => {
1930
+ map.delete(node);
1931
+ lastTickRef.current += 1;
1932
+ setMapTick(lastTickRef.current);
1933
+ });
1934
+ const sortedMap = React__namespace.useMemo(() => {
1935
+ const newMap = new Map();
1936
+ // Filter out disconnected elements before sorting to avoid inconsistent
1937
+ // compareDocumentPosition results when elements are detached from the DOM.
1938
+ const sortedNodes = Array.from(map.keys()).filter(node => node.isConnected).sort(sortByDocumentPosition);
1939
+ sortedNodes.forEach((node, index) => {
1940
+ const metadata = map.get(node) ?? {};
1941
+ newMap.set(node, {
1942
+ ...metadata,
1943
+ index
2171
1944
  });
2172
- },
2173
- onClick(event) {
2174
- if (closeOnClick) {
2175
- menuEvents.emit('close', {
2176
- domEvent: event,
2177
- reason: useValueChanged.itemPress
1945
+ });
1946
+ return newMap;
1947
+ }, [map, mapTick]);
1948
+ clamp.useIsoLayoutEffect(() => {
1949
+ if (typeof MutationObserver !== 'function' || sortedMap.size === 0) {
1950
+ return undefined;
1951
+ }
1952
+ const mutationObserver = new MutationObserver(entries => {
1953
+ const diff = new Set();
1954
+ const updateDiff = node => diff.has(node) ? diff.delete(node) : diff.add(node);
1955
+ entries.forEach(entry => {
1956
+ entry.removedNodes.forEach(updateDiff);
1957
+ entry.addedNodes.forEach(updateDiff);
1958
+ });
1959
+ if (diff.size === 0) {
1960
+ lastTickRef.current += 1;
1961
+ setMapTick(lastTickRef.current);
1962
+ }
1963
+ });
1964
+ sortedMap.forEach((_, node) => {
1965
+ if (node.parentElement) {
1966
+ mutationObserver.observe(node.parentElement, {
1967
+ childList: true
2178
1968
  });
2179
1969
  }
2180
- },
2181
- onMouseUp(event) {
2182
- if (contextMenuContext) {
2183
- const initialCursorPoint = contextMenuContext.initialCursorPointRef.current;
2184
- contextMenuContext.initialCursorPointRef.current = null;
2185
- if (isContextMenu && initialCursorPoint && Math.abs(event.clientX - initialCursorPoint.x) <= 1 && Math.abs(event.clientY - initialCursorPoint.y) <= 1) {
2186
- return;
2187
- }
2188
-
2189
- // On non-macOS platforms, this mouseup belongs to the right-click gesture
2190
- // that opened the context menu, so it must not activate an item.
2191
- if (isContextMenu && !useValueChanged.isMac && event.button === 2) {
2192
- return;
2193
- }
1970
+ });
1971
+ return () => {
1972
+ mutationObserver.disconnect();
1973
+ };
1974
+ }, [sortedMap]);
1975
+ clamp.useIsoLayoutEffect(() => {
1976
+ const shouldUpdateLengths = lastTickRef.current === mapTick;
1977
+ if (shouldUpdateLengths) {
1978
+ if (elementsRef.current.length !== sortedMap.size) {
1979
+ elementsRef.current.length = sortedMap.size;
2194
1980
  }
2195
- if (itemRef.current && store.context.allowMouseUpTriggerRef.current && (!isContextMenu || event.button === 2)) {
2196
- // This fires whenever the user clicks on the trigger, moves the cursor, and releases it over the item.
2197
- // We trigger the click and override the `closeOnClick` preference to always close the menu.
2198
- if (!itemMetadata || itemMetadata.type === 'regular-item') {
2199
- itemRef.current.click();
2200
- }
1981
+ if (labelsRef && labelsRef.current.length !== sortedMap.size) {
1982
+ labelsRef.current.length = sortedMap.size;
2201
1983
  }
1984
+ nextIndexRef.current = sortedMap.size;
2202
1985
  }
2203
- }), [closeOnClick, highlighted, id, menuEvents, nodeId, store, typingRef, itemRef, contextMenuContext, isContextMenu, itemMetadata]);
2204
- }
2205
-
2206
- const REGULAR_ITEM = {
2207
- type: 'regular-item'
2208
- };
2209
- function useMenuItem(params) {
2210
- const {
2211
- closeOnClick,
2212
- disabled = false,
2213
- highlighted,
2214
- id,
2215
- store,
2216
- typingRef = store.context.typingRef,
2217
- nativeButton,
2218
- itemMetadata,
2219
- nodeId
2220
- } = params;
2221
- const itemRef = React__namespace.useRef(null);
2222
- const {
2223
- getButtonProps,
2224
- buttonRef
2225
- } = useBaseUiId.useButton({
2226
- disabled,
2227
- focusableWhenDisabled: true,
2228
- native: nativeButton,
2229
- composite: true
1986
+ onMapChange(sortedMap);
1987
+ }, [onMapChange, sortedMap, elementsRef, labelsRef, mapTick]);
1988
+ clamp.useIsoLayoutEffect(() => {
1989
+ return () => {
1990
+ elementsRef.current = [];
1991
+ };
1992
+ }, [elementsRef]);
1993
+ clamp.useIsoLayoutEffect(() => {
1994
+ return () => {
1995
+ if (labelsRef) {
1996
+ labelsRef.current = [];
1997
+ }
1998
+ };
1999
+ }, [labelsRef]);
2000
+ const subscribeMapChange = clamp.useStableCallback(fn => {
2001
+ listeners.add(fn);
2002
+ return () => {
2003
+ listeners.delete(fn);
2004
+ };
2230
2005
  });
2231
- const commonProps = useMenuItemCommonProps({
2232
- closeOnClick,
2233
- highlighted,
2234
- id,
2235
- nodeId,
2236
- store,
2237
- typingRef,
2238
- itemRef,
2239
- itemMetadata
2006
+ clamp.useIsoLayoutEffect(() => {
2007
+ listeners.forEach(l => l(sortedMap));
2008
+ }, [listeners, sortedMap]);
2009
+ const contextValue = React__namespace.useMemo(() => ({
2010
+ register,
2011
+ unregister,
2012
+ subscribeMapChange,
2013
+ elementsRef,
2014
+ labelsRef,
2015
+ nextIndexRef
2016
+ }), [register, unregister, subscribeMapChange, elementsRef, labelsRef, nextIndexRef]);
2017
+ return /*#__PURE__*/jsxRuntime.jsx(CompositeListContext.Provider, {
2018
+ value: contextValue,
2019
+ children: children
2240
2020
  });
2241
- const getItemProps = React__namespace.useCallback(externalProps => {
2242
- return useRenderElement.mergeProps(commonProps, {
2243
- onMouseEnter() {
2244
- if (itemMetadata.type !== 'submenu-trigger') {
2245
- return;
2246
- }
2247
- itemMetadata.setActive();
2248
- }
2249
- }, externalProps, getButtonProps);
2250
- }, [commonProps, getButtonProps, itemMetadata]);
2251
- const mergedRef = useRenderElement.useMergedRefs(itemRef, buttonRef);
2252
- return React__namespace.useMemo(() => ({
2253
- getItemProps,
2254
- itemRef: mergedRef
2255
- }), [getItemProps, mergedRef]);
2256
2021
  }
2257
-
2258
- const CompositeListContext = /*#__PURE__*/React__namespace.createContext({
2259
- register: () => {},
2260
- unregister: () => {},
2261
- subscribeMapChange: () => {
2262
- return () => {};
2263
- },
2264
- elementsRef: {
2265
- current: []
2266
- },
2267
- nextIndexRef: {
2268
- current: 0
2022
+ function createMap() {
2023
+ return new Map();
2024
+ }
2025
+ function createListeners() {
2026
+ return new Set();
2027
+ }
2028
+ function sortByDocumentPosition(a, b) {
2029
+ const position = a.compareDocumentPosition(b);
2030
+ if (position & Node.DOCUMENT_POSITION_FOLLOWING || position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
2031
+ return -1;
2269
2032
  }
2270
- });
2271
- if (process.env.NODE_ENV !== "production") CompositeListContext.displayName = "CompositeListContext";
2272
- function useCompositeListContext() {
2273
- return React__namespace.useContext(CompositeListContext);
2033
+ if (position & Node.DOCUMENT_POSITION_PRECEDING || position & Node.DOCUMENT_POSITION_CONTAINS) {
2034
+ return 1;
2035
+ }
2036
+ return 0;
2274
2037
  }
2275
2038
 
2276
- let IndexGuessBehavior = /*#__PURE__*/function (IndexGuessBehavior) {
2277
- IndexGuessBehavior[IndexGuessBehavior["None"] = 0] = "None";
2278
- IndexGuessBehavior[IndexGuessBehavior["GuessFromOrder"] = 1] = "GuessFromOrder";
2279
- return IndexGuessBehavior;
2280
- }({});
2281
-
2282
2039
  /**
2283
- * Used to register a list item and its index (DOM position) in the `CompositeList`.
2040
+ * Fork of the original `arrow` middleware from Floating UI that allows
2041
+ * configuring the offset parent.
2284
2042
  */
2285
- function useCompositeListItem(params = {}) {
2286
- const {
2287
- label,
2288
- metadata,
2289
- textRef,
2290
- indexGuessBehavior,
2291
- index: externalIndex
2292
- } = params;
2293
- const {
2294
- register,
2295
- unregister,
2296
- subscribeMapChange,
2297
- elementsRef,
2298
- labelsRef,
2299
- nextIndexRef
2300
- } = useCompositeListContext();
2301
- const indexRef = React__namespace.useRef(-1);
2302
- const [index, setIndex] = React__namespace.useState(externalIndex ?? (indexGuessBehavior === IndexGuessBehavior.GuessFromOrder ? () => {
2303
- if (indexRef.current === -1) {
2304
- const newIndex = nextIndexRef.current;
2305
- nextIndexRef.current += 1;
2306
- indexRef.current = newIndex;
2307
- }
2308
- return indexRef.current;
2309
- } : -1));
2310
- const componentRef = React__namespace.useRef(null);
2311
- const ref = React__namespace.useCallback(node => {
2312
- componentRef.current = node;
2313
- if (index !== -1 && node !== null) {
2314
- elementsRef.current[index] = node;
2315
- if (labelsRef) {
2316
- const isLabelDefined = label !== undefined;
2317
- labelsRef.current[index] = isLabelDefined ? label : textRef?.current?.textContent ?? node.textContent;
2318
- }
2319
- }
2320
- }, [index, elementsRef, labelsRef, label, textRef]);
2321
- useValueChanged.useIsoLayoutEffect(() => {
2322
- if (externalIndex != null) {
2323
- return undefined;
2324
- }
2325
- const node = componentRef.current;
2326
- if (node) {
2327
- register(node, metadata);
2328
- return () => {
2329
- unregister(node);
2330
- };
2043
+ const baseArrow = options => ({
2044
+ name: 'arrow',
2045
+ options,
2046
+ async fn(state) {
2047
+ const {
2048
+ x,
2049
+ y,
2050
+ placement,
2051
+ rects,
2052
+ platform,
2053
+ elements,
2054
+ middlewareData
2055
+ } = state;
2056
+ // Since `element` is required, we don't Partial<> the type.
2057
+ const {
2058
+ element,
2059
+ padding = 0,
2060
+ offsetParent = 'real'
2061
+ } = index_esm.evaluate(options, state) || {};
2062
+ if (element == null) {
2063
+ return {};
2331
2064
  }
2332
- return undefined;
2333
- }, [externalIndex, register, unregister, metadata]);
2334
- useValueChanged.useIsoLayoutEffect(() => {
2335
- if (externalIndex != null) {
2336
- return undefined;
2065
+ const paddingObject = index_esm.getPaddingObject(padding);
2066
+ const coords = {
2067
+ x,
2068
+ y
2069
+ };
2070
+ const axis = index_esm.getAlignmentAxis(placement);
2071
+ const length = index_esm.getAxisLength(axis);
2072
+ const arrowDimensions = await platform.getDimensions(element);
2073
+ const isYAxis = axis === 'y';
2074
+ const minProp = isYAxis ? 'top' : 'left';
2075
+ const maxProp = isYAxis ? 'bottom' : 'right';
2076
+ const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';
2077
+ const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];
2078
+ const startDiff = coords[axis] - rects.reference[axis];
2079
+ const arrowOffsetParent = offsetParent === 'real' ? await platform.getOffsetParent?.(element) : elements.floating;
2080
+ let clientSize = elements.floating[clientProp] || rects.floating[length];
2081
+
2082
+ // DOM platform can return `window` as the `offsetParent`.
2083
+ if (!clientSize || !(await platform.isElement?.(arrowOffsetParent))) {
2084
+ clientSize = elements.floating[clientProp] || rects.floating[length];
2337
2085
  }
2338
- return subscribeMapChange(map => {
2339
- const i = componentRef.current ? map.get(componentRef.current)?.index : null;
2340
- if (i != null) {
2341
- setIndex(i);
2342
- }
2343
- });
2344
- }, [externalIndex, subscribeMapChange, setIndex]);
2345
- return React__namespace.useMemo(() => ({
2346
- ref,
2347
- index
2348
- }), [index, ref]);
2349
- }
2086
+ const centerToReference = endDiff / 2 - startDiff / 2;
2350
2087
 
2351
- let MenuCheckboxItemDataAttributes = /*#__PURE__*/function (MenuCheckboxItemDataAttributes) {
2352
- /**
2353
- * Present when the menu checkbox item is checked.
2354
- */
2355
- MenuCheckboxItemDataAttributes["checked"] = "data-checked";
2356
- /**
2357
- * Present when the menu checkbox item is not checked.
2358
- */
2359
- MenuCheckboxItemDataAttributes["unchecked"] = "data-unchecked";
2360
- /**
2361
- * Present when the menu checkbox item is disabled.
2362
- */
2363
- MenuCheckboxItemDataAttributes["disabled"] = "data-disabled";
2364
- /**
2365
- * Present when the menu checkbox item is highlighted.
2366
- */
2367
- MenuCheckboxItemDataAttributes["highlighted"] = "data-highlighted";
2368
- return MenuCheckboxItemDataAttributes;
2369
- }({});
2088
+ // If the padding is large enough that it causes the arrow to no longer be
2089
+ // centered, modify the padding so that it is centered.
2090
+ const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;
2091
+ const minPadding = Math.min(paddingObject[minProp], largestPossiblePadding);
2092
+ const maxPadding = Math.min(paddingObject[maxProp], largestPossiblePadding);
2370
2093
 
2371
- const itemMapping = {
2372
- checked(value) {
2373
- if (value) {
2374
- return {
2375
- [MenuCheckboxItemDataAttributes.checked]: ''
2376
- };
2377
- }
2094
+ // Make sure the arrow doesn't overflow the floating element if the center
2095
+ // point is outside the floating element's bounds.
2096
+ const min = minPadding;
2097
+ const max = clientSize - arrowDimensions[length] - maxPadding;
2098
+ const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
2099
+ const offset = index_esm.clamp(min, center, max);
2100
+
2101
+ // If the reference is small enough that the arrow's padding causes it to
2102
+ // to point to nothing for an aligned placement, adjust the offset of the
2103
+ // floating element itself. To ensure `shift()` continues to take action,
2104
+ // a single reset is performed when this is true.
2105
+ const shouldAddOffset = !middlewareData.arrow && index_esm.getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
2106
+ // eslint-disable-next-line no-nested-ternary
2107
+ const alignmentOffset = shouldAddOffset ? center < min ? center - min : center - max : 0;
2378
2108
  return {
2379
- [MenuCheckboxItemDataAttributes.unchecked]: ''
2109
+ [axis]: coords[axis] + alignmentOffset,
2110
+ data: {
2111
+ [axis]: offset,
2112
+ centerOffset: center - offset - alignmentOffset,
2113
+ ...(shouldAddOffset && {
2114
+ alignmentOffset
2115
+ })
2116
+ },
2117
+ reset: shouldAddOffset
2380
2118
  };
2381
- },
2382
- ...useValueChanged.transitionStatusMapping
2383
- };
2384
-
2385
- const MenuGroupContext = /*#__PURE__*/React__namespace.createContext(undefined);
2386
- if (process.env.NODE_ENV !== "production") MenuGroupContext.displayName = "MenuGroupContext";
2387
- function useMenuGroupRootContext() {
2388
- const context = React__namespace.useContext(MenuGroupContext);
2389
- if (context === undefined) {
2390
- throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: MenuGroupRootContext is missing. Menu group parts must be used within <Menu.Group>.' : useRenderElement.formatErrorMessage(31));
2391
2119
  }
2392
- return context;
2393
- }
2394
-
2395
- const MenuGroup = /*#__PURE__*/React__namespace.forwardRef(function MenuGroup(componentProps, forwardedRef) {
2396
- const {
2397
- render,
2398
- className,
2399
- ...elementProps
2400
- } = componentProps;
2401
- const [labelId, setLabelId] = React__namespace.useState(undefined);
2402
- const context = React__namespace.useMemo(() => ({
2403
- setLabelId
2404
- }), [setLabelId]);
2405
- const element = useRenderElement.useRenderElement('div', componentProps, {
2406
- ref: forwardedRef,
2407
- props: {
2408
- role: 'group',
2409
- 'aria-labelledby': labelId,
2410
- ...elementProps
2411
- }
2412
- });
2413
- return /*#__PURE__*/jsxRuntime.jsx(MenuGroupContext.Provider, {
2414
- value: context,
2415
- children: element
2416
- });
2417
2120
  });
2418
- if (process.env.NODE_ENV !== "production") MenuGroup.displayName = "MenuGroup";
2419
2121
 
2420
2122
  /**
2421
- * An accessible label that is automatically associated with its parent group.
2422
- * Renders a `<div>` element.
2423
- *
2424
- * Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
2123
+ * Provides data to position an inner element of the floating element so that it
2124
+ * appears centered to the reference element.
2125
+ * This wraps the core `arrow` middleware to allow React refs as the element.
2126
+ * @see https://floating-ui.com/docs/arrow
2425
2127
  */
2426
- const MenuGroupLabel = /*#__PURE__*/React__namespace.forwardRef(function MenuGroupLabelComponent(componentProps, forwardedRef) {
2427
- const {
2428
- className,
2429
- render,
2430
- id: idProp,
2431
- ...elementProps
2432
- } = componentProps;
2433
- const id = useBaseUiId.useBaseUiId(idProp);
2434
- const {
2435
- setLabelId
2436
- } = useMenuGroupRootContext();
2437
- useValueChanged.useIsoLayoutEffect(() => {
2438
- setLabelId(id);
2439
- return () => {
2440
- setLabelId(undefined);
2128
+ const arrow = (options, deps) => ({
2129
+ ...baseArrow(options),
2130
+ options: [options, deps]
2131
+ });
2132
+
2133
+ const hide = {
2134
+ name: 'hide',
2135
+ async fn(state) {
2136
+ const {
2137
+ width,
2138
+ height,
2139
+ x,
2140
+ y
2141
+ } = state.rects.reference;
2142
+ const anchorHidden = width === 0 && height === 0 && x === 0 && y === 0;
2143
+ const nativeHideResult = await floatingUi_reactDom.hide().fn(state);
2144
+ return {
2145
+ data: {
2146
+ referenceHidden: nativeHideResult.data?.referenceHidden || anchorHidden
2147
+ }
2441
2148
  };
2442
- }, [setLabelId, id]);
2443
- return useRenderElement.useRenderElement('div', componentProps, {
2444
- ref: forwardedRef,
2445
- props: {
2446
- id,
2447
- role: 'presentation',
2448
- ...elementProps
2149
+ }
2150
+ };
2151
+
2152
+ const DEFAULT_SIDES = {
2153
+ sideX: 'left',
2154
+ sideY: 'top'
2155
+ };
2156
+ const adaptiveOrigin = {
2157
+ name: 'adaptiveOrigin',
2158
+ async fn(state) {
2159
+ const {
2160
+ x: rawX,
2161
+ y: rawY,
2162
+ rects: {
2163
+ floating: floatRect
2164
+ },
2165
+ elements: {
2166
+ floating
2167
+ },
2168
+ platform,
2169
+ strategy,
2170
+ placement
2171
+ } = state;
2172
+ const win = floatingUi_utils_dom.getWindow(floating);
2173
+ const styles = win.getComputedStyle(floating);
2174
+ const hasTransition = styles.transitionDuration !== '0s' && styles.transitionDuration !== '';
2175
+ if (!hasTransition) {
2176
+ return {
2177
+ x: rawX,
2178
+ y: rawY,
2179
+ data: DEFAULT_SIDES
2180
+ };
2449
2181
  }
2450
- });
2451
- });
2452
- if (process.env.NODE_ENV !== "production") MenuGroupLabel.displayName = "MenuGroupLabel";
2182
+ const offsetParent = await platform.getOffsetParent?.(floating);
2183
+ let offsetDimensions = {
2184
+ width: 0,
2185
+ height: 0
2186
+ };
2453
2187
 
2454
- /**
2455
- * An individual interactive item in the menu.
2456
- * Renders a `<div>` element.
2457
- *
2458
- * Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
2459
- */
2460
- const MenuItem = /*#__PURE__*/React__namespace.forwardRef(function MenuItem(componentProps, forwardedRef) {
2461
- const {
2462
- render,
2463
- className,
2464
- id: idProp,
2465
- label,
2466
- nativeButton = false,
2467
- disabled = false,
2468
- closeOnClick = true,
2469
- ...elementProps
2470
- } = componentProps;
2471
- const listItem = useCompositeListItem({
2472
- label
2473
- });
2474
- const menuPositionerContext = useMenuPositionerContext(true);
2475
- const id = useBaseUiId.useBaseUiId(idProp);
2476
- const {
2477
- store
2478
- } = useMenuRootContext();
2479
- const highlighted = store.useState('isActive', listItem.index);
2480
- const itemProps = store.useState('itemProps');
2188
+ // For fixed strategy, prefer visualViewport if available
2189
+ if (strategy === 'fixed' && win?.visualViewport) {
2190
+ offsetDimensions = {
2191
+ width: win.visualViewport.width,
2192
+ height: win.visualViewport.height
2193
+ };
2194
+ } else if (offsetParent === win) {
2195
+ const doc = clamp.ownerDocument(floating);
2196
+ offsetDimensions = {
2197
+ width: doc.documentElement.clientWidth,
2198
+ height: doc.documentElement.clientHeight
2199
+ };
2200
+ } else if (await platform.isElement?.(offsetParent)) {
2201
+ offsetDimensions = await platform.getDimensions(offsetParent);
2202
+ }
2203
+ const currentSide = index_esm.getSide(placement);
2204
+ let x = rawX;
2205
+ let y = rawY;
2206
+ if (currentSide === 'left') {
2207
+ x = offsetDimensions.width - (rawX + floatRect.width);
2208
+ }
2209
+ if (currentSide === 'top') {
2210
+ y = offsetDimensions.height - (rawY + floatRect.height);
2211
+ }
2212
+ const sideX = currentSide === 'left' ? 'right' : DEFAULT_SIDES.sideX;
2213
+ const sideY = currentSide === 'top' ? 'bottom' : DEFAULT_SIDES.sideY;
2214
+ return {
2215
+ x,
2216
+ y,
2217
+ data: {
2218
+ sideX,
2219
+ sideY
2220
+ }
2221
+ };
2222
+ }
2223
+ };
2224
+
2225
+ function getLogicalSide(sideParam, renderedSide, isRtl) {
2226
+ const isLogicalSideParam = sideParam === 'inline-start' || sideParam === 'inline-end';
2227
+ const logicalRight = isRtl ? 'inline-start' : 'inline-end';
2228
+ const logicalLeft = isRtl ? 'inline-end' : 'inline-start';
2229
+ return {
2230
+ top: 'top',
2231
+ right: isLogicalSideParam ? logicalRight : 'right',
2232
+ bottom: 'bottom',
2233
+ left: isLogicalSideParam ? logicalLeft : 'left'
2234
+ }[renderedSide];
2235
+ }
2236
+ function getOffsetData(state, sideParam, isRtl) {
2481
2237
  const {
2482
- getItemProps,
2483
- itemRef
2484
- } = useMenuItem({
2485
- closeOnClick,
2486
- disabled,
2487
- highlighted,
2488
- id,
2489
- store,
2490
- nativeButton,
2491
- nodeId: menuPositionerContext?.nodeId,
2492
- itemMetadata: REGULAR_ITEM
2493
- });
2494
- const state = {
2495
- disabled,
2496
- highlighted
2238
+ rects,
2239
+ placement
2240
+ } = state;
2241
+ const data = {
2242
+ side: getLogicalSide(sideParam, index_esm.getSide(placement), isRtl),
2243
+ align: index_esm.getAlignment(placement) || 'center',
2244
+ anchor: {
2245
+ width: rects.reference.width,
2246
+ height: rects.reference.height
2247
+ },
2248
+ positioner: {
2249
+ width: rects.floating.width,
2250
+ height: rects.floating.height
2251
+ }
2497
2252
  };
2498
- return useRenderElement.useRenderElement('div', componentProps, {
2499
- state,
2500
- props: [itemProps, elementProps, getItemProps],
2501
- ref: [itemRef, forwardedRef, listItem.ref]
2502
- });
2503
- });
2504
- if (process.env.NODE_ENV !== "production") MenuItem.displayName = "MenuItem";
2505
-
2253
+ return data;
2254
+ }
2506
2255
  /**
2507
- * A link in the menu that can be used to navigate to a different page or section.
2508
- * Renders an `<a>` element.
2509
- *
2510
- * Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
2256
+ * Provides standardized anchor positioning behavior for floating elements. Wraps Floating UI's
2257
+ * `useFloating` hook.
2511
2258
  */
2512
- const MenuLinkItem = /*#__PURE__*/React__namespace.forwardRef(function MenuLinkItem(componentProps, forwardedRef) {
2513
- const {
2514
- render,
2515
- className,
2516
- id: idProp,
2517
- label,
2518
- closeOnClick = false,
2519
- ...elementProps
2520
- } = componentProps;
2521
- const linkRef = React__namespace.useRef(null);
2522
- const listItem = useCompositeListItem({
2523
- label
2524
- });
2525
- const menuPositionerContext = useMenuPositionerContext(true);
2526
- const nodeId = menuPositionerContext?.nodeId;
2527
- const id = useBaseUiId.useBaseUiId(idProp);
2528
- const {
2529
- store
2530
- } = useMenuRootContext();
2531
- const highlighted = store.useState('isActive', listItem.index);
2532
- const itemProps = store.useState('itemProps');
2533
- const typingRef = store.context.typingRef;
2259
+ function useAnchorPositioning(params) {
2534
2260
  const {
2535
- getButtonProps,
2536
- buttonRef
2537
- } = useBaseUiId.useButton({
2538
- native: false,
2539
- composite: true
2540
- });
2541
- const commonProps = useMenuItemCommonProps({
2542
- closeOnClick,
2543
- highlighted,
2544
- id,
2261
+ // Public parameters
2262
+ anchor,
2263
+ positionMethod = 'absolute',
2264
+ side: sideParam = 'bottom',
2265
+ sideOffset = 0,
2266
+ align = 'center',
2267
+ alignOffset = 0,
2268
+ collisionBoundary,
2269
+ collisionPadding: collisionPaddingParam = 5,
2270
+ sticky = false,
2271
+ arrowPadding = 5,
2272
+ disableAnchorTracking = false,
2273
+ // Private parameters
2274
+ keepMounted = false,
2275
+ floatingRootContext,
2276
+ mounted,
2277
+ collisionAvoidance,
2278
+ shiftCrossAxis = false,
2545
2279
  nodeId,
2546
- store,
2547
- typingRef,
2548
- itemRef: linkRef
2549
- });
2550
- function getItemProps(externalProps) {
2551
- return useRenderElement.mergeProps(commonProps, externalProps, getButtonProps);
2280
+ adaptiveOrigin,
2281
+ lazyFlip = false,
2282
+ externalTree
2283
+ } = params;
2284
+ const [mountSide, setMountSide] = React__namespace.useState(null);
2285
+ if (!mounted && mountSide !== null) {
2286
+ setMountSide(null);
2552
2287
  }
2553
- const state = React__namespace.useMemo(() => ({
2554
- highlighted
2555
- }), [highlighted]);
2556
- return useRenderElement.useRenderElement('a', componentProps, {
2557
- state,
2558
- props: [itemProps, elementProps, getItemProps],
2559
- ref: [linkRef, buttonRef, forwardedRef, listItem.ref]
2560
- });
2561
- });
2562
- if (process.env.NODE_ENV !== "production") MenuLinkItem.displayName = "MenuLinkItem";
2288
+ const collisionAvoidanceSide = collisionAvoidance.side || 'flip';
2289
+ const collisionAvoidanceAlign = collisionAvoidance.align || 'flip';
2290
+ const collisionAvoidanceFallbackAxisSide = collisionAvoidance.fallbackAxisSide || 'end';
2291
+ const anchorFn = typeof anchor === 'function' ? anchor : undefined;
2292
+ const anchorFnCallback = clamp.useStableCallback(anchorFn);
2293
+ const anchorDep = anchorFn ? anchorFnCallback : anchor;
2294
+ const anchorValueRef = clamp.useValueAsRef(anchor);
2295
+ const direction = ScrollAreaViewport.useDirection();
2296
+ const isRtl = direction === 'rtl';
2297
+ const side = mountSide || {
2298
+ top: 'top',
2299
+ right: 'right',
2300
+ bottom: 'bottom',
2301
+ left: 'left',
2302
+ 'inline-end': isRtl ? 'left' : 'right',
2303
+ 'inline-start': isRtl ? 'right' : 'left'
2304
+ }[sideParam];
2305
+ const placement = align === 'center' ? side : `${side}-${align}`;
2306
+ let collisionPadding = collisionPaddingParam;
2563
2307
 
2564
- const ToolbarRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
2565
- if (process.env.NODE_ENV !== "production") ToolbarRootContext.displayName = "ToolbarRootContext";
2566
- function useToolbarRootContext(optional) {
2567
- const context = React__namespace.useContext(ToolbarRootContext);
2568
- if (context === undefined && !optional) {
2569
- throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: ToolbarRootContext is missing. Toolbar parts must be placed within <Toolbar.Root>.' : useRenderElement.formatErrorMessage(69));
2308
+ // Create a bias to the preferred side.
2309
+ // On iOS, when the mobile software keyboard opens, the input is exactly centered
2310
+ // in the viewport, but this can cause it to flip to the top undesirably.
2311
+ const bias = 1;
2312
+ const biasTop = sideParam === 'bottom' ? bias : 0;
2313
+ const biasBottom = sideParam === 'top' ? bias : 0;
2314
+ const biasLeft = sideParam === 'right' ? bias : 0;
2315
+ const biasRight = sideParam === 'left' ? bias : 0;
2316
+ if (typeof collisionPadding === 'number') {
2317
+ collisionPadding = {
2318
+ top: collisionPadding + biasTop,
2319
+ right: collisionPadding + biasRight,
2320
+ bottom: collisionPadding + biasBottom,
2321
+ left: collisionPadding + biasLeft
2322
+ };
2323
+ } else if (collisionPadding) {
2324
+ collisionPadding = {
2325
+ top: (collisionPadding.top || 0) + biasTop,
2326
+ right: (collisionPadding.right || 0) + biasRight,
2327
+ bottom: (collisionPadding.bottom || 0) + biasBottom,
2328
+ left: (collisionPadding.left || 0) + biasLeft
2329
+ };
2570
2330
  }
2571
- return context;
2572
- }
2573
-
2574
- function getDisabledMountTransitionStyles(transitionStatus) {
2575
- return transitionStatus === 'starting' ? DrawerRoot.DISABLED_TRANSITIONS_STYLE : useRenderElement.EMPTY_OBJECT;
2576
- }
2331
+ const commonCollisionProps = {
2332
+ boundary: collisionBoundary === 'clipping-ancestors' ? 'clippingAncestors' : collisionBoundary,
2333
+ padding: collisionPadding
2334
+ };
2577
2335
 
2578
- const stateAttributesMapping = {
2579
- ...DrawerRoot.popupStateMapping,
2580
- ...useValueChanged.transitionStatusMapping
2581
- };
2336
+ // Using a ref assumes that the arrow element is always present in the DOM for the lifetime of the
2337
+ // popup. If this assumption ends up being false, we can switch to state to manage the arrow's
2338
+ // presence.
2339
+ const arrowRef = React__namespace.useRef(null);
2582
2340
 
2583
- /**
2584
- * A container for the menu items.
2585
- * Renders a `<div>` element.
2586
- *
2587
- * Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
2588
- */
2589
- const MenuPopup = /*#__PURE__*/React__namespace.forwardRef(function MenuPopup(componentProps, forwardedRef) {
2590
- const {
2591
- render,
2592
- className,
2593
- finalFocus,
2594
- ...elementProps
2595
- } = componentProps;
2341
+ // Keep these reactive if they're not functions
2342
+ const sideOffsetRef = clamp.useValueAsRef(sideOffset);
2343
+ const alignOffsetRef = clamp.useValueAsRef(alignOffset);
2344
+ const sideOffsetDep = typeof sideOffset !== 'function' ? sideOffset : 0;
2345
+ const alignOffsetDep = typeof alignOffset !== 'function' ? alignOffset : 0;
2346
+ const middleware = [floatingUi_reactDom.offset(state => {
2347
+ const data = getOffsetData(state, sideParam, isRtl);
2348
+ const sideAxis = typeof sideOffsetRef.current === 'function' ? sideOffsetRef.current(data) : sideOffsetRef.current;
2349
+ const alignAxis = typeof alignOffsetRef.current === 'function' ? alignOffsetRef.current(data) : alignOffsetRef.current;
2350
+ return {
2351
+ mainAxis: sideAxis,
2352
+ crossAxis: alignAxis,
2353
+ alignmentAxis: alignAxis
2354
+ };
2355
+ }, [sideOffsetDep, alignOffsetDep, isRtl, sideParam])];
2356
+ const shiftDisabled = collisionAvoidanceAlign === 'none' && collisionAvoidanceSide !== 'shift';
2357
+ const crossAxisShiftEnabled = !shiftDisabled && (sticky || shiftCrossAxis || collisionAvoidanceSide === 'shift');
2358
+ const flipMiddleware = collisionAvoidanceSide === 'none' ? null : floatingUi_reactDom.flip({
2359
+ ...commonCollisionProps,
2360
+ // Ensure the popup flips if it's been limited by its --available-height and it resizes.
2361
+ // Since the size() padding is smaller than the flip() padding, flip() will take precedence.
2362
+ padding: {
2363
+ top: collisionPadding.top + bias,
2364
+ right: collisionPadding.right + bias,
2365
+ bottom: collisionPadding.bottom + bias,
2366
+ left: collisionPadding.left + bias
2367
+ },
2368
+ mainAxis: !shiftCrossAxis && collisionAvoidanceSide === 'flip',
2369
+ crossAxis: collisionAvoidanceAlign === 'flip' ? 'alignment' : false,
2370
+ fallbackAxisSideDirection: collisionAvoidanceFallbackAxisSide
2371
+ });
2372
+ const shiftMiddleware = shiftDisabled ? null : floatingUi_reactDom.shift(data => {
2373
+ const html = clamp.ownerDocument(data.elements.floating).documentElement;
2374
+ return {
2375
+ ...commonCollisionProps,
2376
+ // Use the Layout Viewport to avoid shifting around when pinch-zooming
2377
+ // for context menus.
2378
+ rootBoundary: shiftCrossAxis ? {
2379
+ x: 0,
2380
+ y: 0,
2381
+ width: html.clientWidth,
2382
+ height: html.clientHeight
2383
+ } : undefined,
2384
+ mainAxis: collisionAvoidanceAlign !== 'none',
2385
+ crossAxis: crossAxisShiftEnabled,
2386
+ limiter: sticky || shiftCrossAxis ? undefined : floatingUi_reactDom.limitShift(limitData => {
2387
+ if (!arrowRef.current) {
2388
+ return {};
2389
+ }
2390
+ const {
2391
+ width,
2392
+ height
2393
+ } = arrowRef.current.getBoundingClientRect();
2394
+ const sideAxis = index_esm.getSideAxis(index_esm.getSide(limitData.placement));
2395
+ const arrowSize = sideAxis === 'y' ? width : height;
2396
+ const offsetAmount = sideAxis === 'y' ? collisionPadding.left + collisionPadding.right : collisionPadding.top + collisionPadding.bottom;
2397
+ return {
2398
+ offset: arrowSize / 2 + offsetAmount / 2
2399
+ };
2400
+ })
2401
+ };
2402
+ }, [commonCollisionProps, sticky, shiftCrossAxis, collisionPadding, collisionAvoidanceAlign]);
2403
+
2404
+ // https://floating-ui.com/docs/flip#combining-with-shift
2405
+ if (collisionAvoidanceSide === 'shift' || collisionAvoidanceAlign === 'shift' || align === 'center') {
2406
+ middleware.push(shiftMiddleware, flipMiddleware);
2407
+ } else {
2408
+ middleware.push(flipMiddleware, shiftMiddleware);
2409
+ }
2410
+ middleware.push(floatingUi_reactDom.size({
2411
+ ...commonCollisionProps,
2412
+ apply({
2413
+ elements: {
2414
+ floating
2415
+ },
2416
+ availableWidth,
2417
+ availableHeight,
2418
+ rects
2419
+ }) {
2420
+ const floatingStyle = floating.style;
2421
+ floatingStyle.setProperty('--available-width', `${availableWidth}px`);
2422
+ floatingStyle.setProperty('--available-height', `${availableHeight}px`);
2423
+
2424
+ // Snap anchor dimensions to device pixels to ensure the popup's visual width matches the anchor's one.
2425
+ const dpr = window.devicePixelRatio || 1;
2426
+ const {
2427
+ x,
2428
+ y,
2429
+ width,
2430
+ height
2431
+ } = rects.reference;
2432
+ const anchorWidth = (Math.round((x + width) * dpr) - Math.round(x * dpr)) / dpr;
2433
+ const anchorHeight = (Math.round((y + height) * dpr) - Math.round(y * dpr)) / dpr;
2434
+ floatingStyle.setProperty('--anchor-width', `${anchorWidth}px`);
2435
+ floatingStyle.setProperty('--anchor-height', `${anchorHeight}px`);
2436
+ }
2437
+ }), arrow(() => ({
2438
+ // `transform-origin` calculations rely on an element existing. If the arrow hasn't been set,
2439
+ // we'll create a fake element.
2440
+ element: arrowRef.current || document.createElement('div'),
2441
+ padding: arrowPadding,
2442
+ offsetParent: 'floating'
2443
+ }), [arrowPadding]), {
2444
+ name: 'transformOrigin',
2445
+ fn(state) {
2446
+ const {
2447
+ elements,
2448
+ middlewareData,
2449
+ placement: renderedPlacement,
2450
+ rects,
2451
+ y
2452
+ } = state;
2453
+ const currentRenderedSide = index_esm.getSide(renderedPlacement);
2454
+ const currentRenderedAxis = index_esm.getSideAxis(currentRenderedSide);
2455
+ const arrowEl = arrowRef.current;
2456
+ const arrowX = middlewareData.arrow?.x || 0;
2457
+ const arrowY = middlewareData.arrow?.y || 0;
2458
+ const arrowWidth = arrowEl?.clientWidth || 0;
2459
+ const arrowHeight = arrowEl?.clientHeight || 0;
2460
+ const transformX = arrowX + arrowWidth / 2;
2461
+ const transformY = arrowY + arrowHeight / 2;
2462
+ const shiftY = Math.abs(middlewareData.shift?.y || 0);
2463
+ const halfAnchorHeight = rects.reference.height / 2;
2464
+ const sideOffsetValue = typeof sideOffset === 'function' ? sideOffset(getOffsetData(state, sideParam, isRtl)) : sideOffset;
2465
+ const isOverlappingAnchor = shiftY > sideOffsetValue;
2466
+ const adjacentTransformOrigin = {
2467
+ top: `${transformX}px calc(100% + ${sideOffsetValue}px)`,
2468
+ bottom: `${transformX}px ${-sideOffsetValue}px`,
2469
+ left: `calc(100% + ${sideOffsetValue}px) ${transformY}px`,
2470
+ right: `${-sideOffsetValue}px ${transformY}px`
2471
+ }[currentRenderedSide];
2472
+ const overlapTransformOrigin = `${transformX}px ${rects.reference.y + halfAnchorHeight - y}px`;
2473
+ elements.floating.style.setProperty('--transform-origin', crossAxisShiftEnabled && currentRenderedAxis === 'y' && isOverlappingAnchor ? overlapTransformOrigin : adjacentTransformOrigin);
2474
+ return {};
2475
+ }
2476
+ }, hide, adaptiveOrigin);
2477
+ clamp.useIsoLayoutEffect(() => {
2478
+ // Ensure positioning doesn't run initially for `keepMounted` elements that
2479
+ // aren't initially open.
2480
+ if (!mounted && floatingRootContext) {
2481
+ floatingRootContext.update({
2482
+ referenceElement: null,
2483
+ floatingElement: null,
2484
+ domReferenceElement: null
2485
+ });
2486
+ }
2487
+ }, [mounted, floatingRootContext]);
2488
+ const autoUpdateOptions = React__namespace.useMemo(() => ({
2489
+ elementResize: !disableAnchorTracking && typeof ResizeObserver !== 'undefined',
2490
+ layoutShift: !disableAnchorTracking && typeof IntersectionObserver !== 'undefined'
2491
+ }), [disableAnchorTracking]);
2596
2492
  const {
2597
- store
2598
- } = useMenuRootContext();
2493
+ refs,
2494
+ elements,
2495
+ x,
2496
+ y,
2497
+ middlewareData,
2498
+ update,
2499
+ placement: renderedPlacement,
2500
+ context,
2501
+ isPositioned,
2502
+ floatingStyles: originalFloatingStyles
2503
+ } = useFloating({
2504
+ rootContext: floatingRootContext,
2505
+ placement,
2506
+ middleware,
2507
+ strategy: positionMethod,
2508
+ whileElementsMounted: keepMounted ? undefined : (...args) => floatingUi_reactDom.autoUpdate(...args, autoUpdateOptions),
2509
+ nodeId,
2510
+ externalTree
2511
+ });
2599
2512
  const {
2600
- side,
2601
- align
2602
- } = useMenuPositionerContext();
2603
- const insideToolbar = useToolbarRootContext(true) != null;
2604
- const open = store.useState('open');
2605
- const transitionStatus = store.useState('transitionStatus');
2606
- const popupProps = store.useState('popupProps');
2607
- const mounted = store.useState('mounted');
2608
- const instantType = store.useState('instantType');
2609
- const triggerElement = store.useState('activeTriggerElement');
2610
- const parent = store.useState('parent');
2611
- const lastOpenChangeReason = store.useState('lastOpenChangeReason');
2612
- const rootId = store.useState('rootId');
2613
- const floatingContext = store.useState('floatingRootContext');
2614
- const floatingTreeRoot = store.useState('floatingTreeRoot');
2615
- const closeDelay = store.useState('closeDelay');
2616
- const activeTriggerElement = store.useState('activeTriggerElement');
2617
- const isContextMenu = parent.type === 'context-menu';
2618
- useValueChanged.useOpenChangeComplete({
2619
- open,
2620
- ref: store.context.popupRef,
2621
- onComplete() {
2622
- if (open) {
2623
- store.context.onOpenChangeComplete?.(true);
2624
- }
2513
+ sideX,
2514
+ sideY
2515
+ } = middlewareData.adaptiveOrigin || DEFAULT_SIDES;
2516
+
2517
+ // Default to `fixed` when not positioned to prevent `autoFocus` scroll jumps.
2518
+ // This ensures the popup is inside the viewport initially before it gets positioned.
2519
+ const resolvedPosition = isPositioned ? positionMethod : 'fixed';
2520
+ const floatingStyles = React__namespace.useMemo(() => {
2521
+ const base = adaptiveOrigin ? {
2522
+ position: resolvedPosition,
2523
+ [sideX]: x,
2524
+ [sideY]: y
2525
+ } : {
2526
+ position: resolvedPosition,
2527
+ ...originalFloatingStyles
2528
+ };
2529
+ if (!isPositioned) {
2530
+ base.opacity = 0;
2625
2531
  }
2626
- });
2532
+ return base;
2533
+ }, [adaptiveOrigin, resolvedPosition, sideX, x, sideY, y, originalFloatingStyles, isPositioned]);
2534
+ const registeredPositionReferenceRef = React__namespace.useRef(null);
2535
+ clamp.useIsoLayoutEffect(() => {
2536
+ if (!mounted) {
2537
+ return;
2538
+ }
2539
+ const anchorValue = anchorValueRef.current;
2540
+ const resolvedAnchor = typeof anchorValue === 'function' ? anchorValue() : anchorValue;
2541
+ const unwrappedElement = (isRef(resolvedAnchor) ? resolvedAnchor.current : resolvedAnchor) || null;
2542
+ const finalAnchor = unwrappedElement || null;
2543
+ if (finalAnchor !== registeredPositionReferenceRef.current) {
2544
+ refs.setPositionReference(finalAnchor);
2545
+ registeredPositionReferenceRef.current = finalAnchor;
2546
+ }
2547
+ }, [mounted, refs, anchorDep, anchorValueRef]);
2627
2548
  React__namespace.useEffect(() => {
2628
- function handleClose(event) {
2629
- store.setOpen(false, useValueChanged.createChangeEventDetails(event.reason, event.domEvent));
2549
+ if (!mounted) {
2550
+ return;
2630
2551
  }
2631
- floatingTreeRoot.events.on('close', handleClose);
2632
- return () => {
2633
- floatingTreeRoot.events.off('close', handleClose);
2634
- };
2635
- }, [floatingTreeRoot.events, store]);
2636
- const hoverEnabled = store.useState('hoverEnabled');
2637
- const disabled = store.useState('disabled');
2638
- useHoverFloatingInteraction(floatingContext, {
2639
- enabled: hoverEnabled && !disabled && !isContextMenu && parent.type !== 'menubar',
2640
- closeDelay
2641
- });
2642
- const state = {
2643
- transitionStatus,
2644
- side,
2645
- align,
2646
- open,
2647
- nested: parent.type === 'menu',
2648
- instant: instantType
2649
- };
2650
- const setPopupElement = React__namespace.useCallback(element => {
2651
- store.set('popupElement', element);
2652
- }, [store]);
2653
- const element = useRenderElement.useRenderElement('div', componentProps, {
2654
- state,
2655
- ref: [forwardedRef, store.context.popupRef, setPopupElement],
2656
- stateAttributesMapping,
2657
- props: [popupProps, {
2658
- onKeyDown(event) {
2659
- if (insideToolbar && DrawerRoot.COMPOSITE_KEYS.has(event.key)) {
2660
- event.stopPropagation();
2661
- }
2552
+ const anchorValue = anchorValueRef.current;
2553
+
2554
+ // Refs from parent components are set after useLayoutEffect runs and are available in useEffect.
2555
+ // Therefore, if the anchor is a ref, we need to update the position reference in useEffect.
2556
+ if (typeof anchorValue === 'function') {
2557
+ return;
2558
+ }
2559
+ if (isRef(anchorValue) && anchorValue.current !== registeredPositionReferenceRef.current) {
2560
+ refs.setPositionReference(anchorValue.current);
2561
+ registeredPositionReferenceRef.current = anchorValue.current;
2562
+ }
2563
+ }, [mounted, refs, anchorDep, anchorValueRef]);
2564
+ React__namespace.useEffect(() => {
2565
+ if (keepMounted && mounted && elements.domReference && elements.floating) {
2566
+ return floatingUi_reactDom.autoUpdate(elements.domReference, elements.floating, update, autoUpdateOptions);
2567
+ }
2568
+ return undefined;
2569
+ }, [keepMounted, mounted, elements, update, autoUpdateOptions]);
2570
+ const renderedSide = index_esm.getSide(renderedPlacement);
2571
+ const logicalRenderedSide = getLogicalSide(sideParam, renderedSide, isRtl);
2572
+ const renderedAlign = index_esm.getAlignment(renderedPlacement) || 'center';
2573
+ const anchorHidden = Boolean(middlewareData.hide?.referenceHidden);
2574
+
2575
+ /**
2576
+ * Locks the flip (makes it "sticky") so it doesn't prefer a given placement
2577
+ * and flips back lazily, not eagerly. Ideal for filtered lists that change
2578
+ * the size of the popup dynamically to avoid unwanted flipping when typing.
2579
+ */
2580
+ clamp.useIsoLayoutEffect(() => {
2581
+ if (lazyFlip && mounted && isPositioned) {
2582
+ setMountSide(renderedSide);
2583
+ }
2584
+ }, [lazyFlip, mounted, isPositioned, renderedSide]);
2585
+ const arrowStyles = React__namespace.useMemo(() => ({
2586
+ position: 'absolute',
2587
+ top: middlewareData.arrow?.y,
2588
+ left: middlewareData.arrow?.x
2589
+ }), [middlewareData.arrow]);
2590
+ const arrowUncentered = middlewareData.arrow?.centerOffset !== 0;
2591
+ return React__namespace.useMemo(() => ({
2592
+ positionerStyles: floatingStyles,
2593
+ arrowStyles,
2594
+ arrowRef,
2595
+ arrowUncentered,
2596
+ side: logicalRenderedSide,
2597
+ align: renderedAlign,
2598
+ physicalSide: renderedSide,
2599
+ anchorHidden,
2600
+ refs,
2601
+ context,
2602
+ isPositioned,
2603
+ update
2604
+ }), [floatingStyles, arrowStyles, arrowRef, arrowUncentered, logicalRenderedSide, renderedAlign, renderedSide, anchorHidden, refs, context, isPositioned, update]);
2605
+ }
2606
+ function isRef(param) {
2607
+ return param != null && 'current' in param;
2608
+ }
2609
+
2610
+ function getDisabledMountTransitionStyles(transitionStatus) {
2611
+ return transitionStatus === 'starting' ? ScrollAreaViewport.DISABLED_TRANSITIONS_STYLE : useRenderElement.EMPTY_OBJECT;
2612
+ }
2613
+
2614
+ let IndexGuessBehavior = /*#__PURE__*/function (IndexGuessBehavior) {
2615
+ IndexGuessBehavior[IndexGuessBehavior["None"] = 0] = "None";
2616
+ IndexGuessBehavior[IndexGuessBehavior["GuessFromOrder"] = 1] = "GuessFromOrder";
2617
+ return IndexGuessBehavior;
2618
+ }({});
2619
+
2620
+ /**
2621
+ * Used to register a list item and its index (DOM position) in the `CompositeList`.
2622
+ */
2623
+ function useCompositeListItem(params = {}) {
2624
+ const {
2625
+ label,
2626
+ metadata,
2627
+ textRef,
2628
+ indexGuessBehavior,
2629
+ index: externalIndex
2630
+ } = params;
2631
+ const {
2632
+ register,
2633
+ unregister,
2634
+ subscribeMapChange,
2635
+ elementsRef,
2636
+ labelsRef,
2637
+ nextIndexRef
2638
+ } = useCompositeListContext();
2639
+ const indexRef = React__namespace.useRef(-1);
2640
+ const [index, setIndex] = React__namespace.useState(externalIndex ?? (indexGuessBehavior === IndexGuessBehavior.GuessFromOrder ? () => {
2641
+ if (indexRef.current === -1) {
2642
+ const newIndex = nextIndexRef.current;
2643
+ nextIndexRef.current += 1;
2644
+ indexRef.current = newIndex;
2645
+ }
2646
+ return indexRef.current;
2647
+ } : -1));
2648
+ const componentRef = React__namespace.useRef(null);
2649
+ const ref = React__namespace.useCallback(node => {
2650
+ componentRef.current = node;
2651
+ if (index !== -1 && node !== null) {
2652
+ elementsRef.current[index] = node;
2653
+ if (labelsRef) {
2654
+ const isLabelDefined = label !== undefined;
2655
+ labelsRef.current[index] = isLabelDefined ? label : textRef?.current?.textContent ?? node.textContent;
2656
+ }
2657
+ }
2658
+ }, [index, elementsRef, labelsRef, label, textRef]);
2659
+ clamp.useIsoLayoutEffect(() => {
2660
+ if (externalIndex != null) {
2661
+ return undefined;
2662
+ }
2663
+ const node = componentRef.current;
2664
+ if (node) {
2665
+ register(node, metadata);
2666
+ return () => {
2667
+ unregister(node);
2668
+ };
2669
+ }
2670
+ return undefined;
2671
+ }, [externalIndex, register, unregister, metadata]);
2672
+ clamp.useIsoLayoutEffect(() => {
2673
+ if (externalIndex != null) {
2674
+ return undefined;
2675
+ }
2676
+ return subscribeMapChange(map => {
2677
+ const i = componentRef.current ? map.get(componentRef.current)?.index : null;
2678
+ if (i != null) {
2679
+ setIndex(i);
2662
2680
  }
2663
- }, getDisabledMountTransitionStyles(transitionStatus), elementProps, {
2664
- 'data-rootownerid': rootId
2665
- }]
2666
- });
2667
- let returnFocus = parent.type === undefined || isContextMenu;
2668
- if (triggerElement || parent.type === 'menubar' && lastOpenChangeReason !== useValueChanged.outsidePress) {
2669
- returnFocus = true;
2670
- }
2671
- return /*#__PURE__*/jsxRuntime.jsx(DrawerRoot.FloatingFocusManager, {
2672
- context: floatingContext,
2673
- modal: isContextMenu,
2674
- disabled: !mounted,
2675
- returnFocus: finalFocus === undefined ? returnFocus : finalFocus,
2676
- initialFocus: parent.type !== 'menu',
2677
- restoreFocus: true,
2678
- externalTree: parent.type !== 'menubar' ? floatingTreeRoot : undefined,
2679
- previousFocusableElement: activeTriggerElement,
2680
- nextFocusableElement: parent.type === undefined ? store.context.triggerFocusTargetRef : undefined,
2681
- beforeContentFocusGuardRef: parent.type === undefined ? store.context.beforeContentFocusGuardRef : undefined,
2682
- children: element
2683
- });
2684
- });
2685
- if (process.env.NODE_ENV !== "production") MenuPopup.displayName = "MenuPopup";
2686
-
2687
- const MenuPortalContext = /*#__PURE__*/React__namespace.createContext(undefined);
2688
- if (process.env.NODE_ENV !== "production") MenuPortalContext.displayName = "MenuPortalContext";
2689
- function useMenuPortalContext() {
2690
- const value = React__namespace.useContext(MenuPortalContext);
2691
- if (value === undefined) {
2692
- throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Menu.Portal> is missing.' : useRenderElement.formatErrorMessage(32));
2693
- }
2694
- return value;
2681
+ });
2682
+ }, [externalIndex, subscribeMapChange, setIndex]);
2683
+ return React__namespace.useMemo(() => ({
2684
+ ref,
2685
+ index
2686
+ }), [index, ref]);
2695
2687
  }
2696
2688
 
2697
- const MenuPortal = /*#__PURE__*/React__namespace.forwardRef(function MenuPortal(props, forwardedRef) {
2689
+ /**
2690
+ * A button that closes the dialog.
2691
+ * Renders a `<button>` element.
2692
+ *
2693
+ * Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
2694
+ */
2695
+ const DialogClose = /*#__PURE__*/React__namespace.forwardRef(function DialogClose(componentProps, forwardedRef) {
2698
2696
  const {
2699
- keepMounted = false,
2700
- ...portalProps
2701
- } = props;
2697
+ render,
2698
+ className,
2699
+ disabled = false,
2700
+ nativeButton = true,
2701
+ ...elementProps
2702
+ } = componentProps;
2702
2703
  const {
2703
2704
  store
2704
- } = useMenuRootContext();
2705
- const mounted = store.useState('mounted');
2706
- const shouldRender = mounted || keepMounted;
2707
- if (!shouldRender) {
2708
- return null;
2705
+ } = ScrollAreaViewport.useDialogRootContext();
2706
+ const open = store.useState('open');
2707
+ function handleClick(event) {
2708
+ if (open) {
2709
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.closePress, event.nativeEvent));
2710
+ }
2709
2711
  }
2710
- return /*#__PURE__*/jsxRuntime.jsx(MenuPortalContext.Provider, {
2711
- value: keepMounted,
2712
- children: /*#__PURE__*/jsxRuntime.jsx(DrawerRoot.FloatingPortal, {
2713
- ref: forwardedRef,
2714
- ...portalProps
2715
- })
2712
+ const {
2713
+ getButtonProps,
2714
+ buttonRef
2715
+ } = clamp.useButton({
2716
+ disabled,
2717
+ native: nativeButton
2718
+ });
2719
+ const state = {
2720
+ disabled
2721
+ };
2722
+ return useRenderElement.useRenderElement('button', componentProps, {
2723
+ state,
2724
+ ref: [forwardedRef, buttonRef],
2725
+ props: [{
2726
+ onClick: handleClick
2727
+ }, elementProps, getButtonProps]
2716
2728
  });
2717
2729
  });
2718
- if (process.env.NODE_ENV !== "production") MenuPortal.displayName = "MenuPortal";
2719
-
2720
- /**
2721
- * @internal
2722
- */
2723
- const DirectionContext = /*#__PURE__*/React__namespace.createContext(undefined);
2724
- if (process.env.NODE_ENV !== "production") DirectionContext.displayName = "DirectionContext";
2725
- function useDirection() {
2726
- const context = React__namespace.useContext(DirectionContext);
2727
- return context?.direction ?? 'ltr';
2728
- }
2730
+ if (process.env.NODE_ENV !== "production") DialogClose.displayName = "DialogClose";
2729
2731
 
2730
2732
  /**
2731
- * Fork of the original `arrow` middleware from Floating UI that allows
2732
- * configuring the offset parent.
2733
+ * A button that closes the drawer.
2734
+ * Renders a `<button>` element.
2735
+ *
2736
+ * Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
2733
2737
  */
2734
- const baseArrow = options => ({
2735
- name: 'arrow',
2736
- options,
2737
- async fn(state) {
2738
- const {
2739
- x,
2740
- y,
2741
- placement,
2742
- rects,
2743
- platform,
2744
- elements,
2745
- middlewareData
2746
- } = state;
2747
- // Since `element` is required, we don't Partial<> the type.
2748
- const {
2749
- element,
2750
- padding = 0,
2751
- offsetParent = 'real'
2752
- } = index_esm.evaluate(options, state) || {};
2753
- if (element == null) {
2754
- return {};
2755
- }
2756
- const paddingObject = index_esm.getPaddingObject(padding);
2757
- const coords = {
2758
- x,
2759
- y
2760
- };
2761
- const axis = index_esm.getAlignmentAxis(placement);
2762
- const length = index_esm.getAxisLength(axis);
2763
- const arrowDimensions = await platform.getDimensions(element);
2764
- const isYAxis = axis === 'y';
2765
- const minProp = isYAxis ? 'top' : 'left';
2766
- const maxProp = isYAxis ? 'bottom' : 'right';
2767
- const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';
2768
- const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];
2769
- const startDiff = coords[axis] - rects.reference[axis];
2770
- const arrowOffsetParent = offsetParent === 'real' ? await platform.getOffsetParent?.(element) : elements.floating;
2771
- let clientSize = elements.floating[clientProp] || rects.floating[length];
2772
-
2773
- // DOM platform can return `window` as the `offsetParent`.
2774
- if (!clientSize || !(await platform.isElement?.(arrowOffsetParent))) {
2775
- clientSize = elements.floating[clientProp] || rects.floating[length];
2776
- }
2777
- const centerToReference = endDiff / 2 - startDiff / 2;
2778
-
2779
- // If the padding is large enough that it causes the arrow to no longer be
2780
- // centered, modify the padding so that it is centered.
2781
- const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;
2782
- const minPadding = Math.min(paddingObject[minProp], largestPossiblePadding);
2783
- const maxPadding = Math.min(paddingObject[maxProp], largestPossiblePadding);
2784
-
2785
- // Make sure the arrow doesn't overflow the floating element if the center
2786
- // point is outside the floating element's bounds.
2787
- const min = minPadding;
2788
- const max = clientSize - arrowDimensions[length] - maxPadding;
2789
- const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
2790
- const offset = index_esm.clamp(min, center, max);
2791
-
2792
- // If the reference is small enough that the arrow's padding causes it to
2793
- // to point to nothing for an aligned placement, adjust the offset of the
2794
- // floating element itself. To ensure `shift()` continues to take action,
2795
- // a single reset is performed when this is true.
2796
- const shouldAddOffset = !middlewareData.arrow && index_esm.getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
2797
- // eslint-disable-next-line no-nested-ternary
2798
- const alignmentOffset = shouldAddOffset ? center < min ? center - min : center - max : 0;
2799
- return {
2800
- [axis]: coords[axis] + alignmentOffset,
2801
- data: {
2802
- [axis]: offset,
2803
- centerOffset: center - offset - alignmentOffset,
2804
- ...(shouldAddOffset && {
2805
- alignmentOffset
2806
- })
2807
- },
2808
- reset: shouldAddOffset
2809
- };
2810
- }
2811
- });
2738
+ const DrawerClose = DialogClose;
2812
2739
 
2813
2740
  /**
2814
- * Provides data to position an inner element of the floating element so that it
2815
- * appears centered to the reference element.
2816
- * This wraps the core `arrow` middleware to allow React refs as the element.
2817
- * @see https://floating-ui.com/docs/arrow
2741
+ * A heading that labels the dialog.
2742
+ * Renders an `<h2>` element.
2743
+ *
2744
+ * Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
2818
2745
  */
2819
- const arrow = (options, deps) => ({
2820
- ...baseArrow(options),
2821
- options: [options, deps]
2822
- });
2823
-
2824
- const hide = {
2825
- name: 'hide',
2826
- async fn(state) {
2827
- const {
2828
- width,
2829
- height,
2830
- x,
2831
- y
2832
- } = state.rects.reference;
2833
- const anchorHidden = width === 0 && height === 0 && x === 0 && y === 0;
2834
- const nativeHideResult = await floatingUi_reactDom.hide().fn(state);
2835
- return {
2836
- data: {
2837
- referenceHidden: nativeHideResult.data?.referenceHidden || anchorHidden
2838
- }
2839
- };
2840
- }
2841
- };
2842
-
2843
- const DEFAULT_SIDES = {
2844
- sideX: 'left',
2845
- sideY: 'top'
2846
- };
2847
- const adaptiveOrigin = {
2848
- name: 'adaptiveOrigin',
2849
- async fn(state) {
2850
- const {
2851
- x: rawX,
2852
- y: rawY,
2853
- rects: {
2854
- floating: floatRect
2855
- },
2856
- elements: {
2857
- floating
2858
- },
2859
- platform,
2860
- strategy,
2861
- placement
2862
- } = state;
2863
- const win = floatingUi_utils_dom.getWindow(floating);
2864
- const styles = win.getComputedStyle(floating);
2865
- const hasTransition = styles.transitionDuration !== '0s' && styles.transitionDuration !== '';
2866
- if (!hasTransition) {
2867
- return {
2868
- x: rawX,
2869
- y: rawY,
2870
- data: DEFAULT_SIDES
2871
- };
2872
- }
2873
- const offsetParent = await platform.getOffsetParent?.(floating);
2874
- let offsetDimensions = {
2875
- width: 0,
2876
- height: 0
2877
- };
2746
+ const DialogTitle = /*#__PURE__*/React__namespace.forwardRef(function DialogTitle(componentProps, forwardedRef) {
2747
+ const {
2748
+ render,
2749
+ className,
2750
+ id: idProp,
2751
+ ...elementProps
2752
+ } = componentProps;
2753
+ const {
2754
+ store
2755
+ } = ScrollAreaViewport.useDialogRootContext();
2756
+ const id = clamp.useBaseUiId(idProp);
2757
+ store.useSyncedValueWithCleanup('titleElementId', id);
2758
+ return useRenderElement.useRenderElement('h2', componentProps, {
2759
+ ref: forwardedRef,
2760
+ props: [{
2761
+ id
2762
+ }, elementProps]
2763
+ });
2764
+ });
2765
+ if (process.env.NODE_ENV !== "production") DialogTitle.displayName = "DialogTitle";
2878
2766
 
2879
- // For fixed strategy, prefer visualViewport if available
2880
- if (strategy === 'fixed' && win?.visualViewport) {
2881
- offsetDimensions = {
2882
- width: win.visualViewport.width,
2883
- height: win.visualViewport.height
2884
- };
2885
- } else if (offsetParent === win) {
2886
- const doc = useValueChanged.ownerDocument(floating);
2887
- offsetDimensions = {
2888
- width: doc.documentElement.clientWidth,
2889
- height: doc.documentElement.clientHeight
2890
- };
2891
- } else if (await platform.isElement?.(offsetParent)) {
2892
- offsetDimensions = await platform.getDimensions(offsetParent);
2893
- }
2894
- const currentSide = index_esm.getSide(placement);
2895
- let x = rawX;
2896
- let y = rawY;
2897
- if (currentSide === 'left') {
2898
- x = offsetDimensions.width - (rawX + floatRect.width);
2899
- }
2900
- if (currentSide === 'top') {
2901
- y = offsetDimensions.height - (rawY + floatRect.height);
2902
- }
2903
- const sideX = currentSide === 'left' ? 'right' : DEFAULT_SIDES.sideX;
2904
- const sideY = currentSide === 'top' ? 'bottom' : DEFAULT_SIDES.sideY;
2905
- return {
2906
- x,
2907
- y,
2908
- data: {
2909
- sideX,
2910
- sideY
2911
- }
2912
- };
2767
+ /**
2768
+ * A heading that labels the drawer.
2769
+ * Renders an `<h2>` element.
2770
+ *
2771
+ * Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
2772
+ */
2773
+ const DrawerTitle = DialogTitle;
2774
+
2775
+ const MenuPositionerContext = /*#__PURE__*/React__namespace.createContext(undefined);
2776
+ if (process.env.NODE_ENV !== "production") MenuPositionerContext.displayName = "MenuPositionerContext";
2777
+ function useMenuPositionerContext(optional) {
2778
+ const context = React__namespace.useContext(MenuPositionerContext);
2779
+ if (context === undefined && !optional) {
2780
+ throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: MenuPositionerContext is missing. MenuPositioner parts must be placed within <Menu.Positioner>.' : useRenderElement.formatErrorMessage(33));
2913
2781
  }
2914
- };
2782
+ return context;
2783
+ }
2915
2784
 
2916
- function getLogicalSide(sideParam, renderedSide, isRtl) {
2917
- const isLogicalSideParam = sideParam === 'inline-start' || sideParam === 'inline-end';
2918
- const logicalRight = isRtl ? 'inline-start' : 'inline-end';
2919
- const logicalLeft = isRtl ? 'inline-end' : 'inline-start';
2920
- return {
2921
- top: 'top',
2922
- right: isLogicalSideParam ? logicalRight : 'right',
2923
- bottom: 'bottom',
2924
- left: isLogicalSideParam ? logicalLeft : 'left'
2925
- }[renderedSide];
2785
+ const MenuRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
2786
+ if (process.env.NODE_ENV !== "production") MenuRootContext.displayName = "MenuRootContext";
2787
+ function useMenuRootContext(optional) {
2788
+ const context = React__namespace.useContext(MenuRootContext);
2789
+ if (context === undefined && !optional) {
2790
+ throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: MenuRootContext is missing. Menu parts must be placed within <Menu.Root>.' : useRenderElement.formatErrorMessage(36));
2791
+ }
2792
+ return context;
2926
2793
  }
2927
- function getOffsetData(state, sideParam, isRtl) {
2928
- const {
2929
- rects,
2930
- placement
2931
- } = state;
2932
- const data = {
2933
- side: getLogicalSide(sideParam, index_esm.getSide(placement), isRtl),
2934
- align: index_esm.getAlignment(placement) || 'center',
2935
- anchor: {
2936
- width: rects.reference.width,
2937
- height: rects.reference.height
2938
- },
2939
- positioner: {
2940
- width: rects.floating.width,
2941
- height: rects.floating.height
2942
- }
2943
- };
2944
- return data;
2794
+
2795
+ const ContextMenuRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
2796
+ if (process.env.NODE_ENV !== "production") ContextMenuRootContext.displayName = "ContextMenuRootContext";
2797
+ function useContextMenuRootContext(optional = true) {
2798
+ const context = React__namespace.useContext(ContextMenuRootContext);
2799
+ if (context === undefined && !optional) {
2800
+ throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: ContextMenuRootContext is missing. ContextMenu parts must be placed within <ContextMenu.Root>.' : useRenderElement.formatErrorMessage(25));
2801
+ }
2802
+ return context;
2945
2803
  }
2804
+
2946
2805
  /**
2947
- * Provides standardized anchor positioning behavior for floating elements. Wraps Floating UI's
2948
- * `useFloating` hook.
2806
+ * Returns common props shared by all menu item types.
2807
+ * This hook extracts the shared logic for id, role, tabIndex, onKeyDown,
2808
+ * onMouseMove, onClick, and onMouseUp handlers.
2949
2809
  */
2950
- function useAnchorPositioning(params) {
2810
+ function useMenuItemCommonProps(params) {
2951
2811
  const {
2952
- // Public parameters
2953
- anchor,
2954
- positionMethod = 'absolute',
2955
- side: sideParam = 'bottom',
2956
- sideOffset = 0,
2957
- align = 'center',
2958
- alignOffset = 0,
2959
- collisionBoundary,
2960
- collisionPadding: collisionPaddingParam = 5,
2961
- sticky = false,
2962
- arrowPadding = 5,
2963
- disableAnchorTracking = false,
2964
- // Private parameters
2965
- keepMounted = false,
2966
- floatingRootContext,
2967
- mounted,
2968
- collisionAvoidance,
2969
- shiftCrossAxis = false,
2812
+ closeOnClick,
2813
+ highlighted,
2814
+ id,
2970
2815
  nodeId,
2971
- adaptiveOrigin,
2972
- lazyFlip = false,
2973
- externalTree
2816
+ store,
2817
+ typingRef,
2818
+ itemRef,
2819
+ itemMetadata
2974
2820
  } = params;
2975
- const [mountSide, setMountSide] = React__namespace.useState(null);
2976
- if (!mounted && mountSide !== null) {
2977
- setMountSide(null);
2978
- }
2979
- const collisionAvoidanceSide = collisionAvoidance.side || 'flip';
2980
- const collisionAvoidanceAlign = collisionAvoidance.align || 'flip';
2981
- const collisionAvoidanceFallbackAxisSide = collisionAvoidance.fallbackAxisSide || 'end';
2982
- const anchorFn = typeof anchor === 'function' ? anchor : undefined;
2983
- const anchorFnCallback = useValueChanged.useStableCallback(anchorFn);
2984
- const anchorDep = anchorFn ? anchorFnCallback : anchor;
2985
- const anchorValueRef = useValueChanged.useValueAsRef(anchor);
2986
- const direction = useDirection();
2987
- const isRtl = direction === 'rtl';
2988
- const side = mountSide || {
2989
- top: 'top',
2990
- right: 'right',
2991
- bottom: 'bottom',
2992
- left: 'left',
2993
- 'inline-end': isRtl ? 'left' : 'right',
2994
- 'inline-start': isRtl ? 'right' : 'left'
2995
- }[sideParam];
2996
- const placement = align === 'center' ? side : `${side}-${align}`;
2997
- let collisionPadding = collisionPaddingParam;
2821
+ const {
2822
+ events: menuEvents
2823
+ } = store.useState('floatingTreeRoot');
2824
+ const contextMenuContext = useContextMenuRootContext(true);
2825
+ const isContextMenu = contextMenuContext !== undefined;
2826
+ return React__namespace.useMemo(() => ({
2827
+ id,
2828
+ role: 'menuitem',
2829
+ tabIndex: highlighted ? 0 : -1,
2830
+ onKeyDown(event) {
2831
+ if (event.key === ' ' && typingRef?.current) {
2832
+ event.preventDefault();
2833
+ }
2834
+ },
2835
+ onMouseMove(event) {
2836
+ if (!nodeId) {
2837
+ return;
2838
+ }
2998
2839
 
2999
- // Create a bias to the preferred side.
3000
- // On iOS, when the mobile software keyboard opens, the input is exactly centered
3001
- // in the viewport, but this can cause it to flip to the top undesirably.
3002
- const bias = 1;
3003
- const biasTop = sideParam === 'bottom' ? bias : 0;
3004
- const biasBottom = sideParam === 'top' ? bias : 0;
3005
- const biasLeft = sideParam === 'right' ? bias : 0;
3006
- const biasRight = sideParam === 'left' ? bias : 0;
3007
- if (typeof collisionPadding === 'number') {
3008
- collisionPadding = {
3009
- top: collisionPadding + biasTop,
3010
- right: collisionPadding + biasRight,
3011
- bottom: collisionPadding + biasBottom,
3012
- left: collisionPadding + biasLeft
3013
- };
3014
- } else if (collisionPadding) {
3015
- collisionPadding = {
3016
- top: (collisionPadding.top || 0) + biasTop,
3017
- right: (collisionPadding.right || 0) + biasRight,
3018
- bottom: (collisionPadding.bottom || 0) + biasBottom,
3019
- left: (collisionPadding.left || 0) + biasLeft
3020
- };
3021
- }
3022
- const commonCollisionProps = {
3023
- boundary: collisionBoundary === 'clipping-ancestors' ? 'clippingAncestors' : collisionBoundary,
3024
- padding: collisionPadding
3025
- };
2840
+ // Inform the floating tree that a menu item within this menu was hovered/moved over
2841
+ // so unrelated descendant submenus can be closed.
2842
+ menuEvents.emit('itemhover', {
2843
+ nodeId,
2844
+ target: event.currentTarget
2845
+ });
2846
+ },
2847
+ onClick(event) {
2848
+ if (closeOnClick) {
2849
+ menuEvents.emit('close', {
2850
+ domEvent: event,
2851
+ reason: clamp.itemPress
2852
+ });
2853
+ }
2854
+ },
2855
+ onMouseUp(event) {
2856
+ if (contextMenuContext) {
2857
+ const initialCursorPoint = contextMenuContext.initialCursorPointRef.current;
2858
+ contextMenuContext.initialCursorPointRef.current = null;
2859
+ if (isContextMenu && initialCursorPoint && Math.abs(event.clientX - initialCursorPoint.x) <= 1 && Math.abs(event.clientY - initialCursorPoint.y) <= 1) {
2860
+ return;
2861
+ }
2862
+
2863
+ // On non-macOS platforms, this mouseup belongs to the right-click gesture
2864
+ // that opened the context menu, so it must not activate an item.
2865
+ if (isContextMenu && !clamp.isMac && event.button === 2) {
2866
+ return;
2867
+ }
2868
+ }
2869
+ if (itemRef.current && store.context.allowMouseUpTriggerRef.current && (!isContextMenu || event.button === 2)) {
2870
+ // This fires whenever the user clicks on the trigger, moves the cursor, and releases it over the item.
2871
+ // We trigger the click and override the `closeOnClick` preference to always close the menu.
2872
+ if (!itemMetadata || itemMetadata.type === 'regular-item') {
2873
+ itemRef.current.click();
2874
+ }
2875
+ }
2876
+ }
2877
+ }), [closeOnClick, highlighted, id, menuEvents, nodeId, store, typingRef, itemRef, contextMenuContext, isContextMenu, itemMetadata]);
2878
+ }
2879
+
2880
+ const REGULAR_ITEM = {
2881
+ type: 'regular-item'
2882
+ };
2883
+ function useMenuItem(params) {
2884
+ const {
2885
+ closeOnClick,
2886
+ disabled = false,
2887
+ highlighted,
2888
+ id,
2889
+ store,
2890
+ typingRef = store.context.typingRef,
2891
+ nativeButton,
2892
+ itemMetadata,
2893
+ nodeId
2894
+ } = params;
2895
+ const itemRef = React__namespace.useRef(null);
2896
+ const {
2897
+ getButtonProps,
2898
+ buttonRef
2899
+ } = clamp.useButton({
2900
+ disabled,
2901
+ focusableWhenDisabled: true,
2902
+ native: nativeButton,
2903
+ composite: true
2904
+ });
2905
+ const commonProps = useMenuItemCommonProps({
2906
+ closeOnClick,
2907
+ highlighted,
2908
+ id,
2909
+ nodeId,
2910
+ store,
2911
+ typingRef,
2912
+ itemRef,
2913
+ itemMetadata
2914
+ });
2915
+ const getItemProps = React__namespace.useCallback(externalProps => {
2916
+ return useRenderElement.mergeProps(commonProps, {
2917
+ onMouseEnter() {
2918
+ if (itemMetadata.type !== 'submenu-trigger') {
2919
+ return;
2920
+ }
2921
+ itemMetadata.setActive();
2922
+ }
2923
+ }, externalProps, getButtonProps);
2924
+ }, [commonProps, getButtonProps, itemMetadata]);
2925
+ const mergedRef = useRenderElement.useMergedRefs(itemRef, buttonRef);
2926
+ return React__namespace.useMemo(() => ({
2927
+ getItemProps,
2928
+ itemRef: mergedRef
2929
+ }), [getItemProps, mergedRef]);
2930
+ }
3026
2931
 
3027
- // Using a ref assumes that the arrow element is always present in the DOM for the lifetime of the
3028
- // popup. If this assumption ends up being false, we can switch to state to manage the arrow's
3029
- // presence.
3030
- const arrowRef = React__namespace.useRef(null);
2932
+ let MenuCheckboxItemDataAttributes = /*#__PURE__*/function (MenuCheckboxItemDataAttributes) {
2933
+ /**
2934
+ * Present when the menu checkbox item is checked.
2935
+ */
2936
+ MenuCheckboxItemDataAttributes["checked"] = "data-checked";
2937
+ /**
2938
+ * Present when the menu checkbox item is not checked.
2939
+ */
2940
+ MenuCheckboxItemDataAttributes["unchecked"] = "data-unchecked";
2941
+ /**
2942
+ * Present when the menu checkbox item is disabled.
2943
+ */
2944
+ MenuCheckboxItemDataAttributes["disabled"] = "data-disabled";
2945
+ /**
2946
+ * Present when the menu checkbox item is highlighted.
2947
+ */
2948
+ MenuCheckboxItemDataAttributes["highlighted"] = "data-highlighted";
2949
+ return MenuCheckboxItemDataAttributes;
2950
+ }({});
3031
2951
 
3032
- // Keep these reactive if they're not functions
3033
- const sideOffsetRef = useValueChanged.useValueAsRef(sideOffset);
3034
- const alignOffsetRef = useValueChanged.useValueAsRef(alignOffset);
3035
- const sideOffsetDep = typeof sideOffset !== 'function' ? sideOffset : 0;
3036
- const alignOffsetDep = typeof alignOffset !== 'function' ? alignOffset : 0;
3037
- const middleware = [floatingUi_reactDom.offset(state => {
3038
- const data = getOffsetData(state, sideParam, isRtl);
3039
- const sideAxis = typeof sideOffsetRef.current === 'function' ? sideOffsetRef.current(data) : sideOffsetRef.current;
3040
- const alignAxis = typeof alignOffsetRef.current === 'function' ? alignOffsetRef.current(data) : alignOffsetRef.current;
3041
- return {
3042
- mainAxis: sideAxis,
3043
- crossAxis: alignAxis,
3044
- alignmentAxis: alignAxis
3045
- };
3046
- }, [sideOffsetDep, alignOffsetDep, isRtl, sideParam])];
3047
- const shiftDisabled = collisionAvoidanceAlign === 'none' && collisionAvoidanceSide !== 'shift';
3048
- const crossAxisShiftEnabled = !shiftDisabled && (sticky || shiftCrossAxis || collisionAvoidanceSide === 'shift');
3049
- const flipMiddleware = collisionAvoidanceSide === 'none' ? null : floatingUi_reactDom.flip({
3050
- ...commonCollisionProps,
3051
- // Ensure the popup flips if it's been limited by its --available-height and it resizes.
3052
- // Since the size() padding is smaller than the flip() padding, flip() will take precedence.
3053
- padding: {
3054
- top: collisionPadding.top + bias,
3055
- right: collisionPadding.right + bias,
3056
- bottom: collisionPadding.bottom + bias,
3057
- left: collisionPadding.left + bias
3058
- },
3059
- mainAxis: !shiftCrossAxis && collisionAvoidanceSide === 'flip',
3060
- crossAxis: collisionAvoidanceAlign === 'flip' ? 'alignment' : false,
3061
- fallbackAxisSideDirection: collisionAvoidanceFallbackAxisSide
3062
- });
3063
- const shiftMiddleware = shiftDisabled ? null : floatingUi_reactDom.shift(data => {
3064
- const html = useValueChanged.ownerDocument(data.elements.floating).documentElement;
2952
+ const itemMapping = {
2953
+ checked(value) {
2954
+ if (value) {
2955
+ return {
2956
+ [MenuCheckboxItemDataAttributes.checked]: ''
2957
+ };
2958
+ }
3065
2959
  return {
3066
- ...commonCollisionProps,
3067
- // Use the Layout Viewport to avoid shifting around when pinch-zooming
3068
- // for context menus.
3069
- rootBoundary: shiftCrossAxis ? {
3070
- x: 0,
3071
- y: 0,
3072
- width: html.clientWidth,
3073
- height: html.clientHeight
3074
- } : undefined,
3075
- mainAxis: collisionAvoidanceAlign !== 'none',
3076
- crossAxis: crossAxisShiftEnabled,
3077
- limiter: sticky || shiftCrossAxis ? undefined : floatingUi_reactDom.limitShift(limitData => {
3078
- if (!arrowRef.current) {
3079
- return {};
3080
- }
3081
- const {
3082
- width,
3083
- height
3084
- } = arrowRef.current.getBoundingClientRect();
3085
- const sideAxis = index_esm.getSideAxis(index_esm.getSide(limitData.placement));
3086
- const arrowSize = sideAxis === 'y' ? width : height;
3087
- const offsetAmount = sideAxis === 'y' ? collisionPadding.left + collisionPadding.right : collisionPadding.top + collisionPadding.bottom;
3088
- return {
3089
- offset: arrowSize / 2 + offsetAmount / 2
3090
- };
3091
- })
2960
+ [MenuCheckboxItemDataAttributes.unchecked]: ''
3092
2961
  };
3093
- }, [commonCollisionProps, sticky, shiftCrossAxis, collisionPadding, collisionAvoidanceAlign]);
2962
+ },
2963
+ ...clamp.transitionStatusMapping
2964
+ };
3094
2965
 
3095
- // https://floating-ui.com/docs/flip#combining-with-shift
3096
- if (collisionAvoidanceSide === 'shift' || collisionAvoidanceAlign === 'shift' || align === 'center') {
3097
- middleware.push(shiftMiddleware, flipMiddleware);
3098
- } else {
3099
- middleware.push(flipMiddleware, shiftMiddleware);
2966
+ const MenuGroupContext = /*#__PURE__*/React__namespace.createContext(undefined);
2967
+ if (process.env.NODE_ENV !== "production") MenuGroupContext.displayName = "MenuGroupContext";
2968
+ function useMenuGroupRootContext() {
2969
+ const context = React__namespace.useContext(MenuGroupContext);
2970
+ if (context === undefined) {
2971
+ throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: MenuGroupRootContext is missing. Menu group parts must be used within <Menu.Group>.' : useRenderElement.formatErrorMessage(31));
3100
2972
  }
3101
- middleware.push(floatingUi_reactDom.size({
3102
- ...commonCollisionProps,
3103
- apply({
3104
- elements: {
3105
- floating
3106
- },
3107
- availableWidth,
3108
- availableHeight,
3109
- rects
3110
- }) {
3111
- const floatingStyle = floating.style;
3112
- floatingStyle.setProperty('--available-width', `${availableWidth}px`);
3113
- floatingStyle.setProperty('--available-height', `${availableHeight}px`);
2973
+ return context;
2974
+ }
3114
2975
 
3115
- // Snap anchor dimensions to device pixels to ensure the popup's visual width matches the anchor's one.
3116
- const dpr = window.devicePixelRatio || 1;
3117
- const {
3118
- x,
3119
- y,
3120
- width,
3121
- height
3122
- } = rects.reference;
3123
- const anchorWidth = (Math.round((x + width) * dpr) - Math.round(x * dpr)) / dpr;
3124
- const anchorHeight = (Math.round((y + height) * dpr) - Math.round(y * dpr)) / dpr;
3125
- floatingStyle.setProperty('--anchor-width', `${anchorWidth}px`);
3126
- floatingStyle.setProperty('--anchor-height', `${anchorHeight}px`);
3127
- }
3128
- }), arrow(() => ({
3129
- // `transform-origin` calculations rely on an element existing. If the arrow hasn't been set,
3130
- // we'll create a fake element.
3131
- element: arrowRef.current || document.createElement('div'),
3132
- padding: arrowPadding,
3133
- offsetParent: 'floating'
3134
- }), [arrowPadding]), {
3135
- name: 'transformOrigin',
3136
- fn(state) {
3137
- const {
3138
- elements,
3139
- middlewareData,
3140
- placement: renderedPlacement,
3141
- rects,
3142
- y
3143
- } = state;
3144
- const currentRenderedSide = index_esm.getSide(renderedPlacement);
3145
- const currentRenderedAxis = index_esm.getSideAxis(currentRenderedSide);
3146
- const arrowEl = arrowRef.current;
3147
- const arrowX = middlewareData.arrow?.x || 0;
3148
- const arrowY = middlewareData.arrow?.y || 0;
3149
- const arrowWidth = arrowEl?.clientWidth || 0;
3150
- const arrowHeight = arrowEl?.clientHeight || 0;
3151
- const transformX = arrowX + arrowWidth / 2;
3152
- const transformY = arrowY + arrowHeight / 2;
3153
- const shiftY = Math.abs(middlewareData.shift?.y || 0);
3154
- const halfAnchorHeight = rects.reference.height / 2;
3155
- const sideOffsetValue = typeof sideOffset === 'function' ? sideOffset(getOffsetData(state, sideParam, isRtl)) : sideOffset;
3156
- const isOverlappingAnchor = shiftY > sideOffsetValue;
3157
- const adjacentTransformOrigin = {
3158
- top: `${transformX}px calc(100% + ${sideOffsetValue}px)`,
3159
- bottom: `${transformX}px ${-sideOffsetValue}px`,
3160
- left: `calc(100% + ${sideOffsetValue}px) ${transformY}px`,
3161
- right: `${-sideOffsetValue}px ${transformY}px`
3162
- }[currentRenderedSide];
3163
- const overlapTransformOrigin = `${transformX}px ${rects.reference.y + halfAnchorHeight - y}px`;
3164
- elements.floating.style.setProperty('--transform-origin', crossAxisShiftEnabled && currentRenderedAxis === 'y' && isOverlappingAnchor ? overlapTransformOrigin : adjacentTransformOrigin);
3165
- return {};
3166
- }
3167
- }, hide, adaptiveOrigin);
3168
- useValueChanged.useIsoLayoutEffect(() => {
3169
- // Ensure positioning doesn't run initially for `keepMounted` elements that
3170
- // aren't initially open.
3171
- if (!mounted && floatingRootContext) {
3172
- floatingRootContext.update({
3173
- referenceElement: null,
3174
- floatingElement: null,
3175
- domReferenceElement: null
3176
- });
3177
- }
3178
- }, [mounted, floatingRootContext]);
3179
- const autoUpdateOptions = React__namespace.useMemo(() => ({
3180
- elementResize: !disableAnchorTracking && typeof ResizeObserver !== 'undefined',
3181
- layoutShift: !disableAnchorTracking && typeof IntersectionObserver !== 'undefined'
3182
- }), [disableAnchorTracking]);
2976
+ const MenuGroup = /*#__PURE__*/React__namespace.forwardRef(function MenuGroup(componentProps, forwardedRef) {
3183
2977
  const {
3184
- refs,
3185
- elements,
3186
- x,
3187
- y,
3188
- middlewareData,
3189
- update,
3190
- placement: renderedPlacement,
3191
- context,
3192
- isPositioned,
3193
- floatingStyles: originalFloatingStyles
3194
- } = useFloating({
3195
- rootContext: floatingRootContext,
3196
- placement,
3197
- middleware,
3198
- strategy: positionMethod,
3199
- whileElementsMounted: keepMounted ? undefined : (...args) => floatingUi_reactDom.autoUpdate(...args, autoUpdateOptions),
3200
- nodeId,
3201
- externalTree
2978
+ render,
2979
+ className,
2980
+ ...elementProps
2981
+ } = componentProps;
2982
+ const [labelId, setLabelId] = React__namespace.useState(undefined);
2983
+ const context = React__namespace.useMemo(() => ({
2984
+ setLabelId
2985
+ }), [setLabelId]);
2986
+ const element = useRenderElement.useRenderElement('div', componentProps, {
2987
+ ref: forwardedRef,
2988
+ props: {
2989
+ role: 'group',
2990
+ 'aria-labelledby': labelId,
2991
+ ...elementProps
2992
+ }
2993
+ });
2994
+ return /*#__PURE__*/jsxRuntime.jsx(MenuGroupContext.Provider, {
2995
+ value: context,
2996
+ children: element
3202
2997
  });
3203
- const {
3204
- sideX,
3205
- sideY
3206
- } = middlewareData.adaptiveOrigin || DEFAULT_SIDES;
2998
+ });
2999
+ if (process.env.NODE_ENV !== "production") MenuGroup.displayName = "MenuGroup";
3207
3000
 
3208
- // Default to `fixed` when not positioned to prevent `autoFocus` scroll jumps.
3209
- // This ensures the popup is inside the viewport initially before it gets positioned.
3210
- const resolvedPosition = isPositioned ? positionMethod : 'fixed';
3211
- const floatingStyles = React__namespace.useMemo(() => {
3212
- const base = adaptiveOrigin ? {
3213
- position: resolvedPosition,
3214
- [sideX]: x,
3215
- [sideY]: y
3216
- } : {
3217
- position: resolvedPosition,
3218
- ...originalFloatingStyles
3001
+ /**
3002
+ * An accessible label that is automatically associated with its parent group.
3003
+ * Renders a `<div>` element.
3004
+ *
3005
+ * Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
3006
+ */
3007
+ const MenuGroupLabel = /*#__PURE__*/React__namespace.forwardRef(function MenuGroupLabelComponent(componentProps, forwardedRef) {
3008
+ const {
3009
+ className,
3010
+ render,
3011
+ id: idProp,
3012
+ ...elementProps
3013
+ } = componentProps;
3014
+ const id = clamp.useBaseUiId(idProp);
3015
+ const {
3016
+ setLabelId
3017
+ } = useMenuGroupRootContext();
3018
+ clamp.useIsoLayoutEffect(() => {
3019
+ setLabelId(id);
3020
+ return () => {
3021
+ setLabelId(undefined);
3219
3022
  };
3220
- if (!isPositioned) {
3221
- base.opacity = 0;
3222
- }
3223
- return base;
3224
- }, [adaptiveOrigin, resolvedPosition, sideX, x, sideY, y, originalFloatingStyles, isPositioned]);
3225
- const registeredPositionReferenceRef = React__namespace.useRef(null);
3226
- useValueChanged.useIsoLayoutEffect(() => {
3227
- if (!mounted) {
3228
- return;
3229
- }
3230
- const anchorValue = anchorValueRef.current;
3231
- const resolvedAnchor = typeof anchorValue === 'function' ? anchorValue() : anchorValue;
3232
- const unwrappedElement = (isRef(resolvedAnchor) ? resolvedAnchor.current : resolvedAnchor) || null;
3233
- const finalAnchor = unwrappedElement || null;
3234
- if (finalAnchor !== registeredPositionReferenceRef.current) {
3235
- refs.setPositionReference(finalAnchor);
3236
- registeredPositionReferenceRef.current = finalAnchor;
3237
- }
3238
- }, [mounted, refs, anchorDep, anchorValueRef]);
3239
- React__namespace.useEffect(() => {
3240
- if (!mounted) {
3241
- return;
3023
+ }, [setLabelId, id]);
3024
+ return useRenderElement.useRenderElement('div', componentProps, {
3025
+ ref: forwardedRef,
3026
+ props: {
3027
+ id,
3028
+ role: 'presentation',
3029
+ ...elementProps
3242
3030
  }
3243
- const anchorValue = anchorValueRef.current;
3031
+ });
3032
+ });
3033
+ if (process.env.NODE_ENV !== "production") MenuGroupLabel.displayName = "MenuGroupLabel";
3244
3034
 
3245
- // Refs from parent components are set after useLayoutEffect runs and are available in useEffect.
3246
- // Therefore, if the anchor is a ref, we need to update the position reference in useEffect.
3247
- if (typeof anchorValue === 'function') {
3248
- return;
3249
- }
3250
- if (isRef(anchorValue) && anchorValue.current !== registeredPositionReferenceRef.current) {
3251
- refs.setPositionReference(anchorValue.current);
3252
- registeredPositionReferenceRef.current = anchorValue.current;
3253
- }
3254
- }, [mounted, refs, anchorDep, anchorValueRef]);
3255
- React__namespace.useEffect(() => {
3256
- if (keepMounted && mounted && elements.domReference && elements.floating) {
3257
- return floatingUi_reactDom.autoUpdate(elements.domReference, elements.floating, update, autoUpdateOptions);
3258
- }
3259
- return undefined;
3260
- }, [keepMounted, mounted, elements, update, autoUpdateOptions]);
3261
- const renderedSide = index_esm.getSide(renderedPlacement);
3262
- const logicalRenderedSide = getLogicalSide(sideParam, renderedSide, isRtl);
3263
- const renderedAlign = index_esm.getAlignment(renderedPlacement) || 'center';
3264
- const anchorHidden = Boolean(middlewareData.hide?.referenceHidden);
3035
+ /**
3036
+ * An individual interactive item in the menu.
3037
+ * Renders a `<div>` element.
3038
+ *
3039
+ * Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
3040
+ */
3041
+ const MenuItem = /*#__PURE__*/React__namespace.forwardRef(function MenuItem(componentProps, forwardedRef) {
3042
+ const {
3043
+ render,
3044
+ className,
3045
+ id: idProp,
3046
+ label,
3047
+ nativeButton = false,
3048
+ disabled = false,
3049
+ closeOnClick = true,
3050
+ ...elementProps
3051
+ } = componentProps;
3052
+ const listItem = useCompositeListItem({
3053
+ label
3054
+ });
3055
+ const menuPositionerContext = useMenuPositionerContext(true);
3056
+ const id = clamp.useBaseUiId(idProp);
3057
+ const {
3058
+ store
3059
+ } = useMenuRootContext();
3060
+ const highlighted = store.useState('isActive', listItem.index);
3061
+ const itemProps = store.useState('itemProps');
3062
+ const {
3063
+ getItemProps,
3064
+ itemRef
3065
+ } = useMenuItem({
3066
+ closeOnClick,
3067
+ disabled,
3068
+ highlighted,
3069
+ id,
3070
+ store,
3071
+ nativeButton,
3072
+ nodeId: menuPositionerContext?.nodeId,
3073
+ itemMetadata: REGULAR_ITEM
3074
+ });
3075
+ const state = {
3076
+ disabled,
3077
+ highlighted
3078
+ };
3079
+ return useRenderElement.useRenderElement('div', componentProps, {
3080
+ state,
3081
+ props: [itemProps, elementProps, getItemProps],
3082
+ ref: [itemRef, forwardedRef, listItem.ref]
3083
+ });
3084
+ });
3085
+ if (process.env.NODE_ENV !== "production") MenuItem.displayName = "MenuItem";
3265
3086
 
3266
- /**
3267
- * Locks the flip (makes it "sticky") so it doesn't prefer a given placement
3268
- * and flips back lazily, not eagerly. Ideal for filtered lists that change
3269
- * the size of the popup dynamically to avoid unwanted flipping when typing.
3270
- */
3271
- useValueChanged.useIsoLayoutEffect(() => {
3272
- if (lazyFlip && mounted && isPositioned) {
3273
- setMountSide(renderedSide);
3274
- }
3275
- }, [lazyFlip, mounted, isPositioned, renderedSide]);
3276
- const arrowStyles = React__namespace.useMemo(() => ({
3277
- position: 'absolute',
3278
- top: middlewareData.arrow?.y,
3279
- left: middlewareData.arrow?.x
3280
- }), [middlewareData.arrow]);
3281
- const arrowUncentered = middlewareData.arrow?.centerOffset !== 0;
3282
- return React__namespace.useMemo(() => ({
3283
- positionerStyles: floatingStyles,
3284
- arrowStyles,
3285
- arrowRef,
3286
- arrowUncentered,
3287
- side: logicalRenderedSide,
3288
- align: renderedAlign,
3289
- physicalSide: renderedSide,
3290
- anchorHidden,
3291
- refs,
3292
- context,
3293
- isPositioned,
3294
- update
3295
- }), [floatingStyles, arrowStyles, arrowRef, arrowUncentered, logicalRenderedSide, renderedAlign, renderedSide, anchorHidden, refs, context, isPositioned, update]);
3296
- }
3297
- function isRef(param) {
3298
- return param != null && 'current' in param;
3087
+ /**
3088
+ * A link in the menu that can be used to navigate to a different page or section.
3089
+ * Renders an `<a>` element.
3090
+ *
3091
+ * Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
3092
+ */
3093
+ const MenuLinkItem = /*#__PURE__*/React__namespace.forwardRef(function MenuLinkItem(componentProps, forwardedRef) {
3094
+ const {
3095
+ render,
3096
+ className,
3097
+ id: idProp,
3098
+ label,
3099
+ closeOnClick = false,
3100
+ ...elementProps
3101
+ } = componentProps;
3102
+ const linkRef = React__namespace.useRef(null);
3103
+ const listItem = useCompositeListItem({
3104
+ label
3105
+ });
3106
+ const menuPositionerContext = useMenuPositionerContext(true);
3107
+ const nodeId = menuPositionerContext?.nodeId;
3108
+ const id = clamp.useBaseUiId(idProp);
3109
+ const {
3110
+ store
3111
+ } = useMenuRootContext();
3112
+ const highlighted = store.useState('isActive', listItem.index);
3113
+ const itemProps = store.useState('itemProps');
3114
+ const typingRef = store.context.typingRef;
3115
+ const {
3116
+ getButtonProps,
3117
+ buttonRef
3118
+ } = clamp.useButton({
3119
+ native: false,
3120
+ composite: true
3121
+ });
3122
+ const commonProps = useMenuItemCommonProps({
3123
+ closeOnClick,
3124
+ highlighted,
3125
+ id,
3126
+ nodeId,
3127
+ store,
3128
+ typingRef,
3129
+ itemRef: linkRef
3130
+ });
3131
+ function getItemProps(externalProps) {
3132
+ return useRenderElement.mergeProps(commonProps, externalProps, getButtonProps);
3133
+ }
3134
+ const state = React__namespace.useMemo(() => ({
3135
+ highlighted
3136
+ }), [highlighted]);
3137
+ return useRenderElement.useRenderElement('a', componentProps, {
3138
+ state,
3139
+ props: [itemProps, elementProps, getItemProps],
3140
+ ref: [linkRef, buttonRef, forwardedRef, listItem.ref]
3141
+ });
3142
+ });
3143
+ if (process.env.NODE_ENV !== "production") MenuLinkItem.displayName = "MenuLinkItem";
3144
+
3145
+ const ToolbarRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
3146
+ if (process.env.NODE_ENV !== "production") ToolbarRootContext.displayName = "ToolbarRootContext";
3147
+ function useToolbarRootContext(optional) {
3148
+ const context = React__namespace.useContext(ToolbarRootContext);
3149
+ if (context === undefined && !optional) {
3150
+ throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: ToolbarRootContext is missing. Toolbar parts must be placed within <Toolbar.Root>.' : useRenderElement.formatErrorMessage(69));
3151
+ }
3152
+ return context;
3299
3153
  }
3300
3154
 
3301
- /* eslint-disable no-bitwise */
3155
+ const stateAttributesMapping = {
3156
+ ...ScrollAreaViewport.popupStateMapping,
3157
+ ...clamp.transitionStatusMapping
3158
+ };
3159
+
3302
3160
  /**
3303
- * Provides context for a list of items in a composite component.
3304
- * @internal
3161
+ * A container for the menu items.
3162
+ * Renders a `<div>` element.
3163
+ *
3164
+ * Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
3305
3165
  */
3306
- function CompositeList(props) {
3166
+ const MenuPopup = /*#__PURE__*/React__namespace.forwardRef(function MenuPopup(componentProps, forwardedRef) {
3167
+ const {
3168
+ render,
3169
+ className,
3170
+ finalFocus,
3171
+ ...elementProps
3172
+ } = componentProps;
3173
+ const {
3174
+ store
3175
+ } = useMenuRootContext();
3307
3176
  const {
3308
- children,
3309
- elementsRef,
3310
- labelsRef,
3311
- onMapChange: onMapChangeProp
3312
- } = props;
3313
- const onMapChange = useValueChanged.useStableCallback(onMapChangeProp);
3314
- const nextIndexRef = React__namespace.useRef(0);
3315
- const listeners = useRenderElement.useRefWithInit(createListeners).current;
3316
-
3317
- // We use a stable `map` to avoid O(n^2) re-allocation costs for large lists.
3318
- // `mapTick` is our re-render trigger mechanism. We also need to update the
3319
- // elements and label refs, but there's a lot of async work going on and sometimes
3320
- // the effect that handles `onMapChange` gets called after those refs have been
3321
- // filled, and we don't want to lose those values by setting their lengths to `0`.
3322
- // We also need to have them at the proper length because floating-ui uses that
3323
- // information for list navigation.
3324
-
3325
- const map = useRenderElement.useRefWithInit(createMap).current;
3326
- // `mapTick` uses a counter rather than objects for low precision-loss risk and better memory efficiency
3327
- const [mapTick, setMapTick] = React__namespace.useState(0);
3328
- const lastTickRef = React__namespace.useRef(mapTick);
3329
- const register = useValueChanged.useStableCallback((node, metadata) => {
3330
- map.set(node, metadata ?? null);
3331
- lastTickRef.current += 1;
3332
- setMapTick(lastTickRef.current);
3333
- });
3334
- const unregister = useValueChanged.useStableCallback(node => {
3335
- map.delete(node);
3336
- lastTickRef.current += 1;
3337
- setMapTick(lastTickRef.current);
3338
- });
3339
- const sortedMap = React__namespace.useMemo(() => {
3340
- const newMap = new Map();
3341
- // Filter out disconnected elements before sorting to avoid inconsistent
3342
- // compareDocumentPosition results when elements are detached from the DOM.
3343
- const sortedNodes = Array.from(map.keys()).filter(node => node.isConnected).sort(sortByDocumentPosition);
3344
- sortedNodes.forEach((node, index) => {
3345
- const metadata = map.get(node) ?? {};
3346
- newMap.set(node, {
3347
- ...metadata,
3348
- index
3349
- });
3350
- });
3351
- return newMap;
3352
- }, [map, mapTick]);
3353
- useValueChanged.useIsoLayoutEffect(() => {
3354
- if (typeof MutationObserver !== 'function' || sortedMap.size === 0) {
3355
- return undefined;
3356
- }
3357
- const mutationObserver = new MutationObserver(entries => {
3358
- const diff = new Set();
3359
- const updateDiff = node => diff.has(node) ? diff.delete(node) : diff.add(node);
3360
- entries.forEach(entry => {
3361
- entry.removedNodes.forEach(updateDiff);
3362
- entry.addedNodes.forEach(updateDiff);
3363
- });
3364
- if (diff.size === 0) {
3365
- lastTickRef.current += 1;
3366
- setMapTick(lastTickRef.current);
3367
- }
3368
- });
3369
- sortedMap.forEach((_, node) => {
3370
- if (node.parentElement) {
3371
- mutationObserver.observe(node.parentElement, {
3372
- childList: true
3373
- });
3374
- }
3375
- });
3376
- return () => {
3377
- mutationObserver.disconnect();
3378
- };
3379
- }, [sortedMap]);
3380
- useValueChanged.useIsoLayoutEffect(() => {
3381
- const shouldUpdateLengths = lastTickRef.current === mapTick;
3382
- if (shouldUpdateLengths) {
3383
- if (elementsRef.current.length !== sortedMap.size) {
3384
- elementsRef.current.length = sortedMap.size;
3385
- }
3386
- if (labelsRef && labelsRef.current.length !== sortedMap.size) {
3387
- labelsRef.current.length = sortedMap.size;
3177
+ side,
3178
+ align
3179
+ } = useMenuPositionerContext();
3180
+ const insideToolbar = useToolbarRootContext(true) != null;
3181
+ const open = store.useState('open');
3182
+ const transitionStatus = store.useState('transitionStatus');
3183
+ const popupProps = store.useState('popupProps');
3184
+ const mounted = store.useState('mounted');
3185
+ const instantType = store.useState('instantType');
3186
+ const triggerElement = store.useState('activeTriggerElement');
3187
+ const parent = store.useState('parent');
3188
+ const lastOpenChangeReason = store.useState('lastOpenChangeReason');
3189
+ const rootId = store.useState('rootId');
3190
+ const floatingContext = store.useState('floatingRootContext');
3191
+ const floatingTreeRoot = store.useState('floatingTreeRoot');
3192
+ const closeDelay = store.useState('closeDelay');
3193
+ const activeTriggerElement = store.useState('activeTriggerElement');
3194
+ const isContextMenu = parent.type === 'context-menu';
3195
+ clamp.useOpenChangeComplete({
3196
+ open,
3197
+ ref: store.context.popupRef,
3198
+ onComplete() {
3199
+ if (open) {
3200
+ store.context.onOpenChangeComplete?.(true);
3388
3201
  }
3389
- nextIndexRef.current = sortedMap.size;
3390
3202
  }
3391
- onMapChange(sortedMap);
3392
- }, [onMapChange, sortedMap, elementsRef, labelsRef, mapTick]);
3393
- useValueChanged.useIsoLayoutEffect(() => {
3394
- return () => {
3395
- elementsRef.current = [];
3396
- };
3397
- }, [elementsRef]);
3398
- useValueChanged.useIsoLayoutEffect(() => {
3399
- return () => {
3400
- if (labelsRef) {
3401
- labelsRef.current = [];
3402
- }
3403
- };
3404
- }, [labelsRef]);
3405
- const subscribeMapChange = useValueChanged.useStableCallback(fn => {
3406
- listeners.add(fn);
3203
+ });
3204
+ React__namespace.useEffect(() => {
3205
+ function handleClose(event) {
3206
+ store.setOpen(false, clamp.createChangeEventDetails(event.reason, event.domEvent));
3207
+ }
3208
+ floatingTreeRoot.events.on('close', handleClose);
3407
3209
  return () => {
3408
- listeners.delete(fn);
3210
+ floatingTreeRoot.events.off('close', handleClose);
3409
3211
  };
3212
+ }, [floatingTreeRoot.events, store]);
3213
+ const hoverEnabled = store.useState('hoverEnabled');
3214
+ const disabled = store.useState('disabled');
3215
+ useHoverFloatingInteraction(floatingContext, {
3216
+ enabled: hoverEnabled && !disabled && !isContextMenu && parent.type !== 'menubar',
3217
+ closeDelay
3410
3218
  });
3411
- useValueChanged.useIsoLayoutEffect(() => {
3412
- listeners.forEach(l => l(sortedMap));
3413
- }, [listeners, sortedMap]);
3414
- const contextValue = React__namespace.useMemo(() => ({
3415
- register,
3416
- unregister,
3417
- subscribeMapChange,
3418
- elementsRef,
3419
- labelsRef,
3420
- nextIndexRef
3421
- }), [register, unregister, subscribeMapChange, elementsRef, labelsRef, nextIndexRef]);
3422
- return /*#__PURE__*/jsxRuntime.jsx(CompositeListContext.Provider, {
3423
- value: contextValue,
3424
- children: children
3219
+ const state = {
3220
+ transitionStatus,
3221
+ side,
3222
+ align,
3223
+ open,
3224
+ nested: parent.type === 'menu',
3225
+ instant: instantType
3226
+ };
3227
+ const setPopupElement = React__namespace.useCallback(element => {
3228
+ store.set('popupElement', element);
3229
+ }, [store]);
3230
+ const element = useRenderElement.useRenderElement('div', componentProps, {
3231
+ state,
3232
+ ref: [forwardedRef, store.context.popupRef, setPopupElement],
3233
+ stateAttributesMapping,
3234
+ props: [popupProps, {
3235
+ onKeyDown(event) {
3236
+ if (insideToolbar && ScrollAreaViewport.COMPOSITE_KEYS.has(event.key)) {
3237
+ event.stopPropagation();
3238
+ }
3239
+ }
3240
+ }, getDisabledMountTransitionStyles(transitionStatus), elementProps, {
3241
+ 'data-rootownerid': rootId
3242
+ }]
3425
3243
  });
3426
- }
3427
- function createMap() {
3428
- return new Map();
3429
- }
3430
- function createListeners() {
3431
- return new Set();
3432
- }
3433
- function sortByDocumentPosition(a, b) {
3434
- const position = a.compareDocumentPosition(b);
3435
- if (position & Node.DOCUMENT_POSITION_FOLLOWING || position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
3436
- return -1;
3244
+ let returnFocus = parent.type === undefined || isContextMenu;
3245
+ if (triggerElement || parent.type === 'menubar' && lastOpenChangeReason !== clamp.outsidePress) {
3246
+ returnFocus = true;
3437
3247
  }
3438
- if (position & Node.DOCUMENT_POSITION_PRECEDING || position & Node.DOCUMENT_POSITION_CONTAINS) {
3439
- return 1;
3248
+ return /*#__PURE__*/jsxRuntime.jsx(ScrollAreaViewport.FloatingFocusManager, {
3249
+ context: floatingContext,
3250
+ modal: isContextMenu,
3251
+ disabled: !mounted,
3252
+ returnFocus: finalFocus === undefined ? returnFocus : finalFocus,
3253
+ initialFocus: parent.type !== 'menu',
3254
+ restoreFocus: true,
3255
+ externalTree: parent.type !== 'menubar' ? floatingTreeRoot : undefined,
3256
+ previousFocusableElement: activeTriggerElement,
3257
+ nextFocusableElement: parent.type === undefined ? store.context.triggerFocusTargetRef : undefined,
3258
+ beforeContentFocusGuardRef: parent.type === undefined ? store.context.beforeContentFocusGuardRef : undefined,
3259
+ children: element
3260
+ });
3261
+ });
3262
+ if (process.env.NODE_ENV !== "production") MenuPopup.displayName = "MenuPopup";
3263
+
3264
+ const MenuPortalContext = /*#__PURE__*/React__namespace.createContext(undefined);
3265
+ if (process.env.NODE_ENV !== "production") MenuPortalContext.displayName = "MenuPortalContext";
3266
+ function useMenuPortalContext() {
3267
+ const value = React__namespace.useContext(MenuPortalContext);
3268
+ if (value === undefined) {
3269
+ throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Menu.Portal> is missing.' : useRenderElement.formatErrorMessage(32));
3440
3270
  }
3441
- return 0;
3271
+ return value;
3442
3272
  }
3443
3273
 
3274
+ const MenuPortal = /*#__PURE__*/React__namespace.forwardRef(function MenuPortal(props, forwardedRef) {
3275
+ const {
3276
+ keepMounted = false,
3277
+ ...portalProps
3278
+ } = props;
3279
+ const {
3280
+ store
3281
+ } = useMenuRootContext();
3282
+ const mounted = store.useState('mounted');
3283
+ const shouldRender = mounted || keepMounted;
3284
+ if (!shouldRender) {
3285
+ return null;
3286
+ }
3287
+ return /*#__PURE__*/jsxRuntime.jsx(MenuPortalContext.Provider, {
3288
+ value: keepMounted,
3289
+ children: /*#__PURE__*/jsxRuntime.jsx(ScrollAreaViewport.FloatingPortal, {
3290
+ ref: forwardedRef,
3291
+ ...portalProps
3292
+ })
3293
+ });
3294
+ });
3295
+ if (process.env.NODE_ENV !== "production") MenuPortal.displayName = "MenuPortal";
3296
+
3444
3297
  const MenuPositioner = /*#__PURE__*/React__namespace.forwardRef(function MenuPositioner(componentProps, forwardedRef) {
3445
3298
  const {
3446
3299
  anchor: anchorProp,
@@ -3456,7 +3309,7 @@ const MenuPositioner = /*#__PURE__*/React__namespace.forwardRef(function MenuPos
3456
3309
  arrowPadding = 5,
3457
3310
  sticky = false,
3458
3311
  disableAnchorTracking = false,
3459
- collisionAvoidance: collisionAvoidanceProp = DrawerRoot.DROPDOWN_COLLISION_AVOIDANCE,
3312
+ collisionAvoidance: collisionAvoidanceProp = ScrollAreaViewport.DROPDOWN_COLLISION_AVOIDANCE,
3460
3313
  ...elementProps
3461
3314
  } = componentProps;
3462
3315
  const {
@@ -3480,7 +3333,7 @@ const MenuPositioner = /*#__PURE__*/React__namespace.forwardRef(function MenuPos
3480
3333
  const floatingParentNodeId = store.useState('floatingParentNodeId');
3481
3334
  const domReference = floatingRootContext.useState('domReferenceElement');
3482
3335
  const previousTriggerRef = React__namespace.useRef(null);
3483
- const runOnceAnimationsFinish = useValueChanged.useAnimationsFinished(positionerElement, false, false);
3336
+ const runOnceAnimationsFinish = clamp.useAnimationsFinished(positionerElement, false, false);
3484
3337
  let anchor = anchorProp;
3485
3338
  let sideOffset = sideOffsetProp;
3486
3339
  let alignOffset = alignOffsetProp;
@@ -3499,7 +3352,7 @@ const MenuPositioner = /*#__PURE__*/React__namespace.forwardRef(function MenuPos
3499
3352
  if (parent.type === 'menu') {
3500
3353
  computedSide = computedSide ?? 'inline-end';
3501
3354
  computedAlign = computedAlign ?? 'start';
3502
- collisionAvoidance = componentProps.collisionAvoidance ?? DrawerRoot.POPUP_COLLISION_AVOIDANCE;
3355
+ collisionAvoidance = componentProps.collisionAvoidance ?? ScrollAreaViewport.POPUP_COLLISION_AVOIDANCE;
3503
3356
  } else if (parent.type === 'menubar') {
3504
3357
  computedSide = computedSide ?? 'bottom';
3505
3358
  computedAlign = computedAlign ?? 'start';
@@ -3547,7 +3400,7 @@ const MenuPositioner = /*#__PURE__*/React__namespace.forwardRef(function MenuPos
3547
3400
  store.set('hoverEnabled', false);
3548
3401
  }
3549
3402
  if (details.nodeId !== floatingNodeId && details.parentNodeId === store.select('floatingParentNodeId')) {
3550
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.siblingOpen));
3403
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.siblingOpen));
3551
3404
  }
3552
3405
  }
3553
3406
  }
@@ -3564,15 +3417,15 @@ const MenuPositioner = /*#__PURE__*/React__namespace.forwardRef(function MenuPos
3564
3417
  if (details.open || details.nodeId !== store.select('floatingParentNodeId')) {
3565
3418
  return;
3566
3419
  }
3567
- const reason = details.reason ?? useValueChanged.siblingOpen;
3568
- store.setOpen(false, useValueChanged.createChangeEventDetails(reason));
3420
+ const reason = details.reason ?? clamp.siblingOpen;
3421
+ store.setOpen(false, clamp.createChangeEventDetails(reason));
3569
3422
  }
3570
3423
  floatingTreeRoot.events.on('menuopenchange', onParentClose);
3571
3424
  return () => {
3572
3425
  floatingTreeRoot.events.off('menuopenchange', onParentClose);
3573
3426
  };
3574
3427
  }, [floatingTreeRoot.events, store]);
3575
- const closeTimeout = useValueChanged.useTimeout();
3428
+ const closeTimeout = clamp.useTimeout();
3576
3429
 
3577
3430
  // Clear pending close timeout when the menu closes.
3578
3431
  React__namespace.useEffect(() => {
@@ -3594,11 +3447,11 @@ const MenuPositioner = /*#__PURE__*/React__namespace.forwardRef(function MenuPos
3594
3447
  if (delay > 0) {
3595
3448
  if (!closeTimeout.isStarted()) {
3596
3449
  closeTimeout.start(delay, () => {
3597
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.siblingOpen));
3450
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.siblingOpen));
3598
3451
  });
3599
3452
  }
3600
3453
  } else {
3601
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.siblingOpen));
3454
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.siblingOpen));
3602
3455
  }
3603
3456
  } else {
3604
3457
  // User re-hovered the submenu trigger, cancel pending close.
@@ -3621,7 +3474,7 @@ const MenuPositioner = /*#__PURE__*/React__namespace.forwardRef(function MenuPos
3621
3474
  }, [floatingTreeRoot.events, open, store, floatingNodeId, floatingParentNodeId]);
3622
3475
 
3623
3476
  // Keep positioner transition behavior aligned with Popover when switching detached triggers.
3624
- useValueChanged.useIsoLayoutEffect(() => {
3477
+ clamp.useIsoLayoutEffect(() => {
3625
3478
  const currentTrigger = domReference;
3626
3479
  const previousTrigger = previousTriggerRef.current;
3627
3480
  if (currentTrigger) {
@@ -3657,11 +3510,11 @@ const MenuPositioner = /*#__PURE__*/React__namespace.forwardRef(function MenuPos
3657
3510
  }), [positioner.side, positioner.align, positioner.arrowRef, positioner.arrowUncentered, positioner.arrowStyles, positioner.context.nodeId]);
3658
3511
  const element = useRenderElement.useRenderElement('div', componentProps, {
3659
3512
  state,
3660
- stateAttributesMapping: DrawerRoot.popupStateMapping,
3513
+ stateAttributesMapping: ScrollAreaViewport.popupStateMapping,
3661
3514
  ref: [forwardedRef, store.useStateSetter('positionerElement')],
3662
3515
  props: [positionerProps, getDisabledMountTransitionStyles(transitionStatus), elementProps]
3663
3516
  });
3664
- const shouldRenderBackdrop = mounted && parent.type !== 'menu' && (parent.type !== 'menubar' && modal && lastOpenChangeReason !== useValueChanged.triggerHover || parent.type === 'menubar' && parent.context.modal);
3517
+ const shouldRenderBackdrop = mounted && parent.type !== 'menu' && (parent.type !== 'menubar' && modal && lastOpenChangeReason !== clamp.triggerHover || parent.type === 'menubar' && parent.context.modal);
3665
3518
 
3666
3519
  // cuts a hole in the backdrop to allow pointer interaction with the menubar or dropdown menu trigger element
3667
3520
  let backdropCutout = null;
@@ -3672,11 +3525,11 @@ const MenuPositioner = /*#__PURE__*/React__namespace.forwardRef(function MenuPos
3672
3525
  }
3673
3526
  return /*#__PURE__*/jsxRuntime.jsxs(MenuPositionerContext.Provider, {
3674
3527
  value: contextValue,
3675
- children: [shouldRenderBackdrop && /*#__PURE__*/jsxRuntime.jsx(DrawerRoot.InternalBackdrop, {
3528
+ children: [shouldRenderBackdrop && /*#__PURE__*/jsxRuntime.jsx(ScrollAreaViewport.InternalBackdrop, {
3676
3529
  ref: parent.type === 'context-menu' || parent.type === 'nested-context-menu' ? parent.context.internalBackdropRef : null,
3677
- inert: DrawerRoot.inertValue(!open),
3530
+ inert: ScrollAreaViewport.inertValue(!open),
3678
3531
  cutout: backdropCutout
3679
- }), /*#__PURE__*/jsxRuntime.jsx(DrawerRoot.FloatingNode, {
3532
+ }), /*#__PURE__*/jsxRuntime.jsx(ScrollAreaViewport.FloatingNode, {
3680
3533
  id: floatingNodeId,
3681
3534
  children: /*#__PURE__*/jsxRuntime.jsx(CompositeList, {
3682
3535
  elementsRef: store.context.itemDomElements,
@@ -3714,13 +3567,13 @@ const MenuRadioGroup = /*#__PURE__*/React__namespace.memo(/*#__PURE__*/React__na
3714
3567
  disabled = false,
3715
3568
  ...elementProps
3716
3569
  } = componentProps;
3717
- const [value, setValueUnwrapped] = useValueChanged.useControlled({
3570
+ const [value, setValueUnwrapped] = clamp.useControlled({
3718
3571
  controlled: valueProp,
3719
3572
  default: defaultValue,
3720
3573
  name: 'MenuRadioGroup'
3721
3574
  });
3722
- const onValueChange = useValueChanged.useStableCallback(onValueChangeProp);
3723
- const setValue = useValueChanged.useStableCallback((newValue, eventDetails) => {
3575
+ const onValueChange = clamp.useStableCallback(onValueChangeProp);
3576
+ const setValue = clamp.useStableCallback((newValue, eventDetails) => {
3724
3577
  onValueChange?.(newValue, eventDetails);
3725
3578
  if (eventDetails.isCanceled) {
3726
3579
  return;
@@ -3777,7 +3630,7 @@ const MenuRadioItem = /*#__PURE__*/React__namespace.forwardRef(function MenuRadi
3777
3630
  label
3778
3631
  });
3779
3632
  const menuPositionerContext = useMenuPositionerContext(true);
3780
- const id = useBaseUiId.useBaseUiId(idProp);
3633
+ const id = clamp.useBaseUiId(idProp);
3781
3634
  const {
3782
3635
  store
3783
3636
  } = useMenuRootContext();
@@ -3808,9 +3661,9 @@ const MenuRadioItem = /*#__PURE__*/React__namespace.forwardRef(function MenuRadi
3808
3661
  highlighted,
3809
3662
  checked
3810
3663
  }), [disabled, highlighted, checked]);
3811
- const handleClick = useValueChanged.useStableCallback(event => {
3664
+ const handleClick = clamp.useStableCallback(event => {
3812
3665
  const details = {
3813
- ...useValueChanged.createChangeEventDetails(useValueChanged.itemPress, event.nativeEvent),
3666
+ ...clamp.createChangeEventDetails(clamp.itemPress, event.nativeEvent),
3814
3667
  preventUnmountOnClose: () => {}
3815
3668
  };
3816
3669
  setSelectedValue(value, details);
@@ -3850,8 +3703,8 @@ const MenuRadioItemIndicator = /*#__PURE__*/React__namespace.forwardRef(function
3850
3703
  const {
3851
3704
  transitionStatus,
3852
3705
  setMounted
3853
- } = useValueChanged.useTransitionStatus(item.checked);
3854
- useValueChanged.useOpenChangeComplete({
3706
+ } = clamp.useTransitionStatus(item.checked);
3707
+ clamp.useOpenChangeComplete({
3855
3708
  open: item.checked,
3856
3709
  ref: indicatorRef,
3857
3710
  onComplete() {
@@ -3891,35 +3744,35 @@ function useMenubarContext(optional) {
3891
3744
  }
3892
3745
 
3893
3746
  const selectors = {
3894
- ...DrawerRoot.popupStoreSelectors,
3895
- disabled: DrawerRoot.createSelector(state => state.parent.type === 'menubar' ? state.parent.context.disabled || state.disabled : state.disabled),
3896
- modal: DrawerRoot.createSelector(state => (state.parent.type === undefined || state.parent.type === 'context-menu') && (state.modal ?? true)),
3897
- allowMouseEnter: DrawerRoot.createSelector(state => state.allowMouseEnter),
3898
- stickIfOpen: DrawerRoot.createSelector(state => state.stickIfOpen),
3899
- parent: DrawerRoot.createSelector(state => state.parent),
3900
- rootId: DrawerRoot.createSelector(state => {
3747
+ ...ScrollAreaViewport.popupStoreSelectors,
3748
+ disabled: ScrollAreaViewport.createSelector(state => state.parent.type === 'menubar' ? state.parent.context.disabled || state.disabled : state.disabled),
3749
+ modal: ScrollAreaViewport.createSelector(state => (state.parent.type === undefined || state.parent.type === 'context-menu') && (state.modal ?? true)),
3750
+ allowMouseEnter: ScrollAreaViewport.createSelector(state => state.allowMouseEnter),
3751
+ stickIfOpen: ScrollAreaViewport.createSelector(state => state.stickIfOpen),
3752
+ parent: ScrollAreaViewport.createSelector(state => state.parent),
3753
+ rootId: ScrollAreaViewport.createSelector(state => {
3901
3754
  if (state.parent.type === 'menu') {
3902
3755
  return state.parent.store.select('rootId');
3903
3756
  }
3904
3757
  return state.parent.type !== undefined ? state.parent.context.rootId : state.rootId;
3905
3758
  }),
3906
- activeIndex: DrawerRoot.createSelector(state => state.activeIndex),
3907
- isActive: DrawerRoot.createSelector((state, itemIndex) => state.activeIndex === itemIndex),
3908
- hoverEnabled: DrawerRoot.createSelector(state => state.hoverEnabled),
3909
- instantType: DrawerRoot.createSelector(state => state.instantType),
3910
- lastOpenChangeReason: DrawerRoot.createSelector(state => state.openChangeReason),
3911
- floatingTreeRoot: DrawerRoot.createSelector(state => {
3759
+ activeIndex: ScrollAreaViewport.createSelector(state => state.activeIndex),
3760
+ isActive: ScrollAreaViewport.createSelector((state, itemIndex) => state.activeIndex === itemIndex),
3761
+ hoverEnabled: ScrollAreaViewport.createSelector(state => state.hoverEnabled),
3762
+ instantType: ScrollAreaViewport.createSelector(state => state.instantType),
3763
+ lastOpenChangeReason: ScrollAreaViewport.createSelector(state => state.openChangeReason),
3764
+ floatingTreeRoot: ScrollAreaViewport.createSelector(state => {
3912
3765
  if (state.parent.type === 'menu') {
3913
3766
  return state.parent.store.select('floatingTreeRoot');
3914
3767
  }
3915
3768
  return state.floatingTreeRoot;
3916
3769
  }),
3917
- floatingNodeId: DrawerRoot.createSelector(state => state.floatingNodeId),
3918
- floatingParentNodeId: DrawerRoot.createSelector(state => state.floatingParentNodeId),
3919
- itemProps: DrawerRoot.createSelector(state => state.itemProps),
3920
- closeDelay: DrawerRoot.createSelector(state => state.closeDelay),
3921
- hasViewport: DrawerRoot.createSelector(state => state.hasViewport),
3922
- keyboardEventRelay: DrawerRoot.createSelector(state => {
3770
+ floatingNodeId: ScrollAreaViewport.createSelector(state => state.floatingNodeId),
3771
+ floatingParentNodeId: ScrollAreaViewport.createSelector(state => state.floatingParentNodeId),
3772
+ itemProps: ScrollAreaViewport.createSelector(state => state.itemProps),
3773
+ closeDelay: ScrollAreaViewport.createSelector(state => state.closeDelay),
3774
+ hasViewport: ScrollAreaViewport.createSelector(state => state.hasViewport),
3775
+ keyboardEventRelay: ScrollAreaViewport.createSelector(state => {
3923
3776
  if (state.keyboardEventRelay) {
3924
3777
  return state.keyboardEventRelay;
3925
3778
  }
@@ -3929,7 +3782,7 @@ const selectors = {
3929
3782
  return undefined;
3930
3783
  })
3931
3784
  };
3932
- class MenuStore extends DrawerRoot.ReactStore {
3785
+ class MenuStore extends ScrollAreaViewport.ReactStore {
3933
3786
  constructor(initialState) {
3934
3787
  super({
3935
3788
  ...createInitialState(),
@@ -3952,7 +3805,7 @@ class MenuStore extends DrawerRoot.ReactStore {
3952
3805
  triggerFocusTargetRef: /*#__PURE__*/React__namespace.createRef(),
3953
3806
  beforeContentFocusGuardRef: /*#__PURE__*/React__namespace.createRef(),
3954
3807
  onOpenChangeComplete: undefined,
3955
- triggerElements: new DrawerRoot.PopupTriggerMap()
3808
+ triggerElements: new ScrollAreaViewport.PopupTriggerMap()
3956
3809
  }, selectors);
3957
3810
 
3958
3811
  // Set up propagation of state from parent menu if applicable.
@@ -4000,7 +3853,7 @@ class MenuStore extends DrawerRoot.ReactStore {
4000
3853
  }
4001
3854
  function createInitialState() {
4002
3855
  return {
4003
- ...DrawerRoot.createInitialPopupStoreState(),
3856
+ ...ScrollAreaViewport.createInitialPopupStoreState(),
4004
3857
  disabled: false,
4005
3858
  modal: true,
4006
3859
  allowMouseEnter: false,
@@ -4013,7 +3866,7 @@ function createInitialState() {
4013
3866
  hoverEnabled: true,
4014
3867
  instantType: undefined,
4015
3868
  openChangeReason: null,
4016
- floatingTreeRoot: new DrawerRoot.FloatingTreeStore(),
3869
+ floatingTreeRoot: new ScrollAreaViewport.FloatingTreeStore(),
4017
3870
  floatingNodeId: undefined,
4018
3871
  floatingParentNodeId: null,
4019
3872
  itemProps: useRenderElement.EMPTY_OBJECT,
@@ -4029,7 +3882,7 @@ function useMenuSubmenuRootContext() {
4029
3882
  return React__namespace.useContext(MenuSubmenuRootContext);
4030
3883
  }
4031
3884
 
4032
- const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
3885
+ const MenuRoot = ScrollAreaViewport.fastComponent(function MenuRoot(props) {
4033
3886
  const {
4034
3887
  children,
4035
3888
  open: openProp,
@@ -4087,7 +3940,7 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4087
3940
  });
4088
3941
 
4089
3942
  // Support initially open state when uncontrolled
4090
- DrawerRoot.useOnFirstRender(() => {
3943
+ ScrollAreaViewport.useOnFirstRender(() => {
4091
3944
  if (openProp === undefined && store.state.open === false && defaultOpen === true) {
4092
3945
  store.update({
4093
3946
  open: true,
@@ -4099,9 +3952,9 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4099
3952
  store.useControlledProp('triggerIdProp', triggerIdProp);
4100
3953
  store.useContextCallback('onOpenChangeComplete', onOpenChangeComplete);
4101
3954
  const floatingTreeRoot = store.useState('floatingTreeRoot');
4102
- const floatingNodeIdFromContext = DrawerRoot.useFloatingNodeId(floatingTreeRoot);
4103
- const floatingParentNodeIdFromContext = DrawerRoot.useFloatingParentNodeId();
4104
- useValueChanged.useIsoLayoutEffect(() => {
3955
+ const floatingNodeIdFromContext = ScrollAreaViewport.useFloatingNodeId(floatingTreeRoot);
3956
+ const floatingParentNodeIdFromContext = ScrollAreaViewport.useFloatingParentNodeId();
3957
+ clamp.useIsoLayoutEffect(() => {
4105
3958
  if (contextMenuContext && !parentMenuRootContext) {
4106
3959
  // This is a context menu root.
4107
3960
  // It doesn't support detached triggers yet, so we have to sync the parent context manually.
@@ -4142,23 +3995,23 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4142
3995
  store.useSyncedValues({
4143
3996
  disabled: disabledProp,
4144
3997
  modal: parent.type === undefined ? modalProp : undefined,
4145
- rootId: useValueChanged.useId()
3998
+ rootId: clamp.useId()
4146
3999
  });
4147
4000
  const {
4148
4001
  openMethod,
4149
4002
  triggerProps: interactionTypeProps
4150
- } = DrawerRoot.useOpenInteractionType(open);
4151
- DrawerRoot.useImplicitActiveTrigger(store);
4003
+ } = ScrollAreaViewport.useOpenInteractionType(open);
4004
+ ScrollAreaViewport.useImplicitActiveTrigger(store);
4152
4005
  const {
4153
4006
  forceUnmount
4154
- } = DrawerRoot.useOpenStateTransitions(open, store, () => {
4007
+ } = ScrollAreaViewport.useOpenStateTransitions(open, store, () => {
4155
4008
  store.update({
4156
4009
  allowMouseEnter: false,
4157
4010
  stickIfOpen: true
4158
4011
  });
4159
4012
  });
4160
4013
  const allowOutsidePressDismissalRef = React__namespace.useRef(parent.type !== 'context-menu');
4161
- const allowOutsidePressDismissalTimeout = useValueChanged.useTimeout();
4014
+ const allowOutsidePressDismissalTimeout = clamp.useTimeout();
4162
4015
  React__namespace.useEffect(() => {
4163
4016
  if (!open) {
4164
4017
  openEventRef.current = null;
@@ -4179,15 +4032,15 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4179
4032
  allowOutsidePressDismissalRef.current = true;
4180
4033
  });
4181
4034
  }, [allowOutsidePressDismissalTimeout, open, parent.type]);
4182
- DrawerRoot.useScrollLock(open && modal && lastOpenChangeReason !== useValueChanged.triggerHover && openMethod !== 'touch', positionerElement);
4183
- useValueChanged.useIsoLayoutEffect(() => {
4035
+ ScrollAreaViewport.useScrollLock(open && modal && lastOpenChangeReason !== clamp.triggerHover && openMethod !== 'touch', positionerElement);
4036
+ clamp.useIsoLayoutEffect(() => {
4184
4037
  if (!open && !hoverEnabled) {
4185
4038
  store.set('hoverEnabled', true);
4186
4039
  }
4187
4040
  }, [open, hoverEnabled, store]);
4188
4041
  const allowTouchToCloseRef = React__namespace.useRef(true);
4189
- const allowTouchToCloseTimeout = useValueChanged.useTimeout();
4190
- const setOpen = useValueChanged.useStableCallback((nextOpen, eventDetails) => {
4042
+ const allowTouchToCloseTimeout = clamp.useTimeout();
4043
+ const setOpen = clamp.useStableCallback((nextOpen, eventDetails) => {
4191
4044
  const reason = eventDetails.reason;
4192
4045
  if (open === nextOpen && eventDetails.trigger === activeTriggerElement && lastOpenChangeReason === reason) {
4193
4046
  return;
@@ -4233,7 +4086,7 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4233
4086
  // Prevent the menu from closing on mobile devices that have a delayed click event.
4234
4087
  // In some cases the menu, when tapped, will fire the focus event first and then the click event.
4235
4088
  // Without this guard, the menu will close immediately after opening.
4236
- if (nextOpen && reason === useValueChanged.triggerFocus) {
4089
+ if (nextOpen && reason === clamp.triggerFocus) {
4237
4090
  allowTouchToCloseRef.current = false;
4238
4091
  allowTouchToCloseTimeout.start(300, () => {
4239
4092
  allowTouchToCloseRef.current = true;
@@ -4242,8 +4095,8 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4242
4095
  allowTouchToCloseRef.current = true;
4243
4096
  allowTouchToCloseTimeout.clear();
4244
4097
  }
4245
- const isKeyboardClick = (reason === useValueChanged.triggerPress || reason === useValueChanged.itemPress) && nativeEvent.detail === 0 && nativeEvent?.isTrusted;
4246
- const isDismissClose = !nextOpen && (reason === useValueChanged.escapeKey || reason == null);
4098
+ const isKeyboardClick = (reason === clamp.triggerPress || reason === clamp.itemPress) && nativeEvent.detail === 0 && nativeEvent?.isTrusted;
4099
+ const isDismissClose = !nextOpen && (reason === clamp.escapeKey || reason == null);
4247
4100
  const updatedState = {
4248
4101
  open: nextOpen,
4249
4102
  openChangeReason: reason
@@ -4258,7 +4111,7 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4258
4111
  updatedState.activeTriggerElement = eventDetails.trigger ?? null;
4259
4112
  }
4260
4113
  store.update(updatedState);
4261
- if (parent.type === 'menubar' && (reason === useValueChanged.triggerFocus || reason === useValueChanged.focusOut || reason === useValueChanged.triggerHover || reason === useValueChanged.listNavigation || reason === useValueChanged.siblingOpen)) {
4114
+ if (parent.type === 'menubar' && (reason === clamp.triggerFocus || reason === clamp.focusOut || reason === clamp.triggerHover || reason === clamp.listNavigation || reason === clamp.siblingOpen)) {
4262
4115
  store.set('instantType', 'group');
4263
4116
  } else if (isKeyboardClick || isDismissClose) {
4264
4117
  store.set('instantType', isKeyboardClick ? 'click' : 'dismiss');
@@ -4267,14 +4120,14 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4267
4120
  }
4268
4121
  });
4269
4122
  const createMenuEventDetails = React__namespace.useCallback(reason => {
4270
- const details = useValueChanged.createChangeEventDetails(reason);
4123
+ const details = clamp.createChangeEventDetails(reason);
4271
4124
  details.preventUnmountOnClose = () => {
4272
4125
  store.set('preventUnmountingOnClose', true);
4273
4126
  };
4274
4127
  return details;
4275
4128
  }, [store]);
4276
4129
  const handleImperativeClose = React__namespace.useCallback(() => {
4277
- store.setOpen(false, createMenuEventDetails(useValueChanged.imperativeAction));
4130
+ store.setOpen(false, createMenuEventDetails(clamp.imperativeAction));
4278
4131
  }, [store, createMenuEventDetails]);
4279
4132
  React__namespace.useImperativeHandle(actionsRef, () => ({
4280
4133
  unmount: forceUnmount,
@@ -4288,7 +4141,7 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4288
4141
  React__namespace.useImperativeHandle(ctx?.actionsRef, () => ({
4289
4142
  setOpen
4290
4143
  }), [setOpen]);
4291
- const floatingRootContext = DrawerRoot.useSyncedFloatingRootContext({
4144
+ const floatingRootContext = ScrollAreaViewport.useSyncedFloatingRootContext({
4292
4145
  popupStore: store,
4293
4146
  onOpenChange: setOpen
4294
4147
  });
@@ -4303,7 +4156,7 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4303
4156
  floatingEvents?.off('setOpen', handleSetOpenEvent);
4304
4157
  };
4305
4158
  }, [floatingEvents, setOpen]);
4306
- const dismiss = DrawerRoot.useDismiss(floatingRootContext, {
4159
+ const dismiss = ScrollAreaViewport.useDismiss(floatingRootContext, {
4307
4160
  enabled: !disabled,
4308
4161
  bubbles: {
4309
4162
  escapeKey: closeParentOnEsc && parent.type === 'menu'
@@ -4316,10 +4169,10 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4316
4169
  },
4317
4170
  externalTree: nested ? floatingTreeRoot : undefined
4318
4171
  });
4319
- const role = DrawerRoot.useRole(floatingRootContext, {
4172
+ const role = ScrollAreaViewport.useRole(floatingRootContext, {
4320
4173
  role: 'menu'
4321
4174
  });
4322
- const direction = useDirection();
4175
+ const direction = ScrollAreaViewport.useDirection();
4323
4176
  const setActiveIndex = React__namespace.useCallback(index => {
4324
4177
  if (store.select('activeIndex') === index) {
4325
4178
  return;
@@ -4348,7 +4201,7 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4348
4201
  listRef: store.context.itemLabels,
4349
4202
  elementsRef: store.context.itemDomElements,
4350
4203
  activeIndex,
4351
- resetMs: DrawerRoot.TYPEAHEAD_RESET_MS,
4204
+ resetMs: ScrollAreaViewport.TYPEAHEAD_RESET_MS,
4352
4205
  onMatch: index => {
4353
4206
  if (open && index !== activeIndex) {
4354
4207
  store.set('activeIndex', index);
@@ -4361,7 +4214,7 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4361
4214
  getFloatingProps,
4362
4215
  getItemProps,
4363
4216
  getTriggerProps
4364
- } = DrawerRoot.useInteractions([dismiss, role, listNavigation, typeahead]);
4217
+ } = ScrollAreaViewport.useInteractions([dismiss, role, listNavigation, typeahead]);
4365
4218
  const activeTriggerProps = React__namespace.useMemo(() => {
4366
4219
  const mergedProps = useRenderElement.mergeProps(getReferenceProps(), {
4367
4220
  onMouseMove() {
@@ -4423,7 +4276,7 @@ const MenuRoot = DrawerRoot.fastComponent(function MenuRoot(props) {
4423
4276
  });
4424
4277
  if (parent.type === undefined || parent.type === 'context-menu') {
4425
4278
  // set up a FloatingTree to provide the context to nested menus
4426
- return /*#__PURE__*/jsxRuntime.jsx(DrawerRoot.FloatingTree, {
4279
+ return /*#__PURE__*/jsxRuntime.jsx(ScrollAreaViewport.FloatingTree, {
4427
4280
  externalTree: floatingTreeRoot,
4428
4281
  children: content
4429
4282
  });
@@ -4451,47 +4304,12 @@ function MenuSubmenuRoot(props) {
4451
4304
  });
4452
4305
  }
4453
4306
 
4454
- function getPseudoElementBounds(element) {
4455
- const elementRect = element.getBoundingClientRect();
4456
-
4457
- // Avoid "Not implemented: window.getComputedStyle(elt, pseudoElt)"
4458
- if (process.env.NODE_ENV !== 'production') {
4459
- return elementRect;
4460
- }
4461
- const beforeStyles = window.getComputedStyle(element, '::before');
4462
- const afterStyles = window.getComputedStyle(element, '::after');
4463
- const hasPseudoElements = beforeStyles.content !== 'none' || afterStyles.content !== 'none';
4464
- if (!hasPseudoElements) {
4465
- return elementRect;
4466
- }
4467
-
4468
- // Get dimensions of pseudo-elements
4469
- const beforeWidth = parseFloat(beforeStyles.width) || 0;
4470
- const beforeHeight = parseFloat(beforeStyles.height) || 0;
4471
- const afterWidth = parseFloat(afterStyles.width) || 0;
4472
- const afterHeight = parseFloat(afterStyles.height) || 0;
4473
-
4474
- // Calculate max dimensions including pseudo-elements
4475
- const totalWidth = Math.max(elementRect.width, beforeWidth, afterWidth);
4476
- const totalHeight = Math.max(elementRect.height, beforeHeight, afterHeight);
4477
-
4478
- // Calculate the differences to extend the bounds
4479
- const widthDiff = totalWidth - elementRect.width;
4480
- const heightDiff = totalHeight - elementRect.height;
4481
- return {
4482
- left: elementRect.left - widthDiff / 2,
4483
- right: elementRect.right + widthDiff / 2,
4484
- top: elementRect.top - heightDiff / 2,
4485
- bottom: elementRect.bottom + heightDiff / 2
4486
- };
4487
- }
4488
-
4489
4307
  function useCompositeItem(params = {}) {
4490
4308
  const {
4491
4309
  highlightItemOnHover,
4492
4310
  highlightedIndex,
4493
4311
  onHighlightedIndexChange
4494
- } = useBaseUiId.useCompositeRootContext();
4312
+ } = clamp.useCompositeRootContext();
4495
4313
  const {
4496
4314
  ref,
4497
4315
  index
@@ -4581,7 +4399,7 @@ function useMixedToggleClickHandler(params) {
4581
4399
  onMouseDown: event => {
4582
4400
  if (mouseDownAction === 'open' && !open || mouseDownAction === 'close' && open) {
4583
4401
  ignoreClickRef.current = true;
4584
- useValueChanged.ownerDocument(event.currentTarget).addEventListener('click', () => {
4402
+ clamp.ownerDocument(event.currentTarget).addEventListener('click', () => {
4585
4403
  ignoreClickRef.current = false;
4586
4404
  }, {
4587
4405
  once: true
@@ -4606,7 +4424,7 @@ const BOUNDARY_OFFSET = 2;
4606
4424
  *
4607
4425
  * Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
4608
4426
  */
4609
- const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentProps, forwardedRef) {
4427
+ const MenuTrigger = ScrollAreaViewport.fastComponentRef(function MenuTrigger(componentProps, forwardedRef) {
4610
4428
  const {
4611
4429
  render,
4612
4430
  className,
@@ -4625,23 +4443,23 @@ const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentPr
4625
4443
  if (!store) {
4626
4444
  throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Menu.Trigger> must be either used within a <Menu.Root> component or provided with a handle.' : useRenderElement.formatErrorMessage(85));
4627
4445
  }
4628
- const thisTriggerId = useBaseUiId.useBaseUiId(idProp);
4446
+ const thisTriggerId = clamp.useBaseUiId(idProp);
4629
4447
  const isTriggerActive = store.useState('isTriggerActive', thisTriggerId);
4630
4448
  const floatingRootContext = store.useState('floatingRootContext');
4631
4449
  const isOpenedByThisTrigger = store.useState('isOpenedByTrigger', thisTriggerId);
4632
4450
  const triggerElementRef = React__namespace.useRef(null);
4633
4451
  const parent = useMenuParent();
4634
- const compositeRootContext = useBaseUiId.useCompositeRootContext(true);
4635
- const floatingTreeRootFromContext = DrawerRoot.useFloatingTree();
4452
+ const compositeRootContext = clamp.useCompositeRootContext(true);
4453
+ const floatingTreeRootFromContext = ScrollAreaViewport.useFloatingTree();
4636
4454
  const floatingTreeRoot = React__namespace.useMemo(() => {
4637
- return floatingTreeRootFromContext ?? new DrawerRoot.FloatingTreeStore();
4455
+ return floatingTreeRootFromContext ?? new ScrollAreaViewport.FloatingTreeStore();
4638
4456
  }, [floatingTreeRootFromContext]);
4639
- const floatingNodeId = DrawerRoot.useFloatingNodeId(floatingTreeRoot);
4640
- const floatingParentNodeId = DrawerRoot.useFloatingParentNodeId();
4457
+ const floatingNodeId = ScrollAreaViewport.useFloatingNodeId(floatingTreeRoot);
4458
+ const floatingParentNodeId = ScrollAreaViewport.useFloatingParentNodeId();
4641
4459
  const {
4642
4460
  registerTrigger,
4643
4461
  isMountedByThisTrigger
4644
- } = DrawerRoot.useTriggerDataForwarding(thisTriggerId, triggerElementRef, store, {
4462
+ } = ScrollAreaViewport.useTriggerDataForwarding(thisTriggerId, triggerElementRef, store, {
4645
4463
  payload,
4646
4464
  closeDelay,
4647
4465
  parent,
@@ -4656,7 +4474,7 @@ const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentPr
4656
4474
  const {
4657
4475
  getButtonProps,
4658
4476
  buttonRef
4659
- } = useBaseUiId.useButton({
4477
+ } = clamp.useButton({
4660
4478
  disabled,
4661
4479
  native: nativeButton
4662
4480
  });
@@ -4666,15 +4484,15 @@ const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentPr
4666
4484
  }
4667
4485
  }, [store, isOpenedByThisTrigger, parent.type]);
4668
4486
  const triggerRef = React__namespace.useRef(null);
4669
- const allowMouseUpTriggerTimeout = useValueChanged.useTimeout();
4670
- const handleDocumentMouseUp = useValueChanged.useStableCallback(mouseEvent => {
4487
+ const allowMouseUpTriggerTimeout = clamp.useTimeout();
4488
+ const handleDocumentMouseUp = clamp.useStableCallback(mouseEvent => {
4671
4489
  if (!triggerRef.current) {
4672
4490
  return;
4673
4491
  }
4674
4492
  allowMouseUpTriggerTimeout.clear();
4675
4493
  store.context.allowMouseUpTriggerRef.current = false;
4676
4494
  const mouseUpTarget = mouseEvent.target;
4677
- if (DrawerRoot.contains(triggerRef.current, mouseUpTarget) || DrawerRoot.contains(store.select('positionerElement'), mouseUpTarget) || mouseUpTarget === triggerRef.current) {
4495
+ if (ScrollAreaViewport.contains(triggerRef.current, mouseUpTarget) || ScrollAreaViewport.contains(store.select('positionerElement'), mouseUpTarget) || mouseUpTarget === triggerRef.current) {
4678
4496
  return;
4679
4497
  }
4680
4498
  if (mouseUpTarget != null && findRootOwnerId(mouseUpTarget) === store.select('rootId')) {
@@ -4686,12 +4504,12 @@ const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentPr
4686
4504
  }
4687
4505
  floatingTreeRoot.events.emit('close', {
4688
4506
  domEvent: mouseEvent,
4689
- reason: useValueChanged.cancelOpen
4507
+ reason: clamp.cancelOpen
4690
4508
  });
4691
4509
  });
4692
4510
  React__namespace.useEffect(() => {
4693
- if (isOpenedByThisTrigger && store.select('lastOpenChangeReason') === useValueChanged.triggerHover) {
4694
- const doc = useValueChanged.ownerDocument(triggerRef.current);
4511
+ if (isOpenedByThisTrigger && store.select('lastOpenChangeReason') === clamp.triggerHover) {
4512
+ const doc = clamp.ownerDocument(triggerRef.current);
4695
4513
  doc.addEventListener('mouseup', handleDocumentMouseUp, {
4696
4514
  once: true
4697
4515
  });
@@ -4719,7 +4537,7 @@ const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentPr
4719
4537
  // `lastOpenChangeReason` doesn't need to be reactive here, as we need to run this
4720
4538
  // only when `isOpenedByThisTrigger` changes.
4721
4539
  const stickIfOpen = useStickIfOpen(isOpenedByThisTrigger, store.select('lastOpenChangeReason'));
4722
- const click = useClick(floatingRootContext, {
4540
+ const click = ScrollAreaViewport.useClick(floatingRootContext, {
4723
4541
  enabled: !disabled && parent.type !== 'context-menu',
4724
4542
  event: isOpenedByThisTrigger && isInMenubar ? 'click' : 'mousedown',
4725
4543
  toggle: true,
@@ -4734,7 +4552,7 @@ const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentPr
4734
4552
  enabled: isInMenubar,
4735
4553
  mouseDownAction: 'open'
4736
4554
  });
4737
- const localInteractionProps = DrawerRoot.useInteractions([click, focus]);
4555
+ const localInteractionProps = ScrollAreaViewport.useInteractions([click, focus]);
4738
4556
  const state = {
4739
4557
  disabled,
4740
4558
  open: isOpenedByThisTrigger
@@ -4753,7 +4571,7 @@ const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentPr
4753
4571
  allowMouseUpTriggerTimeout.start(200, () => {
4754
4572
  store.context.allowMouseUpTriggerRef.current = true;
4755
4573
  });
4756
- const doc = useValueChanged.ownerDocument(event.currentTarget);
4574
+ const doc = clamp.ownerDocument(event.currentTarget);
4757
4575
  doc.addEventListener('mouseup', handleDocumentMouseUp, {
4758
4576
  once: true
4759
4577
  });
@@ -4762,25 +4580,25 @@ const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentPr
4762
4580
  role: 'menuitem'
4763
4581
  } : {}, mixedToggleHandlers, elementProps, getButtonProps];
4764
4582
  const preFocusGuardRef = React__namespace.useRef(null);
4765
- const handlePreFocusGuardFocus = useValueChanged.useStableCallback(event => {
4583
+ const handlePreFocusGuardFocus = clamp.useStableCallback(event => {
4766
4584
  ReactDOM__namespace.flushSync(() => {
4767
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.focusOut, event.nativeEvent, event.currentTarget));
4585
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.focusOut, event.nativeEvent, event.currentTarget));
4768
4586
  });
4769
- const previousTabbable = DrawerRoot.getTabbableBeforeElement(preFocusGuardRef.current);
4587
+ const previousTabbable = ScrollAreaViewport.getTabbableBeforeElement(preFocusGuardRef.current);
4770
4588
  previousTabbable?.focus();
4771
4589
  });
4772
- const handleFocusTargetFocus = useValueChanged.useStableCallback(event => {
4590
+ const handleFocusTargetFocus = clamp.useStableCallback(event => {
4773
4591
  const currentPositionerElement = store.select('positionerElement');
4774
- if (currentPositionerElement && DrawerRoot.isOutsideEvent(event, currentPositionerElement)) {
4592
+ if (currentPositionerElement && ScrollAreaViewport.isOutsideEvent(event, currentPositionerElement)) {
4775
4593
  store.context.beforeContentFocusGuardRef.current?.focus();
4776
4594
  } else {
4777
4595
  ReactDOM__namespace.flushSync(() => {
4778
- store.setOpen(false, useValueChanged.createChangeEventDetails(useValueChanged.focusOut, event.nativeEvent, event.currentTarget));
4596
+ store.setOpen(false, clamp.createChangeEventDetails(clamp.focusOut, event.nativeEvent, event.currentTarget));
4779
4597
  });
4780
- let nextTabbable = DrawerRoot.getTabbableAfterElement(store.context.triggerFocusTargetRef.current || triggerElementRef.current);
4781
- while (nextTabbable !== null && DrawerRoot.contains(currentPositionerElement, nextTabbable)) {
4598
+ let nextTabbable = ScrollAreaViewport.getTabbableAfterElement(store.context.triggerFocusTargetRef.current || triggerElementRef.current);
4599
+ while (nextTabbable !== null && ScrollAreaViewport.contains(currentPositionerElement, nextTabbable)) {
4782
4600
  const prevTabbable = nextTabbable;
4783
- nextTabbable = DrawerRoot.getNextTabbable(nextTabbable);
4601
+ nextTabbable = ScrollAreaViewport.getNextTabbable(nextTabbable);
4784
4602
  if (nextTabbable === prevTabbable) {
4785
4603
  break;
4786
4604
  }
@@ -4790,7 +4608,7 @@ const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentPr
4790
4608
  });
4791
4609
  const element = useRenderElement.useRenderElement('button', componentProps, {
4792
4610
  enabled: !isInMenubar,
4793
- stateAttributesMapping: DrawerRoot.pressableTriggerOpenStateMapping,
4611
+ stateAttributesMapping: ScrollAreaViewport.pressableTriggerOpenStateMapping,
4794
4612
  state,
4795
4613
  ref,
4796
4614
  props
@@ -4803,7 +4621,7 @@ const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentPr
4803
4621
  state: state,
4804
4622
  refs: ref,
4805
4623
  props: props,
4806
- stateAttributesMapping: DrawerRoot.pressableTriggerOpenStateMapping
4624
+ stateAttributesMapping: ScrollAreaViewport.pressableTriggerOpenStateMapping
4807
4625
  });
4808
4626
  }
4809
4627
 
@@ -4812,12 +4630,12 @@ const MenuTrigger = DrawerRoot.fastComponentRef(function MenuTrigger(componentPr
4812
4630
 
4813
4631
  if (isOpenedByThisTrigger) {
4814
4632
  return /*#__PURE__*/jsxRuntime.jsxs(React__namespace.Fragment, {
4815
- children: [/*#__PURE__*/jsxRuntime.jsx(DrawerRoot.FocusGuard, {
4633
+ children: [/*#__PURE__*/jsxRuntime.jsx(ScrollAreaViewport.FocusGuard, {
4816
4634
  ref: preFocusGuardRef,
4817
4635
  onFocus: handlePreFocusGuardFocus
4818
4636
  }, `${thisTriggerId}-pre-focus-guard`), /*#__PURE__*/jsxRuntime.jsx(React__namespace.Fragment, {
4819
4637
  children: element
4820
- }, thisTriggerId), /*#__PURE__*/jsxRuntime.jsx(DrawerRoot.FocusGuard, {
4638
+ }, thisTriggerId), /*#__PURE__*/jsxRuntime.jsx(ScrollAreaViewport.FocusGuard, {
4821
4639
  ref: store.context.triggerFocusTargetRef,
4822
4640
  onFocus: handleFocusTargetFocus
4823
4641
  }, `${thisTriggerId}-post-focus-guard`)]
@@ -4832,14 +4650,14 @@ if (process.env.NODE_ENV !== "production") MenuTrigger.displayName = "MenuTrigge
4832
4650
  * Determines whether to ignore clicks after a hover-open.
4833
4651
  */
4834
4652
  function useStickIfOpen(open, openReason) {
4835
- const stickIfOpenTimeout = useValueChanged.useTimeout();
4653
+ const stickIfOpenTimeout = clamp.useTimeout();
4836
4654
  const [stickIfOpen, setStickIfOpen] = React__namespace.useState(false);
4837
- useValueChanged.useIsoLayoutEffect(() => {
4655
+ clamp.useIsoLayoutEffect(() => {
4838
4656
  if (open && openReason === 'trigger-hover') {
4839
4657
  // Only allow "patient" clicks to close the menu if it's open.
4840
4658
  // If they clicked within 500ms of the menu opening, keep it open.
4841
4659
  setStickIfOpen(true);
4842
- stickIfOpenTimeout.start(DrawerRoot.PATIENT_CLICK_THRESHOLD, () => {
4660
+ stickIfOpenTimeout.start(ScrollAreaViewport.PATIENT_CLICK_THRESHOLD, () => {
4843
4661
  setStickIfOpen(false);
4844
4662
  });
4845
4663
  } else if (!open) {
@@ -4901,11 +4719,11 @@ const MenuSubmenuTrigger = /*#__PURE__*/React__namespace.forwardRef(function Sub
4901
4719
  const {
4902
4720
  store
4903
4721
  } = useMenuRootContext();
4904
- const thisTriggerId = useBaseUiId.useBaseUiId(idProp);
4722
+ const thisTriggerId = clamp.useBaseUiId(idProp);
4905
4723
  const open = store.useState('open');
4906
4724
  const floatingRootContext = store.useState('floatingRootContext');
4907
4725
  const floatingTreeRoot = store.useState('floatingTreeRoot');
4908
- const baseRegisterTrigger = DrawerRoot.useTriggerRegistration(thisTriggerId, store);
4726
+ const baseRegisterTrigger = ScrollAreaViewport.useTriggerRegistration(thisTriggerId, store);
4909
4727
  const registerTrigger = React__namespace.useCallback(element => {
4910
4728
  const cleanup = baseRegisterTrigger(element);
4911
4729
  if (element !== null && store.select('open') && store.select('activeTriggerId') == null) {
@@ -4969,14 +4787,14 @@ const MenuSubmenuTrigger = /*#__PURE__*/React__namespace.forwardRef(function Sub
4969
4787
  triggerElementRef,
4970
4788
  externalTree: floatingTreeRoot
4971
4789
  });
4972
- const click = useClick(floatingRootContext, {
4790
+ const click = ScrollAreaViewport.useClick(floatingRootContext, {
4973
4791
  enabled: !disabled,
4974
4792
  event: 'mousedown',
4975
4793
  toggle: !openOnHover,
4976
4794
  ignoreMouse: openOnHover,
4977
4795
  stickIfOpen: false
4978
4796
  });
4979
- const localInteractionProps = DrawerRoot.useInteractions([click]);
4797
+ const localInteractionProps = ScrollAreaViewport.useInteractions([click]);
4980
4798
  const rootTriggerProps = store.useState('triggerProps', true);
4981
4799
  delete rootTriggerProps.id;
4982
4800
  const state = {
@@ -4986,7 +4804,7 @@ const MenuSubmenuTrigger = /*#__PURE__*/React__namespace.forwardRef(function Sub
4986
4804
  };
4987
4805
  const element = useRenderElement.useRenderElement('div', componentProps, {
4988
4806
  state,
4989
- stateAttributesMapping: DrawerRoot.triggerOpenStateMapping,
4807
+ stateAttributesMapping: ScrollAreaViewport.triggerOpenStateMapping,
4990
4808
  props: [localInteractionProps.getReferenceProps(), hoverProps, rootTriggerProps, itemProps, {
4991
4809
  tabIndex: open || highlighted ? 0 : -1,
4992
4810
  onBlur() {
@@ -5004,7 +4822,6 @@ if (process.env.NODE_ENV !== "production") MenuSubmenuTrigger.displayName = "Men
5004
4822
  exports.CompositeList = CompositeList;
5005
4823
  exports.DrawerClose = DrawerClose;
5006
4824
  exports.DrawerTitle = DrawerTitle;
5007
- exports.DrawerTrigger = DrawerTrigger;
5008
4825
  exports.IndexGuessBehavior = IndexGuessBehavior;
5009
4826
  exports.MenuGroup = MenuGroup;
5010
4827
  exports.MenuGroupLabel = MenuGroupLabel;
@@ -5026,10 +4843,8 @@ exports.getDisabledMountTransitionStyles = getDisabledMountTransitionStyles;
5026
4843
  exports.getPseudoElementBounds = getPseudoElementBounds;
5027
4844
  exports.itemMapping = itemMapping;
5028
4845
  exports.useAnchorPositioning = useAnchorPositioning;
5029
- exports.useClick = useClick;
5030
4846
  exports.useCompositeListItem = useCompositeListItem;
5031
4847
  exports.useContextMenuRootContext = useContextMenuRootContext;
5032
- exports.useDirection = useDirection;
5033
4848
  exports.useFloatingRootContext = useFloatingRootContext;
5034
4849
  exports.useListNavigation = useListNavigation;
5035
4850
  exports.useMenuItem = useMenuItem;