@jobber/components 9.6.1 → 9.6.2

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 (141) hide show
  1. package/dist/Autocomplete/index.cjs +2 -0
  2. package/dist/Autocomplete/index.mjs +2 -0
  3. package/dist/Autocomplete-cjs.js +5 -4
  4. package/dist/Autocomplete-es.js +2 -1
  5. package/dist/Card/index.cjs +2 -1
  6. package/dist/Card/index.mjs +2 -1
  7. package/dist/Chip/index.cjs +2 -0
  8. package/dist/Chip/index.mjs +2 -0
  9. package/dist/Chips/InternalChipDismissible/hooks/index.cjs +2 -0
  10. package/dist/Chips/InternalChipDismissible/hooks/index.mjs +2 -0
  11. package/dist/Chips/InternalChipDismissible/index.cjs +2 -0
  12. package/dist/Chips/InternalChipDismissible/index.mjs +2 -0
  13. package/dist/Chips/index.cjs +2 -0
  14. package/dist/Chips/index.mjs +2 -0
  15. package/dist/Combobox/index.cjs +4 -2
  16. package/dist/Combobox/index.mjs +4 -2
  17. package/dist/{ComboboxSeparator-cjs.js → ComboboxChipRemove-cjs.js} +455 -501
  18. package/dist/{ComboboxSeparator-es.js → ComboboxChipRemove-es.js} +456 -500
  19. package/dist/ComboboxPrimitive-cjs.js +30 -29
  20. package/dist/ComboboxPrimitive-es.js +3 -2
  21. package/dist/ConfirmationModal/index.cjs +2 -0
  22. package/dist/ConfirmationModal/index.mjs +2 -0
  23. package/dist/DataDump/index.cjs +2 -1
  24. package/dist/DataDump/index.mjs +2 -1
  25. package/dist/DataList/components/DataListActions/index.cjs +2 -0
  26. package/dist/DataList/components/DataListActions/index.mjs +2 -0
  27. package/dist/DataList/components/DataListBulkActions/index.cjs +2 -0
  28. package/dist/DataList/components/DataListBulkActions/index.mjs +2 -0
  29. package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +2 -0
  30. package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +2 -0
  31. package/dist/DataList/components/DataListFilters/index.cjs +2 -0
  32. package/dist/DataList/components/DataListFilters/index.mjs +2 -0
  33. package/dist/DataList/components/DataListHeader/index.cjs +2 -0
  34. package/dist/DataList/components/DataListHeader/index.mjs +2 -0
  35. package/dist/DataList/components/DataListItem/index.cjs +2 -0
  36. package/dist/DataList/components/DataListItem/index.mjs +2 -0
  37. package/dist/DataList/components/DataListItemActions/index.cjs +2 -0
  38. package/dist/DataList/components/DataListItemActions/index.mjs +2 -0
  39. package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +2 -0
  40. package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +2 -0
  41. package/dist/DataList/components/DataListItems/index.cjs +2 -0
  42. package/dist/DataList/components/DataListItems/index.mjs +2 -0
  43. package/dist/DataList/components/DataListLayout/index.cjs +2 -0
  44. package/dist/DataList/components/DataListLayout/index.mjs +2 -0
  45. package/dist/DataList/components/DataListLayoutActions/index.cjs +2 -0
  46. package/dist/DataList/components/DataListLayoutActions/index.mjs +2 -0
  47. package/dist/DataList/index.cjs +2 -0
  48. package/dist/DataList/index.mjs +2 -0
  49. package/dist/DatePicker/index.cjs +2 -0
  50. package/dist/DatePicker/index.mjs +2 -0
  51. package/dist/DatePicker-cjs.js +5 -4
  52. package/dist/DatePicker-es.js +2 -1
  53. package/dist/Dialog/index.cjs +2 -1
  54. package/dist/Dialog/index.mjs +2 -1
  55. package/dist/DrawerDescription-cjs.js +99 -268
  56. package/dist/DrawerDescription-es.js +103 -270
  57. package/dist/DrawerTitle-cjs.js +6 -2
  58. package/dist/DrawerTitle-es.js +7 -3
  59. package/dist/FieldDescription-cjs.js +181 -184
  60. package/dist/FieldDescription-es.js +184 -187
  61. package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +2 -0
  62. package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +2 -0
  63. package/dist/FilterPicker/components/FilterPickerContent/index.cjs +2 -0
  64. package/dist/FilterPicker/components/FilterPickerContent/index.mjs +2 -0
  65. package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +2 -0
  66. package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +2 -0
  67. package/dist/FilterPicker/index.cjs +2 -0
  68. package/dist/FilterPicker/index.mjs +2 -0
  69. package/dist/FilterPickerContent-cjs.js +5 -4
  70. package/dist/FilterPickerContent-es.js +2 -1
  71. package/dist/FormatFile/index.cjs +2 -0
  72. package/dist/FormatFile/index.mjs +2 -0
  73. package/dist/Gallery/index.cjs +2 -0
  74. package/dist/Gallery/index.mjs +2 -0
  75. package/dist/InputDate/index.cjs +2 -0
  76. package/dist/InputDate/index.mjs +2 -0
  77. package/dist/InputNumber/index.cjs +2 -1
  78. package/dist/InputNumber/index.mjs +2 -1
  79. package/dist/LightBox/index.cjs +2 -0
  80. package/dist/LightBox/index.mjs +2 -0
  81. package/dist/Menu/index.cjs +2 -1
  82. package/dist/Menu/index.mjs +2 -1
  83. package/dist/Menu-cjs.js +5 -4
  84. package/dist/Menu-es.js +2 -1
  85. package/dist/MenuSubmenuTrigger-cjs.js +164 -206
  86. package/dist/MenuSubmenuTrigger-es.js +152 -194
  87. package/dist/Modal/index.cjs +2 -0
  88. package/dist/Modal/index.mjs +3 -1
  89. package/dist/NumberFieldInput-cjs.js +308 -187
  90. package/dist/NumberFieldInput-es.js +308 -187
  91. package/dist/Page/index.cjs +2 -1
  92. package/dist/Page/index.mjs +2 -1
  93. package/dist/Popover/index.cjs +2 -0
  94. package/dist/Popover/index.mjs +2 -0
  95. package/dist/Popover-cjs.js +8 -7
  96. package/dist/Popover-es.js +2 -1
  97. package/dist/ScrollAreaViewport-cjs.js +1093 -747
  98. package/dist/ScrollAreaViewport-es.js +1081 -734
  99. package/dist/Select/index.cjs +2 -1
  100. package/dist/Select/index.mjs +2 -1
  101. package/dist/SelectGroupLabel-cjs.js +306 -207
  102. package/dist/SelectGroupLabel-es.js +302 -203
  103. package/dist/Tooltip/index.cjs +2 -0
  104. package/dist/Tooltip/index.mjs +2 -0
  105. package/dist/Tooltip-cjs.js +7 -6
  106. package/dist/Tooltip-es.js +2 -1
  107. package/dist/dialogReturnFocus-cjs.js +1 -1
  108. package/dist/dialogReturnFocus-es.js +2 -2
  109. package/dist/floating-ui.react-cjs.js +192 -2564
  110. package/dist/floating-ui.react-dom-cjs.js +2103 -0
  111. package/dist/floating-ui.react-dom-es.js +2072 -0
  112. package/dist/floating-ui.react-es.js +156 -2519
  113. package/dist/floating-ui.utils-cjs.js +342 -0
  114. package/dist/floating-ui.utils-es.js +300 -0
  115. package/dist/index.cjs +4 -3
  116. package/dist/index.mjs +4 -3
  117. package/dist/primitives/BottomSheet/index.cjs +1 -1
  118. package/dist/primitives/BottomSheet/index.mjs +1 -1
  119. package/dist/primitives/ComboboxPrimitive/index.cjs +4 -2
  120. package/dist/primitives/ComboboxPrimitive/index.mjs +4 -2
  121. package/dist/primitives/SelectPrimitive/index.cjs +2 -0
  122. package/dist/primitives/SelectPrimitive/index.mjs +2 -0
  123. package/dist/primitives/index.cjs +3 -2
  124. package/dist/primitives/index.mjs +3 -2
  125. package/dist/scrollEdges-cjs.js +11 -1
  126. package/dist/scrollEdges-es.js +11 -1
  127. package/dist/unstyledPrimitives/index.cjs +478 -720
  128. package/dist/unstyledPrimitives/index.mjs +421 -663
  129. package/dist/useCompositeListItem-cjs.js +361 -2108
  130. package/dist/useCompositeListItem-es.js +331 -2076
  131. package/dist/useLabel-cjs.js +3 -2
  132. package/dist/useLabel-es.js +3 -2
  133. package/dist/useRenderElement-cjs.js +7 -9
  134. package/dist/useRenderElement-es.js +7 -9
  135. package/dist/useScrollLock-cjs.js +344 -819
  136. package/dist/useScrollLock-es.js +296 -732
  137. package/dist/useScrollToActive-cjs.js +5 -4
  138. package/dist/useScrollToActive-es.js +2 -1
  139. package/package.json +3 -3
  140. package/dist/scrollable-cjs.js +0 -58
  141. package/dist/scrollable-es.js +0 -54
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var React = require('react');
4
+ var floatingUi_utils = require('./floating-ui.utils-cjs.js');
4
5
  var useRenderElement = require('./useRenderElement-cjs.js');
5
6
  var jsxRuntime = require('react/jsx-runtime');
6
7
  var ReactDOM = require('react-dom');
@@ -103,6 +104,14 @@ function serializeToDevModeString(input) {
103
104
  const noop = () => {};
104
105
  const useIsoLayoutEffect = typeof document !== 'undefined' ? React__namespace.useLayoutEffect : noop;
105
106
 
107
+ function useOnFirstRender(fn) {
108
+ const ref = React__namespace.useRef(true);
109
+ if (ref.current) {
110
+ ref.current = false;
111
+ fn();
112
+ }
113
+ }
114
+
106
115
  /**
107
116
  * A clone of the React namespace for reading APIs that may be missing in older
108
117
  * supported React versions. Bundlers can rewrite direct `React.someNewApi`
@@ -201,6 +210,87 @@ const visuallyHiddenInput = {
201
210
  position: 'absolute'
202
211
  };
203
212
 
213
+ /**
214
+ * The NoOptionalParams type is a utility type that checks if a function has optional or default parameters.
215
+ * If the function has optional or default parameters, it returns a string literal type with an error message.
216
+ * Otherwise, it returns the original function type.
217
+ *
218
+ * This is used to enforce that the combiner function passed to createSelector does not have optional or default parameters,
219
+ * as memoization relies on the Function.length property, which does not account for optional or default parameters.
220
+ */
221
+
222
+ /**
223
+ * Creates a selector function that can be used to derive values from the store's state.
224
+ *
225
+ * The combiner function can have up to three additional parameters, but it **cannot have optional or default parameters**.
226
+ *
227
+ * This function accepts up to six functions and combines them into a single selector function.
228
+ * The resulting selector will take the state from the combined selectors and any additional parameters required by the combiner.
229
+ *
230
+ * The return type of the resulting selector is determined by the return type of the combiner function.
231
+ *
232
+ * @example
233
+ * const selector = createSelector(
234
+ * (state) => state.disabled
235
+ * );
236
+ *
237
+ * @example
238
+ * const selector = createSelector(
239
+ * (state) => state.disabled,
240
+ * (state) => state.open,
241
+ * (disabled, open) => ({ disabled, open })
242
+ * );
243
+ */
244
+ /* eslint-disable id-denylist */
245
+ const createSelector = (a, b, c, d, e, f, ...other) => {
246
+ if (other.length > 0) {
247
+ throw new Error(process.env.NODE_ENV !== "production" ? 'Unsupported number of selectors' : useRenderElement.formatErrorMessage(1));
248
+ }
249
+ let selector;
250
+ if (a && b && c && d && e && f) {
251
+ selector = (state, a1, a2, a3) => {
252
+ const va = a(state, a1, a2, a3);
253
+ const vb = b(state, a1, a2, a3);
254
+ const vc = c(state, a1, a2, a3);
255
+ const vd = d(state, a1, a2, a3);
256
+ const ve = e(state, a1, a2, a3);
257
+ return f(va, vb, vc, vd, ve, a1, a2, a3);
258
+ };
259
+ } else if (a && b && c && d && e) {
260
+ selector = (state, a1, a2, a3) => {
261
+ const va = a(state, a1, a2, a3);
262
+ const vb = b(state, a1, a2, a3);
263
+ const vc = c(state, a1, a2, a3);
264
+ const vd = d(state, a1, a2, a3);
265
+ return e(va, vb, vc, vd, a1, a2, a3);
266
+ };
267
+ } else if (a && b && c && d) {
268
+ selector = (state, a1, a2, a3) => {
269
+ const va = a(state, a1, a2, a3);
270
+ const vb = b(state, a1, a2, a3);
271
+ const vc = c(state, a1, a2, a3);
272
+ return d(va, vb, vc, a1, a2, a3);
273
+ };
274
+ } else if (a && b && c) {
275
+ selector = (state, a1, a2, a3) => {
276
+ const va = a(state, a1, a2, a3);
277
+ const vb = b(state, a1, a2, a3);
278
+ return c(va, vb, a1, a2, a3);
279
+ };
280
+ } else if (a && b) {
281
+ selector = (state, a1, a2, a3) => {
282
+ const va = a(state, a1, a2, a3);
283
+ return b(va, a1, a2, a3);
284
+ };
285
+ } else if (a) {
286
+ selector = a;
287
+ } else {
288
+ throw /* minify-error-disabled */new Error('Missing arguments');
289
+ }
290
+ return selector;
291
+ };
292
+ /* eslint-enable id-denylist */
293
+
204
294
  var shim = {exports: {}};
205
295
 
206
296
  var useSyncExternalStoreShim_production = {};
@@ -608,41 +698,6 @@ function getInstance() {
608
698
  function register(hook) {
609
699
  hooks.push(hook);
610
700
  }
611
-
612
- /**
613
- * Wraps a component function to enable performance optimizations for internal hooks.
614
- *
615
- * **Performance Optimization:**
616
- * Components wrapped with `fastComponent` have access to a shared "instance" context that enables
617
- * specialized hook implementations to batch operations and reduce overhead. The wrapper creates a
618
- * stable instance object that persists across renders, sets it as the current context, calls
619
- * registered hooks before and after rendering, then clears the context. The primary benefit is
620
- * with `useStore`, where multiple store subscriptions within the same component are collapsed into
621
- * a single `useSyncExternalStore` subscription per store, significantly reducing re-render overhead.
622
- * This optimization is only active on React 19+; on earlier versions `useStore` falls back to a
623
- * separate subscription per call.
624
- *
625
- * **Requirements:**
626
- * - The component function should follow standard React component patterns
627
- * - `useStore` calls must keep a stable order and count across renders, as batched hooks are
628
- * matched by call index
629
- * - Do not rely on the instance context outside of specialized hooks
630
- *
631
- * @param fn - The component function to wrap
632
- * @returns A wrapped component with the same signature as the input function
633
- *
634
- * @example
635
- * ```tsx
636
- * // Wrapping a component to enable optimized useStore batching
637
- * export const TooltipRoot = fastComponent(function TooltipRoot(props) {
638
- * // These useStore calls share a single subscription
639
- * const open = useStore(store, (state) => state.open);
640
- * const disabled = useStore(store, (state) => state.disabled);
641
- * const value = useStore(store, (state) => state.value);
642
- * // ...
643
- * });
644
- * ```
645
- */
646
701
  function fastComponent(fn) {
647
702
  const FastComponent = (props, forwardedRef) => {
648
703
  const instance = useRenderElement.useRefWithInit(createInstance).current;
@@ -665,31 +720,6 @@ function fastComponent(fn) {
665
720
  FastComponent.displayName = fn.displayName || fn.name;
666
721
  return FastComponent;
667
722
  }
668
-
669
- /**
670
- * Wraps a component function with ref forwarding to enable performance optimizations for internal hooks.
671
- *
672
- * This is a convenience wrapper that combines `fastComponent` with `React.forwardRef`, enabling
673
- * both performance optimizations and proper ref forwarding. See `fastComponent` for details on
674
- * the performance benefits.
675
- *
676
- * @param fn - The component function that accepts props and a forwarded ref
677
- * @returns A wrapped component with ref forwarding enabled
678
- *
679
- * @example
680
- * ```tsx
681
- * // Wrapping a component with ref forwarding and optimized hooks
682
- * export const TooltipTrigger = fastComponentRef(function TooltipTrigger(
683
- * props,
684
- * forwardedRef
685
- * ) {
686
- * const store = useContext(TooltipContext);
687
- * const open = useStore(store, (state) => state.open);
688
- * // ... component logic with ref
689
- * return <button ref={forwardedRef} {...props} />;
690
- * });
691
- * ```
692
- */
693
723
  function fastComponentRef(fn) {
694
724
  return /*#__PURE__*/React__namespace.forwardRef(fastComponent(fn));
695
725
  }
@@ -1105,170 +1135,6 @@ class ReactStore extends Store {
1105
1135
  }
1106
1136
  }
1107
1137
 
1108
- function hasWindow() {
1109
- return typeof window !== 'undefined';
1110
- }
1111
- function getNodeName(node) {
1112
- if (isNode(node)) {
1113
- return (node.nodeName || '').toLowerCase();
1114
- }
1115
- // Mocked nodes in testing environments may not be instances of Node. By
1116
- // returning `#document` an infinite loop won't occur.
1117
- // https://github.com/floating-ui/floating-ui/issues/2317
1118
- return '#document';
1119
- }
1120
- function getWindow(node) {
1121
- var _node$ownerDocument;
1122
- return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
1123
- }
1124
- function getDocumentElement(node) {
1125
- var _ref;
1126
- return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;
1127
- }
1128
- function isNode(value) {
1129
- if (!hasWindow()) {
1130
- return false;
1131
- }
1132
- return value instanceof Node || value instanceof getWindow(value).Node;
1133
- }
1134
- function isElement(value) {
1135
- if (!hasWindow()) {
1136
- return false;
1137
- }
1138
- return value instanceof Element || value instanceof getWindow(value).Element;
1139
- }
1140
- function isHTMLElement(value) {
1141
- if (!hasWindow()) {
1142
- return false;
1143
- }
1144
- return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;
1145
- }
1146
- function isShadowRoot(value) {
1147
- if (!hasWindow() || typeof ShadowRoot === 'undefined') {
1148
- return false;
1149
- }
1150
- return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;
1151
- }
1152
- function isOverflowElement(element) {
1153
- const {
1154
- overflow,
1155
- overflowX,
1156
- overflowY,
1157
- display
1158
- } = getComputedStyle(element);
1159
- return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && display !== 'inline' && display !== 'contents';
1160
- }
1161
- function isTableElement(element) {
1162
- return /^(table|td|th)$/.test(getNodeName(element));
1163
- }
1164
- function isTopLayer(element) {
1165
- try {
1166
- if (element.matches(':popover-open')) {
1167
- return true;
1168
- }
1169
- } catch (_e) {
1170
- // no-op
1171
- }
1172
- try {
1173
- return element.matches(':modal');
1174
- } catch (_e) {
1175
- return false;
1176
- }
1177
- }
1178
- const willChangeRe = /transform|translate|scale|rotate|perspective|filter/;
1179
- const containRe = /paint|layout|strict|content/;
1180
- const isNotNone = value => !!value && value !== 'none';
1181
- let isWebKitValue;
1182
- function isContainingBlock(elementOrCss) {
1183
- const css = isElement(elementOrCss) ? getComputedStyle(elementOrCss) : elementOrCss;
1184
-
1185
- // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
1186
- // https://drafts.csswg.org/css-transforms-2/#individual-transforms
1187
- return isNotNone(css.transform) || isNotNone(css.translate) || isNotNone(css.scale) || isNotNone(css.rotate) || isNotNone(css.perspective) || !isWebKit() && (isNotNone(css.backdropFilter) || isNotNone(css.filter)) || willChangeRe.test(css.willChange || '') || containRe.test(css.contain || '');
1188
- }
1189
- function getContainingBlock(element) {
1190
- let currentNode = getParentNode(element);
1191
- while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
1192
- if (isContainingBlock(currentNode)) {
1193
- return currentNode;
1194
- } else if (isTopLayer(currentNode)) {
1195
- return null;
1196
- }
1197
- currentNode = getParentNode(currentNode);
1198
- }
1199
- return null;
1200
- }
1201
- function isWebKit() {
1202
- if (isWebKitValue == null) {
1203
- isWebKitValue = typeof CSS !== 'undefined' && CSS.supports && CSS.supports('-webkit-backdrop-filter', 'none');
1204
- }
1205
- return isWebKitValue;
1206
- }
1207
- function isLastTraversableNode(node) {
1208
- return /^(html|body|#document)$/.test(getNodeName(node));
1209
- }
1210
- function getComputedStyle(element) {
1211
- return getWindow(element).getComputedStyle(element);
1212
- }
1213
- function getNodeScroll(element) {
1214
- if (isElement(element)) {
1215
- return {
1216
- scrollLeft: element.scrollLeft,
1217
- scrollTop: element.scrollTop
1218
- };
1219
- }
1220
- return {
1221
- scrollLeft: element.scrollX,
1222
- scrollTop: element.scrollY
1223
- };
1224
- }
1225
- function getParentNode(node) {
1226
- if (getNodeName(node) === 'html') {
1227
- return node;
1228
- }
1229
- const result =
1230
- // Step into the shadow DOM of the parent of a slotted node.
1231
- node.assignedSlot ||
1232
- // DOM Element detected.
1233
- node.parentNode ||
1234
- // ShadowRoot detected.
1235
- isShadowRoot(node) && node.host ||
1236
- // Fallback.
1237
- getDocumentElement(node);
1238
- return isShadowRoot(result) ? result.host : result;
1239
- }
1240
- function getNearestOverflowAncestor(node) {
1241
- const parentNode = getParentNode(node);
1242
- if (isLastTraversableNode(parentNode)) {
1243
- return (node.ownerDocument || node).body;
1244
- }
1245
- if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
1246
- return parentNode;
1247
- }
1248
- return getNearestOverflowAncestor(parentNode);
1249
- }
1250
- function getOverflowAncestors(node, list, traverseIframes) {
1251
- var _node$ownerDocument2;
1252
- if (list === void 0) {
1253
- list = [];
1254
- }
1255
- if (traverseIframes === void 0) {
1256
- traverseIframes = true;
1257
- }
1258
- const scrollableAncestor = getNearestOverflowAncestor(node);
1259
- const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
1260
- const win = getWindow(scrollableAncestor);
1261
- if (isBody) {
1262
- const frameElement = getFrameElement(win);
1263
- return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);
1264
- } else {
1265
- return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
1266
- }
1267
- }
1268
- function getFrameElement(win) {
1269
- return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;
1270
- }
1271
-
1272
1138
  /**
1273
1139
  * Combines multiple cleanup functions into a single cleanup function.
1274
1140
  */
@@ -1298,13 +1164,15 @@ function addEventListener(target, type, listener, options) {
1298
1164
  };
1299
1165
  }
1300
1166
 
1167
+ const EMPTY$2 = [];
1168
+
1301
1169
  /**
1302
1170
  * A React.useEffect equivalent that runs once, when the component is mounted.
1303
1171
  */
1304
1172
  function useOnMount(fn) {
1305
1173
  // TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler -- no need to put `fn` in the dependency array
1306
1174
  /* eslint-disable react-hooks/exhaustive-deps */
1307
- React__namespace.useEffect(fn, useRenderElement.EMPTY_ARRAY);
1175
+ React__namespace.useEffect(fn, EMPTY$2);
1308
1176
  /* eslint-enable react-hooks/exhaustive-deps */
1309
1177
  }
1310
1178
 
@@ -1368,7 +1236,7 @@ class Scheduler {
1368
1236
  this.callbacksCount -= 1;
1369
1237
  }
1370
1238
  }
1371
- let scheduler = new Scheduler();
1239
+ const scheduler = new Scheduler();
1372
1240
  class AnimationFrame {
1373
1241
  static create() {
1374
1242
  return new AnimationFrame();
@@ -1615,7 +1483,7 @@ function contains(parent, child) {
1615
1483
  }
1616
1484
 
1617
1485
  // Then fall back to traversing out of shadow roots when needed.
1618
- if (rootNode && isShadowRoot(rootNode)) {
1486
+ if (rootNode && floatingUi_utils.isShadowRoot(rootNode)) {
1619
1487
  let next = child;
1620
1488
  while (next) {
1621
1489
  if (parent === next) {
@@ -1637,7 +1505,7 @@ function getTarget(event) {
1637
1505
  }
1638
1506
 
1639
1507
  function isTargetInsideEnabledTrigger(target, triggerElements) {
1640
- if (!isElement(target)) {
1508
+ if (!floatingUi_utils.isElement(target)) {
1641
1509
  return false;
1642
1510
  }
1643
1511
  const targetElement = target;
@@ -1667,7 +1535,7 @@ function isRootElement(element) {
1667
1535
  return element.matches('html,body');
1668
1536
  }
1669
1537
  function isTypeableElement(element) {
1670
- return isHTMLElement(element) && element.matches(TYPEABLE_SELECTOR);
1538
+ return floatingUi_utils.isHTMLElement(element) && element.matches(TYPEABLE_SELECTOR);
1671
1539
  }
1672
1540
  function isInteractiveElement(element) {
1673
1541
  return element?.closest(`button,a[href],[role="button"],select,[tabindex]:not([tabindex="-1"]),${TYPEABLE_SELECTOR}`) != null;
@@ -1808,138 +1676,6 @@ const FocusGuard = /*#__PURE__*/React__namespace.forwardRef(function FocusGuard(
1808
1676
  });
1809
1677
  if (process.env.NODE_ENV !== "production") FocusGuard.displayName = "FocusGuard";
1810
1678
 
1811
- /**
1812
- * Custom positioning reference element.
1813
- * @see https://floating-ui.com/docs/virtual-elements
1814
- */
1815
-
1816
- const min = Math.min;
1817
- const max = Math.max;
1818
- const round = Math.round;
1819
- const floor = Math.floor;
1820
- const createCoords = v => ({
1821
- x: v,
1822
- y: v
1823
- });
1824
- const oppositeSideMap = {
1825
- left: 'right',
1826
- right: 'left',
1827
- bottom: 'top',
1828
- top: 'bottom'
1829
- };
1830
- function clamp(start, value, end) {
1831
- return max(start, min(value, end));
1832
- }
1833
- function evaluate(value, param) {
1834
- return typeof value === 'function' ? value(param) : value;
1835
- }
1836
- function getSide(placement) {
1837
- return placement.split('-')[0];
1838
- }
1839
- function getAlignment(placement) {
1840
- return placement.split('-')[1];
1841
- }
1842
- function getOppositeAxis(axis) {
1843
- return axis === 'x' ? 'y' : 'x';
1844
- }
1845
- function getAxisLength(axis) {
1846
- return axis === 'y' ? 'height' : 'width';
1847
- }
1848
- function getSideAxis(placement) {
1849
- const firstChar = placement[0];
1850
- return firstChar === 't' || firstChar === 'b' ? 'y' : 'x';
1851
- }
1852
- function getAlignmentAxis(placement) {
1853
- return getOppositeAxis(getSideAxis(placement));
1854
- }
1855
- function getAlignmentSides(placement, rects, rtl) {
1856
- if (rtl === void 0) {
1857
- rtl = false;
1858
- }
1859
- const alignment = getAlignment(placement);
1860
- const alignmentAxis = getAlignmentAxis(placement);
1861
- const length = getAxisLength(alignmentAxis);
1862
- let mainAlignmentSide = alignmentAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top';
1863
- if (rects.reference[length] > rects.floating[length]) {
1864
- mainAlignmentSide = getOppositePlacement(mainAlignmentSide);
1865
- }
1866
- return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];
1867
- }
1868
- function getExpandedPlacements(placement) {
1869
- const oppositePlacement = getOppositePlacement(placement);
1870
- return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];
1871
- }
1872
- function getOppositeAlignmentPlacement(placement) {
1873
- return placement.includes('start') ? placement.replace('start', 'end') : placement.replace('end', 'start');
1874
- }
1875
- const lrPlacement = ['left', 'right'];
1876
- const rlPlacement = ['right', 'left'];
1877
- const tbPlacement = ['top', 'bottom'];
1878
- const btPlacement = ['bottom', 'top'];
1879
- function getSideList(side, isStart, rtl) {
1880
- switch (side) {
1881
- case 'top':
1882
- case 'bottom':
1883
- if (rtl) return isStart ? rlPlacement : lrPlacement;
1884
- return isStart ? lrPlacement : rlPlacement;
1885
- case 'left':
1886
- case 'right':
1887
- return isStart ? tbPlacement : btPlacement;
1888
- default:
1889
- return [];
1890
- }
1891
- }
1892
- function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {
1893
- const alignment = getAlignment(placement);
1894
- let list = getSideList(getSide(placement), direction === 'start', rtl);
1895
- if (alignment) {
1896
- list = list.map(side => side + "-" + alignment);
1897
- if (flipAlignment) {
1898
- list = list.concat(list.map(getOppositeAlignmentPlacement));
1899
- }
1900
- }
1901
- return list;
1902
- }
1903
- function getOppositePlacement(placement) {
1904
- const side = getSide(placement);
1905
- return oppositeSideMap[side] + placement.slice(side.length);
1906
- }
1907
- function expandPaddingObject(padding) {
1908
- var _padding$top, _padding$right, _padding$bottom, _padding$left;
1909
- return {
1910
- top: (_padding$top = padding.top) != null ? _padding$top : 0,
1911
- right: (_padding$right = padding.right) != null ? _padding$right : 0,
1912
- bottom: (_padding$bottom = padding.bottom) != null ? _padding$bottom : 0,
1913
- left: (_padding$left = padding.left) != null ? _padding$left : 0
1914
- };
1915
- }
1916
- function getPaddingObject(padding) {
1917
- return typeof padding !== 'number' ? expandPaddingObject(padding) : {
1918
- top: padding,
1919
- right: padding,
1920
- bottom: padding,
1921
- left: padding
1922
- };
1923
- }
1924
- function rectToClientRect(rect) {
1925
- const {
1926
- x,
1927
- y,
1928
- width,
1929
- height
1930
- } = rect;
1931
- return {
1932
- width,
1933
- height,
1934
- top: y,
1935
- left: x,
1936
- right: x + width,
1937
- bottom: y + height,
1938
- x,
1939
- y
1940
- };
1941
- }
1942
-
1943
1679
  function isDifferentGridRow(index, cols, prevRow) {
1944
1680
  return Math.floor(index / cols) !== prevRow;
1945
1681
  }
@@ -2075,7 +1811,7 @@ function getGridNavigatedIndex(list, {
2075
1811
  const colInRow = prevIndex % verticalCols;
2076
1812
  const rowStep = direction === 'up' ? -verticalCols : verticalCols;
2077
1813
  const lastRowStart = maxIndex - maxIndex % verticalCols;
2078
- const rowCount = floor(maxIndex / verticalCols) + 1;
1814
+ const rowCount = floatingUi_utils.floor(maxIndex / verticalCols) + 1;
2079
1815
  for (let rowStart = prevIndex - colInRow + rowStep, i = 0; i < rowCount; i += 1, rowStart += rowStep) {
2080
1816
  if (rowStart < 0 || rowStart > maxIndex) {
2081
1817
  if (!loopFocus) {
@@ -2140,7 +1876,7 @@ function getGridNavigatedIndex(list, {
2140
1876
 
2141
1877
  // Remains on the same row/column.
2142
1878
  if (orientation === 'both') {
2143
- const prevRow = floor(prevIndex / cols);
1879
+ const prevRow = floatingUi_utils.floor(prevIndex / cols);
2144
1880
  if (event.key === (rtl ? ARROW_LEFT : ARROW_RIGHT)) {
2145
1881
  if (stop) {
2146
1882
  stopEvent(event);
@@ -2206,7 +1942,7 @@ function getGridNavigatedIndex(list, {
2206
1942
  nextIndex = prevIndex;
2207
1943
  }
2208
1944
  }
2209
- const lastRow = floor(maxIndex / cols) === prevRow;
1945
+ const lastRow = floatingUi_utils.floor(maxIndex / cols) === prevRow;
2210
1946
  if (isIndexOutOfListBounds(list, nextIndex)) {
2211
1947
  if (loopFocus && lastRow) {
2212
1948
  nextIndex = event.key === (rtl ? ARROW_RIGHT : ARROW_LEFT) ? maxIndex : findNonDisabledListIndex(list, {
@@ -2235,19 +1971,12 @@ function isListIndexDisabled(list, index, disabledIndices) {
2235
1971
  if (!isElementVisible(element)) {
2236
1972
  return true;
2237
1973
  }
2238
-
2239
- // A natively disabled element can never receive focus, so it must always be
2240
- // skipped, even when `disabledIndices` marks it as enabled. Only
2241
- // `aria-disabled` items can be focusable-while-disabled.
2242
- if (element.matches(':disabled')) {
2243
- return true;
2244
- }
2245
1974
  return !disabledIndices && (element.hasAttribute('disabled') || element.getAttribute('aria-disabled') === 'true');
2246
1975
  }
2247
1976
  function isHiddenByStyles(styles) {
2248
1977
  return styles.visibility === 'hidden' || styles.visibility === 'collapse';
2249
1978
  }
2250
- function isElementVisible(element, styles = element ? getComputedStyle(element) : null) {
1979
+ function isElementVisible(element, styles = element ? floatingUi_utils.getComputedStyle(element) : null) {
2251
1980
  if (!element || !element.isConnected || !styles || isHiddenByStyles(styles)) {
2252
1981
  return false;
2253
1982
  }
@@ -2267,11 +1996,11 @@ function getParentElement(element) {
2267
1996
  return element.parentElement;
2268
1997
  }
2269
1998
  const rootNode = element.getRootNode();
2270
- return isShadowRoot(rootNode) ? rootNode.host : null;
1999
+ return floatingUi_utils.isShadowRoot(rootNode) ? rootNode.host : null;
2271
2000
  }
2272
2001
  function getDetailsSummary(details) {
2273
2002
  for (const child of Array.from(details.children)) {
2274
- if (getNodeName(child) === 'summary') {
2003
+ if (floatingUi_utils.getNodeName(child) === 'summary') {
2275
2004
  return child;
2276
2005
  }
2277
2006
  }
@@ -2282,8 +2011,8 @@ function isWithinOpenDetailsSummary(element, details) {
2282
2011
  return !!summary && (element === summary || contains(summary, element));
2283
2012
  }
2284
2013
  function isFocusableCandidate(element) {
2285
- const nodeName = element ? getNodeName(element) : '';
2286
- return element != null && element.matches(CANDIDATE_SELECTOR) && (nodeName !== 'summary' || element.parentElement != null && getNodeName(element.parentElement) === 'details' && getDetailsSummary(element.parentElement) === element) && (nodeName !== 'details' || getDetailsSummary(element) == null) && (nodeName !== 'input' || element.type !== 'hidden');
2014
+ const nodeName = element ? floatingUi_utils.getNodeName(element) : '';
2015
+ return element != null && element.matches(CANDIDATE_SELECTOR) && (nodeName !== 'summary' || element.parentElement != null && floatingUi_utils.getNodeName(element.parentElement) === 'details' && getDetailsSummary(element.parentElement) === element) && (nodeName !== 'details' || getDetailsSummary(element) == null) && (nodeName !== 'input' || element.type !== 'hidden');
2287
2016
  }
2288
2017
  function isFocusableElement(element) {
2289
2018
  if (!isFocusableCandidate(element) || !element.isConnected || element.matches(':disabled')) {
@@ -2291,18 +2020,18 @@ function isFocusableElement(element) {
2291
2020
  }
2292
2021
  for (let current = element; current; current = getParentElement(current)) {
2293
2022
  const isAncestor = current !== element;
2294
- const isSlot = getNodeName(current) === 'slot';
2023
+ const isSlot = floatingUi_utils.getNodeName(current) === 'slot';
2295
2024
  if (current.hasAttribute('inert')) {
2296
2025
  return false;
2297
2026
  }
2298
- if (isAncestor && getNodeName(current) === 'details' && !current.open && !isWithinOpenDetailsSummary(element, current) || current.hasAttribute('hidden') || !isSlot && !isVisibleInTabbableTree(current, isAncestor)) {
2027
+ if (isAncestor && floatingUi_utils.getNodeName(current) === 'details' && !current.open && !isWithinOpenDetailsSummary(element, current) || current.hasAttribute('hidden') || !isSlot && !isVisibleInTabbableTree(current, isAncestor)) {
2299
2028
  return false;
2300
2029
  }
2301
2030
  }
2302
2031
  return true;
2303
2032
  }
2304
2033
  function isVisibleInTabbableTree(element, isAncestor) {
2305
- const styles = getComputedStyle(element);
2034
+ const styles = floatingUi_utils.getComputedStyle(element);
2306
2035
  if (!isAncestor) {
2307
2036
  return isElementVisible(element, styles);
2308
2037
  }
@@ -2311,15 +2040,15 @@ function isVisibleInTabbableTree(element, isAncestor) {
2311
2040
  function getTabIndex(element) {
2312
2041
  const tabIndex = element.tabIndex;
2313
2042
  if (tabIndex < 0) {
2314
- const nodeName = getNodeName(element);
2315
- if (nodeName === 'details' || nodeName === 'audio' || nodeName === 'video' || isHTMLElement(element) && element.isContentEditable) {
2043
+ const nodeName = floatingUi_utils.getNodeName(element);
2044
+ if (nodeName === 'details' || nodeName === 'audio' || nodeName === 'video' || floatingUi_utils.isHTMLElement(element) && element.isContentEditable) {
2316
2045
  return 0;
2317
2046
  }
2318
2047
  }
2319
2048
  return tabIndex;
2320
2049
  }
2321
2050
  function getNamedRadioInput(element) {
2322
- if (getNodeName(element) !== 'input') {
2051
+ if (floatingUi_utils.getNodeName(element) !== 'input') {
2323
2052
  return null;
2324
2053
  }
2325
2054
  const input = element;
@@ -2343,7 +2072,7 @@ function isTabbableRadio(element, candidates) {
2343
2072
  }) === input;
2344
2073
  }
2345
2074
  function getComposedChildren(container) {
2346
- if (isHTMLElement(container) && getNodeName(container) === 'slot') {
2075
+ if (floatingUi_utils.isHTMLElement(container) && floatingUi_utils.getNodeName(container) === 'slot') {
2347
2076
  const assignedElements = container.assignedElements({
2348
2077
  flatten: true
2349
2078
  });
@@ -2351,7 +2080,7 @@ function getComposedChildren(container) {
2351
2080
  return assignedElements;
2352
2081
  }
2353
2082
  }
2354
- if (isHTMLElement(container) && container.shadowRoot) {
2083
+ if (floatingUi_utils.isHTMLElement(container) && container.shadowRoot) {
2355
2084
  return Array.from(container.shadowRoot.children);
2356
2085
  }
2357
2086
  return Array.from(container.children);
@@ -2366,7 +2095,7 @@ function appendCandidates(container, list) {
2366
2095
  }
2367
2096
  function appendMatchingElements(container, selector, list) {
2368
2097
  getComposedChildren(container).forEach(child => {
2369
- if (isHTMLElement(child) && child.matches(selector)) {
2098
+ if (floatingUi_utils.isHTMLElement(child) && child.matches(selector)) {
2370
2099
  list.push(child);
2371
2100
  }
2372
2101
  appendMatchingElements(child, selector, list);
@@ -2523,7 +2252,7 @@ function unwrapHost(node) {
2523
2252
  if (!node) {
2524
2253
  return null;
2525
2254
  }
2526
- return isShadowRoot(node) ? node.host : unwrapHost(node.parentNode);
2255
+ return floatingUi_utils.isShadowRoot(node) ? node.host : unwrapHost(node.parentNode);
2527
2256
  }
2528
2257
  const correctElements = (parent, targets) => targets.map(target => {
2529
2258
  if (parent.contains(target)) {
@@ -2553,7 +2282,7 @@ const collectOutsideElements = (root, keepElements, stopElements) => {
2553
2282
  return;
2554
2283
  }
2555
2284
  Array.from(parent.children).forEach(node => {
2556
- if (getNodeName(node) === 'script') {
2285
+ if (floatingUi_utils.getNodeName(node) === 'script') {
2557
2286
  return;
2558
2287
  }
2559
2288
  if (keepElements.has(node)) {
@@ -2772,7 +2501,12 @@ function useFloatingPortalNode(props = {}) {
2772
2501
  }
2773
2502
  return;
2774
2503
  }
2775
- const resolvedContainer = (containerProp && (isNode(containerProp) ? containerProp : containerProp.current)) ?? parentPortalNode ?? document.body;
2504
+
2505
+ // React 17 does not use React.useId().
2506
+ if (uniqueId == null) {
2507
+ return;
2508
+ }
2509
+ const resolvedContainer = (containerProp && (floatingUi_utils.isNode(containerProp) ? containerProp : containerProp.current)) ?? parentPortalNode ?? document.body;
2776
2510
  if (resolvedContainer == null) {
2777
2511
  if (containerRef.current) {
2778
2512
  containerRef.current = null;
@@ -2786,7 +2520,7 @@ function useFloatingPortalNode(props = {}) {
2786
2520
  setPortalNode(null);
2787
2521
  setContainerElement(resolvedContainer);
2788
2522
  }
2789
- }, [containerProp, parentPortalNode]);
2523
+ }, [containerProp, parentPortalNode, uniqueId]);
2790
2524
  const portalElement = useRenderElement.useRenderElement('div', componentProps, {
2791
2525
  ref: [ref, setPortalNodeRef],
2792
2526
  props: [{
@@ -2799,11 +2533,8 @@ function useFloatingPortalNode(props = {}) {
2799
2533
  // Another call inside `FloatingPortal`/`FloatingPortalLite` then injects the children into `portalElement`.
2800
2534
  const portalSubtree = containerElement && portalElement ? /*#__PURE__*/ReactDOM__namespace.createPortal(portalElement, containerElement) : null;
2801
2535
  return {
2802
- node: portalNode,
2803
- // `id` and `render` props can override or remove the generated ID. Use the exact
2804
- // rendered value so `aria-owns` never points at an ID absent from the DOM.
2805
- nodeId: /*#__PURE__*/React__namespace.isValidElement(portalElement) ? portalElement.props.id : undefined,
2806
- subtree: portalSubtree
2536
+ portalNode,
2537
+ portalSubtree
2807
2538
  };
2808
2539
  }
2809
2540
 
@@ -2823,12 +2554,12 @@ const FloatingPortal = /*#__PURE__*/React__namespace.forwardRef(function Floatin
2823
2554
  style,
2824
2555
  children,
2825
2556
  container,
2557
+ renderGuards,
2826
2558
  ...elementProps
2827
2559
  } = componentProps;
2828
2560
  const {
2829
- node: portalNode,
2830
- nodeId: portalNodeId,
2831
- subtree: portalSubtree
2561
+ portalNode,
2562
+ portalSubtree
2832
2563
  } = useFloatingPortalNode({
2833
2564
  container,
2834
2565
  ref: forwardedRef,
@@ -2843,7 +2574,7 @@ const FloatingPortal = /*#__PURE__*/React__namespace.forwardRef(function Floatin
2843
2574
  const focusInsideDisabledRef = React__namespace.useRef(false);
2844
2575
  const modal = focusManagerState?.modal;
2845
2576
  const open = focusManagerState?.open;
2846
- const shouldRenderGuards = !!focusManagerState && !focusManagerState.modal && focusManagerState.open && !!portalNode;
2577
+ const shouldRenderGuards = typeof renderGuards === 'boolean' ? renderGuards : !!focusManagerState && !focusManagerState.modal && focusManagerState.open && !!portalNode;
2847
2578
 
2848
2579
  // https://codesandbox.io/s/tabbable-portal-f4tng?file=/src/TabbablePortal.tsx
2849
2580
  React__namespace.useEffect(() => {
@@ -2905,7 +2636,7 @@ const FloatingPortal = /*#__PURE__*/React__namespace.forwardRef(function Floatin
2905
2636
  }
2906
2637
  }
2907
2638
  }), shouldRenderGuards && portalNode && /*#__PURE__*/jsxRuntime.jsx("span", {
2908
- "aria-owns": portalNodeId,
2639
+ "aria-owns": portalNode.id,
2909
2640
  style: ownerVisuallyHidden
2910
2641
  }), portalNode && /*#__PURE__*/ReactDOM__namespace.createPortal(children, portalNode), shouldRenderGuards && portalNode && /*#__PURE__*/jsxRuntime.jsx(FocusGuard, {
2911
2642
  "data-type": "outside",
@@ -3062,7 +2793,7 @@ function resolveRef(maybeRef) {
3062
2793
  }
3063
2794
 
3064
2795
  function getEventType(event, lastInteractionType) {
3065
- const win = getWindow(getTarget(event));
2796
+ const win = floatingUi_utils.getWindow(getTarget(event));
3066
2797
  if (event instanceof win.KeyboardEvent) {
3067
2798
  return 'keyboard';
3068
2799
  }
@@ -3092,7 +2823,7 @@ function clearDisconnectedPreviouslyFocusedElements() {
3092
2823
  }
3093
2824
  function addPreviouslyFocusedElement(element) {
3094
2825
  clearDisconnectedPreviouslyFocusedElements();
3095
- if (element && getNodeName(element) !== 'body') {
2826
+ if (element && floatingUi_utils.getNodeName(element) !== 'body') {
3096
2827
  previouslyFocusedElements.push(new WeakRef(element));
3097
2828
  if (previouslyFocusedElements.length > LIST_LIMIT) {
3098
2829
  previouslyFocusedElements = previouslyFocusedElements.slice(-LIST_LIMIT);
@@ -3169,10 +2900,11 @@ function FloatingFocusManager(props) {
3169
2900
  } = store.context;
3170
2901
  const getNodeId = useStableCallback(() => dataRef.current.floatingContext?.nodeId);
3171
2902
  const ignoreInitialFocus = initialFocus === false;
3172
- // A typeable combobox reference (e.g. input/textarea) with `initialFocus={false}`
3173
- // has different focus semantics: focus is not trapped inside the floating element,
3174
- // so in the modal case the guards are not rendered, but `aria-hidden` is still
3175
- // applied to the outside nodes.
2903
+ // If the reference is a combobox and is typeable (e.g. input/textarea),
2904
+ // there are different focus semantics. The guards should not be rendered, but
2905
+ // aria-hidden should be applied to all nodes still. Further, the visually
2906
+ // hidden dismiss button should only appear at the end of the list, not the
2907
+ // start.
3176
2908
  const isUntrappedTypeableCombobox = isTypeableCombobox(domReference) && ignoreInitialFocus;
3177
2909
  const initialFocusRef = useValueAsRef(initialFocus);
3178
2910
  const returnFocusRef = useValueAsRef(returnFocus);
@@ -3286,25 +3018,25 @@ function FloatingFocusManager(props) {
3286
3018
  const triggers = store.context.triggerElements;
3287
3019
  const insideElements = getResolvedInsideElements();
3288
3020
  const isRelatedFocusGuard = relatedTarget?.hasAttribute(createAttribute('focus-guard')) && [beforeGuardRef.current, afterGuardRef.current, portalContext?.beforeInsideRef.current, portalContext?.afterInsideRef.current, portalContext?.beforeOutsideRef.current, portalContext?.afterOutsideRef.current, resolveRef(previousFocusableElement), resolveRef(nextFocusableElement)].includes(relatedTarget);
3289
- const movedToUnrelatedNode = !(contains(domReference, relatedTarget) || contains(floating, relatedTarget) || contains(relatedTarget, floating) || contains(portalContext?.portalNode, relatedTarget) || insideElements.some(element => element === relatedTarget || contains(element, relatedTarget)) || triggers.hasMatchingElement(trigger => contains(trigger, relatedTarget)) || isRelatedFocusGuard || tree && (getNodeChildren(tree.nodesRef.current, nodeId).find(node => contains(node.context?.elements.floating, relatedTarget) || contains(node.context?.elements.domReference, relatedTarget)) || getNodeAncestors(tree.nodesRef.current, nodeId).find(node => [node.context?.elements.floating, getFloatingFocusElement(node.context?.elements.floating)].includes(relatedTarget) || node.context?.elements.domReference === relatedTarget)));
3021
+ const movedToUnrelatedNode = !(contains(domReference, relatedTarget) || contains(floating, relatedTarget) || contains(relatedTarget, floating) || contains(portalContext?.portalNode, relatedTarget) || insideElements.some(element => element === relatedTarget || contains(element, relatedTarget)) || relatedTarget != null && triggers.hasElement(relatedTarget) || triggers.hasMatchingElement(trigger => contains(trigger, relatedTarget)) || isRelatedFocusGuard || tree && (getNodeChildren(tree.nodesRef.current, nodeId).find(node => contains(node.context?.elements.floating, relatedTarget) || contains(node.context?.elements.domReference, relatedTarget)) || getNodeAncestors(tree.nodesRef.current, nodeId).find(node => [node.context?.elements.floating, getFloatingFocusElement(node.context?.elements.floating)].includes(relatedTarget) || node.context?.elements.domReference === relatedTarget)));
3290
3022
  if (currentTarget === domReference && floatingFocusElement) {
3291
3023
  handleTabIndex(floatingFocusElement);
3292
3024
  }
3293
3025
 
3294
- // Restore focus to the previously focused tabbable element to prevent
3026
+ // Restore focus to the previous tabbable element index to prevent
3295
3027
  // focus from being lost outside the floating tree.
3296
3028
  if (restoreFocus && currentTarget !== domReference && !isElementVisible(target) && activeElement(doc) === doc.body) {
3297
3029
  // Let `FloatingPortal` effect knows that focus is still inside the
3298
3030
  // floating tree.
3299
- if (isHTMLElement(floatingFocusElement)) {
3031
+ if (floatingUi_utils.isHTMLElement(floatingFocusElement)) {
3300
3032
  floatingFocusElement.focus();
3301
3033
  // If explicitly requested to restore focus to the popup container, do not search
3302
3034
  // for the next/previous tabbable element.
3303
3035
  if (restoreFocus === 'popup') {
3304
- // If the focused element is removed on pointerdown, the browser
3305
- // tries to move focus to it right after the `.focus()` call above,
3306
- // but because it's removed in the same tick, focus is lost instead.
3307
- // Re-focusing asynchronously (next frame) wins that race.
3036
+ // If the element is removed on pointerdown, focus tries to move it,
3037
+ // but since it's removed at the same time, focus gets lost as it
3038
+ // happens after the .focus() call above.
3039
+ // In this case, focus needs to be moved asynchronously.
3308
3040
  restoreFocusFrame.request(() => {
3309
3041
  floatingFocusElement.focus();
3310
3042
  });
@@ -3314,7 +3046,7 @@ function FloatingFocusManager(props) {
3314
3046
  const tabbableContent = getTabbableContent();
3315
3047
  const prevTabbable = lastFocusedTabbableRef.current;
3316
3048
  const nodeToFocus = (prevTabbable && tabbableContent.includes(prevTabbable) ? prevTabbable : null) || tabbableContent[tabbableContent.length - 1] || floatingFocusElement;
3317
- if (isHTMLElement(nodeToFocus)) {
3049
+ if (floatingUi_utils.isHTMLElement(nodeToFocus)) {
3318
3050
  nodeToFocus.focus();
3319
3051
  }
3320
3052
  }
@@ -3350,7 +3082,7 @@ function FloatingFocusManager(props) {
3350
3082
  dataRef.current.insideReactTree = false;
3351
3083
  });
3352
3084
  }
3353
- const domReferenceElement = isHTMLElement(domReference) ? domReference : null;
3085
+ const domReferenceElement = floatingUi_utils.isHTMLElement(domReference) ? domReference : null;
3354
3086
  if (!floating && !domReferenceElement) {
3355
3087
  return undefined;
3356
3088
  }
@@ -3383,11 +3115,9 @@ function FloatingFocusManager(props) {
3383
3115
 
3384
3116
  // Focus the initial element when the floating element opens.
3385
3117
  useIsoLayoutEffect(() => {
3386
- if (!open || disabled || !isHTMLElement(floatingFocusElement)) {
3118
+ if (!open || disabled || !floatingUi_utils.isHTMLElement(floatingFocusElement)) {
3387
3119
  return;
3388
3120
  }
3389
- closeTypeRef.current = '';
3390
- lastInteractionTypeRef.current = '';
3391
3121
  const doc = ownerDocument(floatingFocusElement);
3392
3122
  const previouslyFocusedElement = activeElement(doc);
3393
3123
 
@@ -3419,9 +3149,7 @@ function FloatingFocusManager(props) {
3419
3149
  }
3420
3150
  elToFocus = elToFocus || getDefaultFocusElement();
3421
3151
  const hadFocusInside = contains(floatingFocusElement, activeElement(doc));
3422
-
3423
- // enqueueFocus returns a rAF-cancel function; we intentionally don't cancel this focus.
3424
- void enqueueFocus(elToFocus, {
3152
+ enqueueFocus(elToFocus, {
3425
3153
  preventScroll: elToFocus === floatingFocusElement,
3426
3154
  shouldFocus() {
3427
3155
  // This focus is queued on the next animation frame. If the floating element has closed
@@ -3448,11 +3176,13 @@ function FloatingFocusManager(props) {
3448
3176
  }
3449
3177
  const doc = ownerDocument(floatingFocusElement);
3450
3178
  const elementFocusedBeforeOpen = activeElement(doc);
3451
- // Only an explicit `null` interaction type represents a programmatic open.
3452
- // `undefined` is normalized to `''` by the prop default, so it never reaches
3453
- // here as nullish and is intentionally not treated as programmatic.
3179
+ // Only nullish interaction types represent programmatic opens. The empty
3180
+ // string default is intentionally not treated as programmatic.
3454
3181
  const preferPreviousFocus = openInteractionTypeRef.current == null;
3455
3182
  addPreviouslyFocusedElement(elementFocusedBeforeOpen);
3183
+
3184
+ // Dismissing via outside press should always ignore `returnFocus` to
3185
+ // prevent unwanted scrolling.
3456
3186
  function onOpenChangeLocal(details) {
3457
3187
  if (!details.open) {
3458
3188
  closeTypeRef.current = getEventType(details.nativeEvent, lastInteractionTypeRef.current);
@@ -3468,11 +3198,6 @@ function FloatingFocusManager(props) {
3468
3198
  } else if (isVirtualClick(details.nativeEvent) || isVirtualPointerEvent(details.nativeEvent)) {
3469
3199
  preventReturnFocusRef.current = false;
3470
3200
  } else {
3471
- // On outside press, only return focus to the reference when the browser supports the
3472
- // `focus({ preventScroll })` option; without it, restoring focus scrolls the page.
3473
- // Chrome on Android and Samsung Internet still don't support `preventScroll`
3474
- // (https://issues.chromium.org/issues/41453122), so the runtime check keeps return
3475
- // focus disabled there to avoid the scroll jump.
3476
3201
  let isPreventScrollSupported = false;
3477
3202
  ownerDocument(floatingFocusElement).createElement('div').focus({
3478
3203
  get preventScroll() {
@@ -3488,9 +3213,9 @@ function FloatingFocusManager(props) {
3488
3213
  }
3489
3214
  }
3490
3215
  events.on('openchange', onOpenChangeLocal);
3491
- function getReturnElement(closeType) {
3216
+ function getReturnElement() {
3492
3217
  const returnFocusValueOrFn = returnFocusRef.current;
3493
- let resolvedReturnFocusValue = typeof returnFocusValueOrFn === 'function' ? returnFocusValueOrFn(closeType) : returnFocusValueOrFn;
3218
+ let resolvedReturnFocusValue = typeof returnFocusValueOrFn === 'function' ? returnFocusValueOrFn(closeTypeRef.current) : returnFocusValueOrFn;
3494
3219
 
3495
3220
  // `null` should fallback to default behavior in case of an empty ref.
3496
3221
  if (resolvedReturnFocusValue === undefined || resolvedReturnFocusValue === false) {
@@ -3500,7 +3225,7 @@ function FloatingFocusManager(props) {
3500
3225
  resolvedReturnFocusValue = true;
3501
3226
  }
3502
3227
  const referenceReturnElement = domReference?.isConnected ? domReference : null;
3503
- const previousReturnElement = elementFocusedBeforeOpen?.isConnected && getNodeName(elementFocusedBeforeOpen) !== 'body' ? elementFocusedBeforeOpen : null;
3228
+ const previousReturnElement = elementFocusedBeforeOpen?.isConnected && floatingUi_utils.getNodeName(elementFocusedBeforeOpen) !== 'body' ? elementFocusedBeforeOpen : null;
3504
3229
  let defaultReturnElement = preferPreviousFocus ? previousReturnElement || referenceReturnElement : referenceReturnElement || previousReturnElement;
3505
3230
  if (!defaultReturnElement) {
3506
3231
  defaultReturnElement = getPreviouslyFocusedElement() || null;
@@ -3518,25 +3243,19 @@ function FloatingFocusManager(props) {
3518
3243
 
3519
3244
  // eslint-disable-next-line react-hooks/exhaustive-deps
3520
3245
  const returnFocusValueOrFn = returnFocusRef.current;
3521
- const closeType = closeTypeRef.current;
3522
- const returnElement = getReturnElement(closeType);
3246
+ const returnElement = getReturnElement();
3523
3247
  queueMicrotask(() => {
3524
- // `returnElement` if it is tabbable, otherwise its first tabbable child,
3525
- // otherwise `returnElement` itself (which may not be tabbable at all).
3248
+ // This is `returnElement`, if it's tabbable, or its first tabbable child.
3526
3249
  const tabbableReturnElement = getFirstTabbableElement(returnElement);
3527
3250
  const hasExplicitReturnFocus = typeof returnFocusValueOrFn !== 'boolean';
3528
- if (returnFocusValueOrFn && !preventReturnFocusRef.current && isHTMLElement(tabbableReturnElement) && (
3251
+ if (returnFocusValueOrFn && !preventReturnFocusRef.current && floatingUi_utils.isHTMLElement(tabbableReturnElement) && (
3529
3252
  // If the focus moved somewhere else after mount, avoid returning focus
3530
3253
  // since it likely entered a different element which should be
3531
3254
  // respected: https://github.com/floating-ui/floating-ui/issues/2607
3532
3255
  !hasExplicitReturnFocus && tabbableReturnElement !== activeEl && activeEl !== doc.body ? isFocusInsideFloatingTree : true)) {
3533
- const focusOptions = {
3256
+ tabbableReturnElement.focus({
3534
3257
  preventScroll: true
3535
- };
3536
- if (closeType === 'keyboard') {
3537
- focusOptions.focusVisible = true;
3538
- }
3539
- tabbableReturnElement.focus(focusOptions);
3258
+ });
3540
3259
  }
3541
3260
  preventReturnFocusRef.current = false;
3542
3261
  });
@@ -3551,7 +3270,7 @@ function FloatingFocusManager(props) {
3551
3270
  return;
3552
3271
  }
3553
3272
  const activeEl = activeElement(ownerDocument(floating));
3554
- if (!isHTMLElement(activeEl) || !isTypeableElement(activeEl)) {
3273
+ if (!floatingUi_utils.isHTMLElement(activeEl) || !isTypeableElement(activeEl)) {
3555
3274
  return;
3556
3275
  }
3557
3276
  if (contains(floating, activeEl)) {
@@ -3559,8 +3278,8 @@ function FloatingFocusManager(props) {
3559
3278
  }
3560
3279
  }, [open, floating]);
3561
3280
 
3562
- // Synchronize the focus manager state (modal, closeOnFocusOut, open, etc.) to the
3563
- // FloatingPortal context, which uses it to decide whether to render its own guards.
3281
+ // Synchronize the `context` & `modal` value to the FloatingPortal context.
3282
+ // It will decide whether or not it needs to render its own guards.
3564
3283
  useIsoLayoutEffect(() => {
3565
3284
  if (disabled || !portalContext) {
3566
3285
  return undefined;
@@ -3595,8 +3314,7 @@ function FloatingFocusManager(props) {
3595
3314
  onFocus: event => {
3596
3315
  if (modal) {
3597
3316
  const els = getTabbableContent();
3598
- // enqueueFocus returns a rAF-cancel function we don't need here.
3599
- void enqueueFocus(els[els.length - 1]);
3317
+ enqueueFocus(els[els.length - 1]);
3600
3318
  } else if (portalContext?.portalNode) {
3601
3319
  preventReturnFocusRef.current = false;
3602
3320
  if (isOutsideEvent(event, portalContext.portalNode)) {
@@ -3612,8 +3330,7 @@ function FloatingFocusManager(props) {
3612
3330
  ref: mergedAfterGuardRef,
3613
3331
  onFocus: event => {
3614
3332
  if (modal) {
3615
- // enqueueFocus returns a rAF-cancel function we don't need here.
3616
- void enqueueFocus(getTabbableContent()[0]);
3333
+ enqueueFocus(getTabbableContent()[0]);
3617
3334
  } else if (portalContext?.portalNode) {
3618
3335
  if (closeOnFocusOut) {
3619
3336
  preventReturnFocusRef.current = true;
@@ -3685,11 +3402,7 @@ function useClick(context, props = {}) {
3685
3402
  }
3686
3403
  return {
3687
3404
  onPointerDown(event) {
3688
- // Screen reader activations (Android TalkBack, desktop screen readers) report a
3689
- // mouse-like `pointerType`, but `ignoreMouse` must not drop them: hover logic cannot
3690
- // open for a virtual press since there is no real pointer movement to wait for.
3691
- // Virtual `touch` presses (iOS VoiceOver) keep their type so `touchOpenDelay` applies.
3692
- pointerTypeRef.current = isMouseLikePointerType(event.pointerType, true) && isVirtualPointerEvent(event.nativeEvent) ? 'virtual' : event.pointerType;
3405
+ pointerTypeRef.current = event.pointerType;
3693
3406
  },
3694
3407
  onMouseDown(event) {
3695
3408
  const pointerType = pointerTypeRef.current;
@@ -3869,7 +3582,7 @@ function useDismiss(context, props = {}) {
3869
3582
  });
3870
3583
  React__namespace.useEffect(() => {
3871
3584
  if (!open || !enabled) {
3872
- return clearInsideReactTree;
3585
+ return undefined;
3873
3586
  }
3874
3587
  dataRef.current.__escapeKeyBubbles = escapeKeyBubbles;
3875
3588
  dataRef.current.__outsidePressBubbles = outsidePressBubbles;
@@ -3938,18 +3651,18 @@ function useDismiss(context, props = {}) {
3938
3651
  }
3939
3652
  const target = getTarget(event);
3940
3653
  const inertSelector = `[${createAttribute('inert')}]`;
3941
- const targetRoot = isElement(target) ? target.getRootNode() : null;
3942
- const markers = Array.from((isShadowRoot(targetRoot) ? targetRoot : ownerDocument(store.select('floatingElement'))).querySelectorAll(inertSelector));
3654
+ const targetRoot = floatingUi_utils.isElement(target) ? target.getRootNode() : null;
3655
+ const markers = Array.from((floatingUi_utils.isShadowRoot(targetRoot) ? targetRoot : ownerDocument(store.select('floatingElement'))).querySelectorAll(inertSelector));
3943
3656
  const triggers = store.context.triggerElements;
3944
3657
 
3945
3658
  // If another trigger is clicked, don't close the floating element.
3946
3659
  if (target && (triggers.hasElement(target) || triggers.hasMatchingElement(trigger => contains(trigger, target)))) {
3947
3660
  return;
3948
3661
  }
3949
- let targetRootAncestor = isElement(target) ? target : null;
3950
- while (targetRootAncestor && !isLastTraversableNode(targetRootAncestor)) {
3951
- const nextParent = getParentNode(targetRootAncestor);
3952
- if (isLastTraversableNode(nextParent) || !isElement(nextParent)) {
3662
+ let targetRootAncestor = floatingUi_utils.isElement(target) ? target : null;
3663
+ while (targetRootAncestor && !floatingUi_utils.isLastTraversableNode(targetRootAncestor)) {
3664
+ const nextParent = floatingUi_utils.getParentNode(targetRootAncestor);
3665
+ if (floatingUi_utils.isLastTraversableNode(nextParent) || !floatingUi_utils.isElement(nextParent)) {
3953
3666
  break;
3954
3667
  }
3955
3668
  targetRootAncestor = nextParent;
@@ -3957,7 +3670,7 @@ function useDismiss(context, props = {}) {
3957
3670
 
3958
3671
  // Check if the click occurred on a third-party element injected after the
3959
3672
  // floating element rendered.
3960
- if (markers.length && isElement(target) && !isRootElement(target) &&
3673
+ if (markers.length && floatingUi_utils.isElement(target) && !isRootElement(target) &&
3961
3674
  // Clicked on a direct ancestor (e.g. FloatingOverlay).
3962
3675
  !contains(target, store.select('floatingElement')) &&
3963
3676
  // If the target root element contains none of the markers, then the
@@ -3968,9 +3681,9 @@ function useDismiss(context, props = {}) {
3968
3681
 
3969
3682
  // Check if the click occurred on the scrollbar
3970
3683
  // Skip for touch events: scrollbars don't receive touch events on most platforms
3971
- if (isHTMLElement(target) && !('touches' in event)) {
3972
- const lastTraversableNode = isLastTraversableNode(target);
3973
- const style = getComputedStyle(target);
3684
+ if (floatingUi_utils.isHTMLElement(target) && !('touches' in event)) {
3685
+ const lastTraversableNode = floatingUi_utils.isLastTraversableNode(target);
3686
+ const style = floatingUi_utils.getComputedStyle(target);
3974
3687
  const scrollRe = /auto|scroll/;
3975
3688
  const isScrollableX = lastTraversableNode || scrollRe.test(style.overflowX);
3976
3689
  const isScrollableY = lastTraversableNode || scrollRe.test(style.overflowY);
@@ -4147,9 +3860,9 @@ function useDismiss(context, props = {}) {
4147
3860
  preventedPressSuppressionTimeout.clear();
4148
3861
  resetPressStartState();
4149
3862
  suppressNextOutsideClickRef.current = false;
4150
- clearInsideReactTree();
4151
3863
  };
4152
3864
  }, [dataRef, floatingElement, escapeKey$1, outsidePressEnabled, outsidePress$1, open, enabled, escapeKeyBubbles, outsidePressBubbles, closeOnEscapeKeyDown, clearInsideReactTree, getOutsidePressEventProp, hasBlockingChild, isEventWithinOwnElements, tree, store, cancelDismissOnEndTimeout]);
3865
+ React__namespace.useEffect(clearInsideReactTree, [outsidePress$1, clearInsideReactTree]);
4153
3866
  const reference = React__namespace.useMemo(() => ({
4154
3867
  onKeyDown: closeOnEscapeKeyDown,
4155
3868
  onPointerDown: closeOnReferencePress,
@@ -4183,12 +3896,12 @@ function useDismiss(context, props = {}) {
4183
3896
  }
4184
3897
 
4185
3898
  const selectors = {
4186
- open: state => state.open,
4187
- transitionStatus: state => state.transitionStatus,
4188
- domReferenceElement: state => state.domReferenceElement,
4189
- referenceElement: state => state.positionReference ?? state.referenceElement,
4190
- floatingElement: state => state.floatingElement,
4191
- floatingId: state => state.floatingId
3899
+ open: createSelector(state => state.open),
3900
+ transitionStatus: createSelector(state => state.transitionStatus),
3901
+ domReferenceElement: createSelector(state => state.domReferenceElement),
3902
+ referenceElement: createSelector(state => state.positionReference ?? state.referenceElement),
3903
+ floatingElement: createSelector(state => state.floatingElement),
3904
+ floatingId: createSelector(state => state.floatingId)
4192
3905
  };
4193
3906
  class FloatingRootStore extends ReactStore {
4194
3907
  constructor(options) {
@@ -4299,7 +4012,7 @@ function useSyncedFloatingRootContext(options) {
4299
4012
  referenceElement,
4300
4013
  floatingElement
4301
4014
  };
4302
- if (isElement(referenceElement)) {
4015
+ if (floatingUi_utils.isElement(referenceElement)) {
4303
4016
  valuesToSync.domReferenceElement = referenceElement;
4304
4017
  }
4305
4018
  if (store.state.positionReference === store.state.referenceElement) {
@@ -4377,14 +4090,44 @@ function useTransitionStatus(open, enableIdleState = false, deferEndingState = f
4377
4090
  };
4378
4091
  }
4379
4092
 
4093
+ let TransitionStatusDataAttributes = /*#__PURE__*/function (TransitionStatusDataAttributes) {
4094
+ /**
4095
+ * Present when the component is animating in.
4096
+ */
4097
+ TransitionStatusDataAttributes["startingStyle"] = "data-starting-style";
4098
+ /**
4099
+ * Present when the component is animating out.
4100
+ */
4101
+ TransitionStatusDataAttributes["endingStyle"] = "data-ending-style";
4102
+ return TransitionStatusDataAttributes;
4103
+ }({});
4104
+ const STARTING_HOOK = {
4105
+ [TransitionStatusDataAttributes.startingStyle]: ''
4106
+ };
4107
+ const ENDING_HOOK = {
4108
+ [TransitionStatusDataAttributes.endingStyle]: ''
4109
+ };
4110
+ const transitionStatusMapping = {
4111
+ transitionStatus(value) {
4112
+ if (value === 'starting') {
4113
+ return STARTING_HOOK;
4114
+ }
4115
+ if (value === 'ending') {
4116
+ return ENDING_HOOK;
4117
+ }
4118
+ return null;
4119
+ }
4120
+ };
4121
+
4380
4122
  /**
4381
4123
  * Executes a function once all animations have finished on the provided element.
4382
- * If an animation is canceled, waits for any replacement animations before executing.
4383
4124
  * @param elementOrRef - The element to watch for animations.
4384
4125
  * @param waitForStartingStyleRemoved - Whether to wait for [data-starting-style] to be removed before checking for animations.
4126
+ * @param treatAbortedAsFinished - Whether to treat aborted animations as finished. If `false`, and there are aborted animations,
4127
+ * the function will check again if any new animations have started and wait for them to finish.
4385
4128
  * @returns A function that takes a callback to execute once all animations have finished, and an optional AbortSignal to abort the callback
4386
4129
  */
4387
- function useAnimationsFinished(elementOrRef, waitForStartingStyleRemoved = false) {
4130
+ function useAnimationsFinished(elementOrRef, waitForStartingStyleRemoved = false, treatAbortedAsFinished = true) {
4388
4131
  const frame = useAnimationFrame();
4389
4132
  return useStableCallback((fnToExecute,
4390
4133
  /**
@@ -4413,22 +4156,23 @@ function useAnimationsFinished(elementOrRef, waitForStartingStyleRemoved = false
4413
4156
  if (!signal?.aborted) {
4414
4157
  done();
4415
4158
  }
4416
- }, () => {
4417
- if (signal?.aborted) {
4159
+ }).catch(() => {
4160
+ if (treatAbortedAsFinished) {
4161
+ if (!signal?.aborted) {
4162
+ done();
4163
+ }
4418
4164
  return;
4419
4165
  }
4420
4166
  const currentAnimations = resolvedElement.getAnimations();
4421
- if (currentAnimations.some(animation => animation.pending || animation.playState !== 'finished')) {
4167
+ if (!signal?.aborted && currentAnimations.length > 0 && currentAnimations.some(animation => animation.pending || animation.playState !== 'finished')) {
4422
4168
  // Sometimes animations can be aborted because a property they depend on changes while the animation plays.
4423
4169
  // In such cases, we need to re-check if any new animations have started.
4424
4170
  exec();
4425
- return;
4426
4171
  }
4427
- done();
4428
4172
  });
4429
4173
  }
4430
4174
  if (waitForStartingStyleRemoved) {
4431
- const startingStyleAttribute = 'data-starting-style';
4175
+ const startingStyleAttribute = TransitionStatusDataAttributes.startingStyle;
4432
4176
 
4433
4177
  // If `[data-starting-style]` isn't present, fall back to waiting one more frame
4434
4178
  // to give "open" animations a chance to be registered.
@@ -4468,7 +4212,7 @@ function useOpenChangeComplete(parameters) {
4468
4212
  onComplete: onCompleteParam
4469
4213
  } = parameters;
4470
4214
  const onComplete = useStableCallback(onCompleteParam);
4471
- const runOnceAnimationsFinish = useAnimationsFinished(ref, open);
4215
+ const runOnceAnimationsFinish = useAnimationsFinished(ref, open, false);
4472
4216
  React__namespace.useEffect(() => {
4473
4217
  if (!enabled) {
4474
4218
  return undefined;
@@ -4494,26 +4238,14 @@ const FOCUSABLE_POPUP_PROPS = {
4494
4238
  function createDefaultInitialFocus(popupRef) {
4495
4239
  return interactionType => interactionType === 'touch' ? popupRef.current : true;
4496
4240
  }
4497
-
4498
- /**
4499
- * The subset of a popup handle that a Root needs to bind its store to. Both the real handle classes
4500
- * and any test double satisfy it.
4501
- */
4502
-
4503
- /**
4504
- * Creates and owns a popup store on behalf of a Root part. The store is created exactly once, with
4505
- * controlled props and root state synced separately after creation. Sets up the synced floating
4506
- * root context and returns the store.
4507
- *
4508
- * @param createStore Factory that builds the store. Called exactly once, receiving the floating id
4509
- * and whether the popup is nested inside another floating element, both resolved on the first render.
4510
- * @param treatPopupAsFloatingElement Whether the popup element is passed to Floating UI as the
4511
- * floating element instead of the default positioner.
4512
- */
4513
- function usePopupRootStore(createStore, treatPopupAsFloatingElement = false) {
4241
+ function usePopupStore(externalStore, createStore, treatPopupAsFloatingElement = false) {
4514
4242
  const floatingId = useId();
4515
4243
  const nested = useFloatingParentNodeId() != null;
4516
- const store = useRenderElement.useRefWithInit(() => createStore(floatingId, nested)).current;
4244
+ const internalStoreRef = React__namespace.useRef(null);
4245
+ if (externalStore === undefined && internalStoreRef.current === null) {
4246
+ internalStoreRef.current = createStore(floatingId, nested);
4247
+ }
4248
+ const store = externalStore ?? internalStoreRef.current;
4517
4249
  useSyncedFloatingRootContext({
4518
4250
  popupStore: store,
4519
4251
  treatPopupAsFloatingElement,
@@ -4522,27 +4254,10 @@ function usePopupRootStore(createStore, treatPopupAsFloatingElement = false) {
4522
4254
  nested,
4523
4255
  onOpenChange: store.setOpen
4524
4256
  });
4525
- return store;
4526
- }
4527
-
4528
- /**
4529
- * Attaches a Root's store to a handle for this component's committed lifetime. Popup Roots render
4530
- * it before their interactions and user children so its layout effect runs before descendant layout
4531
- * effects. This lets descendants call the handle during the Root's initial commit without attaching
4532
- * during render, which would leak suspended or abandoned stores. Store subscribers are notified by
4533
- * `attachStore` in this ordinary layout phase, where React permits synchronous updates.
4534
- *
4535
- * Popup Roots must render this component only when a handle is present so handle-less Roots avoid
4536
- * mounting an extra fiber and layout effect.
4537
- */
4538
- function PopupHandleAttachment({
4539
- handle,
4540
- store
4541
- }) {
4542
- useIsoLayoutEffect(() => {
4543
- return handle.attachStore(store);
4544
- }, [handle, store]);
4545
- return null;
4257
+ return {
4258
+ store,
4259
+ internalStore: internalStoreRef.current
4260
+ };
4546
4261
  }
4547
4262
 
4548
4263
  /**
@@ -4607,6 +4322,19 @@ function attachPreventUnmountOnClose(eventDetails) {
4607
4322
  };
4608
4323
  return () => preventUnmountOnClose;
4609
4324
  }
4325
+ function useInitialOpenSync(store, openProp, defaultOpen, defaultTriggerId) {
4326
+ useOnFirstRender(() => {
4327
+ if (openProp === undefined && store.state.open === false && defaultOpen) {
4328
+ // Avoid notifying detached trigger subscribers while the Root is rendering.
4329
+ store.state = {
4330
+ ...store.state,
4331
+ open: true,
4332
+ activeTriggerId: defaultTriggerId,
4333
+ preventUnmountingOnClose: false
4334
+ };
4335
+ }
4336
+ });
4337
+ }
4610
4338
 
4611
4339
  /**
4612
4340
  * Sets up trigger data forwarding to the store.
@@ -4619,11 +4347,11 @@ function attachPreventUnmountOnClose(eventDetails) {
4619
4347
  function useTriggerDataForwarding(triggerId, triggerElementRef, store, stateUpdates) {
4620
4348
  const isMountedByThisTrigger = store.useState('isMountedByTrigger', triggerId);
4621
4349
  const baseRegisterTrigger = useTriggerRegistration(triggerId, store);
4622
-
4623
- // Applies trigger-owned state (active-trigger ownership and payload) when the trigger registers.
4624
- // Stable so payload/`stateUpdates` changes do not change the ref identity (which would needlessly
4625
- // churn registration); it reads the latest closure values when invoked.
4626
- const applyTriggerData = useStableCallback(element => {
4350
+ const registerTrigger = useStableCallback(element => {
4351
+ baseRegisterTrigger(element);
4352
+ if (!element) {
4353
+ return;
4354
+ }
4627
4355
  const open = store.select('open');
4628
4356
  const activeTriggerId = store.select('activeTriggerId');
4629
4357
  if (activeTriggerId === triggerId) {
@@ -4644,18 +4372,6 @@ function useTriggerDataForwarding(triggerId, triggerElementRef, store, stateUpda
4644
4372
  });
4645
4373
  }
4646
4374
  });
4647
-
4648
- // Intentionally NOT stable. Its identity is derived from `baseRegisterTrigger`, which is keyed on
4649
- // `[store, id]`, so when a handle-backed trigger's store pointer swaps the merged ref re-fires —
4650
- // unregistering from the previous store and registering into the new one. This lets a detached
4651
- // trigger follow its handle's currently-attached store across attach/detach/remount. (A stable
4652
- // callback would keep its identity and never re-fire on a store swap.)
4653
- const registerTrigger = React__namespace.useCallback(element => {
4654
- baseRegisterTrigger(element);
4655
- if (element) {
4656
- applyTriggerData(element);
4657
- }
4658
- }, [baseRegisterTrigger, applyTriggerData]);
4659
4375
  useIsoLayoutEffect(() => {
4660
4376
  if (isMountedByThisTrigger) {
4661
4377
  store.update({
@@ -4675,17 +4391,12 @@ function useTriggerDataForwarding(triggerId, triggerElementRef, store, stateUpda
4675
4391
  *
4676
4392
  * When a popup opens without an explicit trigger id and exactly one trigger is registered, that
4677
4393
  * trigger is claimed as the active trigger. When the active trigger id is still registered but its
4678
- * element changed, the active element is refreshed. When the active trigger id is missing from the
4679
- * registry but the same element is still registered under a different id (e.g. the rendered trigger
4680
- * carries its own DOM `id` that differs from Base UI's internal trigger id), the active id is
4681
- * reassociated to the registered id instead of being treated as lost. When the active trigger
4682
- * unregisters, the default path preserves existing ownership so non-closing popup families do not
4683
- * silently claim a different trigger while staying open.
4394
+ * element changed, the active element is refreshed. When the active trigger unregisters, the
4395
+ * default path preserves existing ownership so non-closing popup families do not silently claim a
4396
+ * different trigger while staying open.
4684
4397
  *
4685
- * If `closeOnActiveTriggerUnmount` is enabled, unregistering a previously resolved active trigger
4686
- * requests a close after a microtask so a same-tick replacement trigger with the same id can
4687
- * register first. An active trigger id that has not matched a registered trigger yet is treated as
4688
- * pending and does not request a close.
4398
+ * If `closeOnActiveTriggerUnmount` is enabled, unregistering the active trigger requests a close
4399
+ * after a microtask so a same-tick replacement trigger with the same id can register first.
4689
4400
  *
4690
4401
  * This should be called on the Root part.
4691
4402
  *
@@ -4696,22 +4407,10 @@ function useImplicitActiveTrigger(store, options = {}) {
4696
4407
  const {
4697
4408
  closeOnActiveTriggerUnmount = false
4698
4409
  } = options;
4699
- // Distinguishes a trigger that unmounted from a new active trigger that has not hydrated yet.
4700
- const resolvedActiveTriggerIdRef = React__namespace.useRef(null);
4701
4410
  const open = store.useState('open');
4702
4411
  const reactiveTriggerCount = store.useState('triggerCount');
4703
- // Subscribe to the active trigger id so the reconciliation below reruns when ownership moves to
4704
- // another trigger while the popup stays open (e.g. a focus/hover handoff between triggers).
4705
- const activeTriggerId = store.useState('activeTriggerId');
4706
- // Subscribe to the active trigger element so the reconciliation reruns when a pending active
4707
- // trigger registers in a commit where the trigger count nets out unchanged (registration
4708
- // forwards the element to the store when the registering trigger matches the active id).
4709
- // Without this, the id would never be marked resolved and a later genuine unmount would be
4710
- // misclassified as pending, disabling `closeOnActiveTriggerUnmount`.
4711
- const reactiveActiveTriggerElement = store.useState('activeTriggerElement');
4712
4412
  useIsoLayoutEffect(() => {
4713
4413
  if (!open) {
4714
- resolvedActiveTriggerIdRef.current = null;
4715
4414
  if (store.state.triggerCount !== 0) {
4716
4415
  store.set('triggerCount', 0);
4717
4416
  }
@@ -4722,42 +4421,22 @@ function useImplicitActiveTrigger(store, options = {}) {
4722
4421
  if (store.state.triggerCount !== triggerCount) {
4723
4422
  stateUpdates.triggerCount = triggerCount;
4724
4423
  }
4725
- const currentActiveTriggerId = store.select('activeTriggerId');
4424
+ const activeTriggerId = store.select('activeTriggerId');
4726
4425
  let lostActiveTriggerId = null;
4727
- if (currentActiveTriggerId) {
4728
- const activeTriggerElement = store.context.triggerElements.getById(currentActiveTriggerId);
4426
+ if (activeTriggerId) {
4427
+ const activeTriggerElement = store.context.triggerElements.getById(activeTriggerId);
4729
4428
  if (!activeTriggerElement) {
4730
- for (const [triggerId, triggerElement] of store.context.triggerElements.entries()) {
4731
- if (triggerElement === store.state.activeTriggerElement) {
4732
- stateUpdates.activeTriggerId = triggerId;
4733
- stateUpdates.activeTriggerElement = triggerElement;
4734
- resolvedActiveTriggerIdRef.current = triggerId;
4735
- break;
4736
- }
4737
- }
4738
- if (stateUpdates.activeTriggerId === undefined) {
4739
- if (resolvedActiveTriggerIdRef.current === currentActiveTriggerId) {
4740
- lostActiveTriggerId = currentActiveTriggerId;
4741
- } else {
4742
- resolvedActiveTriggerIdRef.current = null;
4743
- }
4744
- }
4745
- } else {
4746
- resolvedActiveTriggerIdRef.current = currentActiveTriggerId;
4747
- if (activeTriggerElement !== store.state.activeTriggerElement) {
4748
- stateUpdates.activeTriggerElement = activeTriggerElement;
4749
- }
4429
+ lostActiveTriggerId = activeTriggerId;
4430
+ } else if (activeTriggerElement !== store.state.activeTriggerElement) {
4431
+ stateUpdates.activeTriggerElement = activeTriggerElement;
4750
4432
  }
4751
- } else {
4752
- resolvedActiveTriggerIdRef.current = null;
4753
4433
  }
4754
- if (!lostActiveTriggerId && !currentActiveTriggerId && triggerCount === 1) {
4434
+ if (!lostActiveTriggerId && !activeTriggerId && triggerCount === 1) {
4755
4435
  const iteratorResult = store.context.triggerElements.entries().next();
4756
4436
  if (!iteratorResult.done) {
4757
4437
  const [implicitTriggerId, implicitTriggerElement] = iteratorResult.value;
4758
4438
  stateUpdates.activeTriggerId = implicitTriggerId;
4759
4439
  stateUpdates.activeTriggerElement = implicitTriggerElement;
4760
- resolvedActiveTriggerIdRef.current = implicitTriggerId;
4761
4440
  }
4762
4441
  }
4763
4442
  if (stateUpdates.triggerCount !== undefined || stateUpdates.activeTriggerId !== undefined || stateUpdates.activeTriggerElement !== undefined) {
@@ -4782,7 +4461,7 @@ function useImplicitActiveTrigger(store, options = {}) {
4782
4461
  });
4783
4462
  }
4784
4463
  }
4785
- }, [open, store, reactiveTriggerCount, activeTriggerId, reactiveActiveTriggerElement, closeOnActiveTriggerUnmount]);
4464
+ }, [open, store, reactiveTriggerCount, closeOnActiveTriggerUnmount]);
4786
4465
  }
4787
4466
 
4788
4467
  /**
@@ -4860,33 +4539,13 @@ function usePopupRootSync(store, open) {
4860
4539
  }, [store]);
4861
4540
  }
4862
4541
 
4863
- /**
4864
- * Development-only reverse index of element to registered id, keyed by the owning map.
4865
- *
4866
- * Registration would otherwise have to scan every entry to detect an element claimed by two ids,
4867
- * making the mount of many triggers sharing one handle quadratic. Kept module-scoped, lazily
4868
- * initialized, and read only from `process.env.NODE_ENV` guards so production builds drop it along
4869
- * with the checks.
4870
- */
4871
- let devElementIdsByMap;
4872
- function getDevElementIds(map) {
4873
- devElementIdsByMap ??= new WeakMap();
4874
- let elementIds = devElementIdsByMap.get(map);
4875
- if (!elementIds) {
4876
- elementIds = new WeakMap();
4877
- devElementIdsByMap.set(map, elementIds);
4878
- }
4879
- return elementIds;
4880
- }
4881
-
4882
4542
  /**
4883
4543
  * Data structure to keep track of popup trigger elements by their IDs.
4884
- *
4885
- * Element lookups iterate the id map rather than maintaining a parallel Set. Registration is O(1),
4886
- * while `hasElement` and `hasMatchingElement` are linear in the number of triggers.
4544
+ * Uses both a set of Elements and a map of IDs to Elements for efficient lookups.
4887
4545
  */
4888
4546
  class PopupTriggerMap {
4889
4547
  constructor() {
4548
+ this.elementsSet = new Set();
4890
4549
  this.idMap = new Map();
4891
4550
  }
4892
4551
 
@@ -4896,56 +4555,49 @@ class PopupTriggerMap {
4896
4555
  * Note: The provided element is assumed to not be registered under multiple IDs.
4897
4556
  */
4898
4557
  add(id, element) {
4558
+ const existingElement = this.idMap.get(id);
4559
+ if (existingElement === element) {
4560
+ return;
4561
+ }
4562
+ if (existingElement !== undefined) {
4563
+ // We assume that the same element won't be registered under multiple ids.
4564
+ // This is safe considering how useTriggerRegistration is implemented.
4565
+ this.elementsSet.delete(existingElement);
4566
+ }
4567
+ this.elementsSet.add(element);
4568
+ this.idMap.set(id, element);
4899
4569
  if (process.env.NODE_ENV !== 'production') {
4900
- const elementIds = getDevElementIds(this);
4901
- const existingId = elementIds.get(element);
4902
- if (existingId !== undefined && existingId !== id) {
4570
+ if (this.elementsSet.size !== this.idMap.size) {
4903
4571
  // TODO: fix mui/no-guarded-throw
4904
4572
  // eslint-disable-next-line mui/no-guarded-throw
4905
4573
  throw new Error('Base UI: A trigger element cannot be registered under multiple IDs in PopupTriggerMap.');
4906
4574
  }
4907
-
4908
- // Reusing an id for a different element evicts the previous one, so it must lose its claim
4909
- // on the id or a later registration under a different id would be reported as a duplicate.
4910
- const previousElement = this.idMap.get(id);
4911
- if (previousElement !== undefined && previousElement !== element) {
4912
- elementIds.delete(previousElement);
4913
- }
4914
- elementIds.set(element, id);
4915
4575
  }
4916
- this.idMap.set(id, element);
4917
4576
  }
4918
4577
 
4919
4578
  /**
4920
4579
  * Removes the trigger element with the given ID.
4921
4580
  */
4922
4581
  delete(id) {
4923
- if (process.env.NODE_ENV !== 'production') {
4924
- const element = this.idMap.get(id);
4925
- if (element !== undefined) {
4926
- devElementIdsByMap?.get(this)?.delete(element);
4927
- }
4582
+ const element = this.idMap.get(id);
4583
+ if (element) {
4584
+ this.elementsSet.delete(element);
4585
+ this.idMap.delete(id);
4928
4586
  }
4929
- this.idMap.delete(id);
4930
4587
  }
4931
4588
 
4932
4589
  /**
4933
4590
  * Whether the given element is registered as a trigger.
4934
4591
  */
4935
4592
  hasElement(element) {
4936
- for (const registered of this.idMap.values()) {
4937
- if (registered === element) {
4938
- return true;
4939
- }
4940
- }
4941
- return false;
4593
+ return this.elementsSet.has(element);
4942
4594
  }
4943
4595
 
4944
4596
  /**
4945
4597
  * Whether there is a registered trigger element matching the given predicate.
4946
4598
  */
4947
4599
  hasMatchingElement(predicate) {
4948
- for (const element of this.idMap.values()) {
4600
+ for (const element of this.elementsSet) {
4949
4601
  if (predicate(element)) {
4950
4602
  return true;
4951
4603
  }
@@ -4971,7 +4623,7 @@ class PopupTriggerMap {
4971
4623
  * Returns an iterable of all registered trigger elements.
4972
4624
  */
4973
4625
  elements() {
4974
- return this.idMap.values();
4626
+ return this.elementsSet.values();
4975
4627
  }
4976
4628
 
4977
4629
  /**
@@ -5031,11 +4683,14 @@ function useValueChanged(value, onChange) {
5031
4683
  const valueRef = React__namespace.useRef(value);
5032
4684
  const onChangeCallback = useStableCallback(onChange);
5033
4685
  useIsoLayoutEffect(() => {
5034
- if (valueRef.current !== value) {
5035
- onChangeCallback(valueRef.current);
4686
+ if (valueRef.current === value) {
4687
+ return;
5036
4688
  }
5037
- valueRef.current = value;
4689
+ onChangeCallback(valueRef.current);
5038
4690
  }, [value, onChangeCallback]);
4691
+ useIsoLayoutEffect(() => {
4692
+ valueRef.current = value;
4693
+ }, [value]);
5039
4694
  }
5040
4695
 
5041
4696
  function useOpenMethodTriggerProps(open, setOpenMethod) {
@@ -5078,6 +4733,9 @@ function useOpenInteractionType(open) {
5078
4733
  }), [openMethod, triggerProps]);
5079
4734
  }
5080
4735
 
4736
+ /**
4737
+ * @internal
4738
+ */
5081
4739
  const DirectionContext = /*#__PURE__*/React__namespace.createContext(undefined);
5082
4740
  if (process.env.NODE_ENV !== "production") DirectionContext.displayName = "DirectionContext";
5083
4741
  function useDirection() {
@@ -5136,30 +4794,6 @@ function useFocusableWhenDisabled(parameters) {
5136
4794
  };
5137
4795
  }
5138
4796
 
5139
- /**
5140
- * Dispatches a constructed click on the target so it carries the source event's
5141
- * modifier state, which `click()` always reports as unpressed. Like `click()`,
5142
- * the untrusted click still runs native activation behavior (form submission,
5143
- * link navigation).
5144
- * `detail` defaults to 0 (the native convention for keyboard-generated clicks);
5145
- * pass `detail: 1` when the click represents a mouse gesture so consumers keying
5146
- * off `detail === 0` don't classify it as a keyboard activation.
5147
- */
5148
- function dispatchClickWithModifiers(target, sourceEvent, {
5149
- detail = 0
5150
- } = {}) {
5151
- target.dispatchEvent(new (getWindow(target).PointerEvent)('click', {
5152
- bubbles: true,
5153
- cancelable: true,
5154
- composed: true,
5155
- detail,
5156
- shiftKey: sourceEvent.shiftKey,
5157
- ctrlKey: sourceEvent.ctrlKey,
5158
- altKey: sourceEvent.altKey,
5159
- metaKey: sourceEvent.metaKey
5160
- }));
5161
- }
5162
-
5163
4797
  function useButton(parameters = {}) {
5164
4798
  const {
5165
4799
  disabled = false,
@@ -5260,34 +4894,24 @@ function useButton(parameters = {}) {
5260
4894
  return;
5261
4895
  }
5262
4896
  event.preventDefault();
5263
-
5264
- // Only a native-mode item that isn't a real <button> is excluded.
5265
- if (!isNativeButton || isButton) {
4897
+ if (isLink || isNativeButton && isButton) {
4898
+ currentTarget.click();
4899
+ event.preventBaseUIHandler();
4900
+ } else if (shouldClick) {
4901
+ externalOnClick?.(event);
5266
4902
  event.preventBaseUIHandler();
5267
- dispatchClickWithModifiers(currentTarget, event);
5268
4903
  }
5269
4904
  return;
5270
4905
  }
5271
4906
 
5272
4907
  // Keyboard accessibility for native and non-native elements.
5273
- if (!shouldClick || isNativeButton || !isSpaceKey && !isEnterKey) {
5274
- // Space activates links on keyup (`role="button"` semantics, matching the
5275
- // composite path); prevent the page scroll Space would otherwise trigger.
5276
- // Enter is left to the browser's native link activation.
5277
- if (isCurrentTarget && isLink && isSpaceKey) {
4908
+ if (shouldClick) {
4909
+ if (!isNativeButton && (isSpaceKey || isEnterKey)) {
5278
4910
  event.preventDefault();
5279
4911
  }
5280
- return;
5281
- }
5282
-
5283
- // Match native buttons: preventing the keydown's default cancels activation.
5284
- if (event.defaultPrevented) {
5285
- return;
5286
- }
5287
- event.preventDefault();
5288
- if (isEnterKey) {
5289
- event.preventBaseUIHandler();
5290
- dispatchClickWithModifiers(currentTarget, event);
4912
+ if (!isNativeButton && isEnterKey) {
4913
+ externalOnClick?.(event);
4914
+ }
5291
4915
  }
5292
4916
  },
5293
4917
  onKeyUp(event) {
@@ -5307,14 +4931,9 @@ function useButton(parameters = {}) {
5307
4931
  return;
5308
4932
  }
5309
4933
 
5310
- // Keyboard accessibility for non interactive elements.
5311
- // Match native buttons: preventing the keyup's default cancels Space activation.
5312
- // Limitation: unlike a native <button>, a prevented *keydown* cannot cancel the
5313
- // activation — no state is kept between keydown and keyup, so we can't tell
5314
- // whether the keydown was prevented or even happened on this element.
5315
- if (event.target === event.currentTarget && !isNativeButton && !isCompositeItem && !event.defaultPrevented && event.key === ' ') {
5316
- event.preventBaseUIHandler();
5317
- dispatchClickWithModifiers(event.currentTarget, event);
4934
+ // Keyboard accessibility for non interactive elements
4935
+ if (event.target === event.currentTarget && !isNativeButton && !isCompositeItem && event.key === ' ') {
4936
+ externalOnClick?.(event);
5318
4937
  }
5319
4938
  },
5320
4939
  onPointerDown(event) {
@@ -5340,41 +4959,12 @@ function useButton(parameters = {}) {
5340
4959
  };
5341
4960
  }
5342
4961
  function isButtonElement(elem) {
5343
- return isHTMLElement(elem) && elem.tagName === 'BUTTON';
4962
+ return floatingUi_utils.isHTMLElement(elem) && elem.tagName === 'BUTTON';
5344
4963
  }
5345
4964
  function isValidLinkElement(elem) {
5346
- return isHTMLElement(elem) && elem.tagName === 'A' && Boolean(elem.href);
4965
+ return Boolean(elem?.tagName === 'A' && elem?.href);
5347
4966
  }
5348
4967
 
5349
- let TransitionStatusDataAttributes = /*#__PURE__*/function (TransitionStatusDataAttributes) {
5350
- /**
5351
- * Present when the component begins animating in.
5352
- */
5353
- TransitionStatusDataAttributes["startingStyle"] = "data-starting-style";
5354
- /**
5355
- * Present when the component is animating out.
5356
- */
5357
- TransitionStatusDataAttributes["endingStyle"] = "data-ending-style";
5358
- return TransitionStatusDataAttributes;
5359
- }({});
5360
- const STARTING_HOOK = {
5361
- 'data-starting-style': ''
5362
- };
5363
- const ENDING_HOOK = {
5364
- 'data-ending-style': ''
5365
- };
5366
- const transitionStatusMapping = {
5367
- transitionStatus(value) {
5368
- if (value === 'starting') {
5369
- return STARTING_HOOK;
5370
- }
5371
- if (value === 'ending') {
5372
- return ENDING_HOOK;
5373
- }
5374
- return null;
5375
- }
5376
- };
5377
-
5378
4968
  let CommonPopupDataAttributes = function (CommonPopupDataAttributes) {
5379
4969
  /**
5380
4970
  * Present when the popup is open.
@@ -5385,7 +4975,7 @@ let CommonPopupDataAttributes = function (CommonPopupDataAttributes) {
5385
4975
  */
5386
4976
  CommonPopupDataAttributes["closed"] = "data-closed";
5387
4977
  /**
5388
- * Present when the popup begins animating in.
4978
+ * Present when the popup is animating in.
5389
4979
  */
5390
4980
  CommonPopupDataAttributes[CommonPopupDataAttributes["startingStyle"] = TransitionStatusDataAttributes.startingStyle] = "startingStyle";
5391
4981
  /**
@@ -5408,24 +4998,32 @@ let CommonPopupDataAttributes = function (CommonPopupDataAttributes) {
5408
4998
  CommonPopupDataAttributes["align"] = "data-align";
5409
4999
  return CommonPopupDataAttributes;
5410
5000
  }({});
5411
-
5412
- // Literal keys (instead of enum member references) keep the docs-only enums above
5413
- // tree-shakeable: a runtime reference would retain the whole enum IIFE in every bundle.
5001
+ let CommonTriggerDataAttributes = /*#__PURE__*/function (CommonTriggerDataAttributes) {
5002
+ /**
5003
+ * Present when the popup is open.
5004
+ */
5005
+ CommonTriggerDataAttributes["popupOpen"] = "data-popup-open";
5006
+ /**
5007
+ * Present when a pressable trigger is pressed.
5008
+ */
5009
+ CommonTriggerDataAttributes["pressed"] = "data-pressed";
5010
+ return CommonTriggerDataAttributes;
5011
+ }({});
5414
5012
  const TRIGGER_HOOK = {
5415
- 'data-popup-open': ''
5013
+ [CommonTriggerDataAttributes.popupOpen]: ''
5416
5014
  };
5417
5015
  const PRESSABLE_TRIGGER_HOOK = {
5418
- 'data-popup-open': '',
5419
- 'data-pressed': ''
5016
+ [CommonTriggerDataAttributes.popupOpen]: '',
5017
+ [CommonTriggerDataAttributes.pressed]: ''
5420
5018
  };
5421
5019
  const POPUP_OPEN_HOOK = {
5422
- 'data-open': ''
5020
+ [CommonPopupDataAttributes.open]: ''
5423
5021
  };
5424
5022
  const POPUP_CLOSED_HOOK = {
5425
- 'data-closed': ''
5023
+ [CommonPopupDataAttributes.closed]: ''
5426
5024
  };
5427
5025
  const ANCHOR_HIDDEN_HOOK = {
5428
- 'data-anchor-hidden': ''
5026
+ [CommonPopupDataAttributes.anchorHidden]: ''
5429
5027
  };
5430
5028
  const triggerOpenStateMapping = {
5431
5029
  open(value) {
@@ -5457,10 +5055,6 @@ const popupStateMapping = {
5457
5055
  return null;
5458
5056
  }
5459
5057
  };
5460
- const popupTransitionStateMapping = {
5461
- ...popupStateMapping,
5462
- ...transitionStatusMapping
5463
- };
5464
5058
 
5465
5059
  function inertValue(value) {
5466
5060
  if (useRenderElement.isReactVersionAtLeast(19)) {
@@ -5502,21 +5096,12 @@ if (process.env.NODE_ENV !== "production") InternalBackdrop.displayName = "Inter
5502
5096
  let originalHtmlStyles = {};
5503
5097
  let originalBodyStyles = {};
5504
5098
  let originalHtmlScrollBehavior = '';
5505
-
5506
- // The viewport's overflow comes from <html> when it establishes its own scroll container, and
5507
- // propagates from <body> otherwise. An `overflow` style on the other element doesn't lock the page.
5508
- function getViewportScroller(html, body) {
5509
- return isOverflowElement(html) ? html : body;
5510
- }
5511
- function isPageScrollLocked(win, html, body) {
5512
- return /hidden|clip/.test(win.getComputedStyle(getViewportScroller(html, body)).overflowY);
5513
- }
5514
5099
  function hasInsetScrollbars(referenceElement) {
5515
5100
  if (typeof document === 'undefined') {
5516
5101
  return false;
5517
5102
  }
5518
5103
  const doc = ownerDocument(referenceElement);
5519
- const win = getWindow(doc);
5104
+ const win = floatingUi_utils.getWindow(doc);
5520
5105
  return win.innerWidth - doc.documentElement.clientWidth > 0;
5521
5106
  }
5522
5107
  function supportsStableScrollbarGutter(referenceElement) {
@@ -5527,7 +5112,7 @@ function supportsStableScrollbarGutter(referenceElement) {
5527
5112
  const doc = ownerDocument(referenceElement);
5528
5113
  const html = doc.documentElement;
5529
5114
  const body = doc.body;
5530
- const scrollContainer = getViewportScroller(html, body);
5115
+ const scrollContainer = floatingUi_utils.isOverflowElement(html) ? html : body;
5531
5116
  const originalScrollContainerOverflowY = scrollContainer.style.overflowY;
5532
5117
  const originalHtmlStyleGutter = html.style.scrollbarGutter;
5533
5118
  html.style.scrollbarGutter = 'stable';
@@ -5548,7 +5133,7 @@ function preventScrollOverlayScrollbars(referenceElement) {
5548
5133
  // won't have any effect.
5549
5134
  // But if <body> has an `overflow` style (like `overflow-x: hidden`), we need to lock it
5550
5135
  // instead, as sticky elements shift otherwise.
5551
- const elementToLock = getViewportScroller(html, body);
5136
+ const elementToLock = floatingUi_utils.isOverflowElement(html) ? html : body;
5552
5137
  const originalElementToLockStyles = {
5553
5138
  overflowY: elementToLock.style.overflowY,
5554
5139
  overflowX: elementToLock.style.overflowX
@@ -5565,7 +5150,7 @@ function preventScrollInsetScrollbars(referenceElement) {
5565
5150
  const doc = ownerDocument(referenceElement);
5566
5151
  const html = doc.documentElement;
5567
5152
  const body = doc.body;
5568
- const win = getWindow(html);
5153
+ const win = floatingUi_utils.getWindow(html);
5569
5154
  let scrollTop = 0;
5570
5155
  let scrollLeft = 0;
5571
5156
  let updateGutterOnly = false;
@@ -5613,7 +5198,7 @@ function preventScrollInsetScrollbars(referenceElement) {
5613
5198
  // with whitespace. Warn if <body> has margins?
5614
5199
  const marginY = parseFloat(bodyStyles.marginTop) + parseFloat(bodyStyles.marginBottom);
5615
5200
  const marginX = parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight);
5616
- const elementToLock = getViewportScroller(html, body);
5201
+ const elementToLock = floatingUi_utils.isOverflowElement(html) ? html : body;
5617
5202
  updateGutterOnly = supportsStableScrollbarGutter(referenceElement);
5618
5203
 
5619
5204
  /*
@@ -5643,9 +5228,7 @@ function preventScrollInsetScrollbars(referenceElement) {
5643
5228
  height: marginY || scrollbarHeight ? `calc(100dvh - ${marginY + scrollbarHeight}px)` : '100dvh',
5644
5229
  width: marginX || scrollbarWidth ? `calc(100vw - ${marginX + scrollbarWidth}px)` : '100vw',
5645
5230
  boxSizing: 'border-box',
5646
- // Assign the longhands that `cleanup` restores, so nothing is left behind.
5647
- overflowY: 'hidden',
5648
- overflowX: 'hidden',
5231
+ overflow: 'hidden',
5649
5232
  scrollBehavior: 'unset'
5650
5233
  });
5651
5234
  body.scrollTop = scrollTop;
@@ -5710,30 +5293,11 @@ class ScrollLocker {
5710
5293
  }
5711
5294
  const doc = ownerDocument(referenceElement);
5712
5295
  const html = doc.documentElement;
5713
- const body = doc.body;
5714
- const win = getWindow(html);
5715
-
5716
- // The page is already locked, either by the site author or by a non-Base UI overlay that
5717
- // hasn't cleaned up yet. Leave it alone and wait for the lock to clear before taking over,
5718
- // otherwise we'd snapshot the locked state and restore it after our own lock is released.
5719
- if (isPageScrollLocked(win, html, body)) {
5720
- const observer = new win.MutationObserver(() => {
5721
- if (isPageScrollLocked(win, html, body)) {
5722
- return;
5723
- }
5724
- observer.disconnect();
5725
- this.restore = null;
5726
- this.lock(referenceElement);
5727
- });
5296
+ const htmlOverflowY = floatingUi_utils.getWindow(html).getComputedStyle(html).overflowY;
5728
5297
 
5729
- // Watch every attribute: locks are applied through inline styles, classes, or attributes
5730
- // paired with a stylesheet (`data-scroll-locked` in react-remove-scroll, for example).
5731
- const options = {
5732
- attributes: true
5733
- };
5734
- observer.observe(html, options);
5735
- observer.observe(body, options);
5736
- this.restore = () => observer.disconnect();
5298
+ // If the site author already hid overflow on <html>, respect it and bail out.
5299
+ if (htmlOverflowY === 'hidden' || htmlOverflowY === 'clip') {
5300
+ this.restore = useRenderElement.NOOP;
5737
5301
  return;
5738
5302
  }
5739
5303
  const hasOverlayScrollbars = ios || !hasInsetScrollbars(referenceElement);
@@ -5768,7 +5332,6 @@ exports.ARROW_DOWN = ARROW_DOWN;
5768
5332
  exports.ARROW_LEFT = ARROW_LEFT;
5769
5333
  exports.ARROW_RIGHT = ARROW_RIGHT;
5770
5334
  exports.ARROW_UP = ARROW_UP;
5771
- exports.AnimationFrame = AnimationFrame;
5772
5335
  exports.BASE_UI_SWIPE_IGNORE_SELECTOR = BASE_UI_SWIPE_IGNORE_SELECTOR;
5773
5336
  exports.CLICK_TRIGGER_IDENTIFIER = CLICK_TRIGGER_IDENTIFIER;
5774
5337
  exports.CommonPopupDataAttributes = CommonPopupDataAttributes;
@@ -5785,7 +5348,6 @@ exports.FocusGuard = FocusGuard;
5785
5348
  exports.InternalBackdrop = InternalBackdrop;
5786
5349
  exports.PATIENT_CLICK_THRESHOLD = PATIENT_CLICK_THRESHOLD;
5787
5350
  exports.POPUP_COLLISION_AVOIDANCE = POPUP_COLLISION_AVOIDANCE;
5788
- exports.PopupHandleAttachment = PopupHandleAttachment;
5789
5351
  exports.PopupTriggerMap = PopupTriggerMap;
5790
5352
  exports.ReactStore = ReactStore;
5791
5353
  exports.SafeReact = SafeReact;
@@ -5799,57 +5361,33 @@ exports.android = android;
5799
5361
  exports.attachPreventUnmountOnClose = attachPreventUnmountOnClose;
5800
5362
  exports.cancelOpen = cancelOpen;
5801
5363
  exports.chipRemovePress = chipRemovePress;
5802
- exports.clamp = clamp;
5803
5364
  exports.clearPress = clearPress;
5804
5365
  exports.closePress = closePress;
5805
5366
  exports.closeWatcher = closeWatcher;
5806
5367
  exports.contains = contains;
5807
5368
  exports.createAttribute = createAttribute;
5808
5369
  exports.createChangeEventDetails = createChangeEventDetails;
5809
- exports.createCoords = createCoords;
5810
5370
  exports.createDefaultInitialFocus = createDefaultInitialFocus;
5811
5371
  exports.createGenericEventDetails = createGenericEventDetails;
5372
+ exports.createSelector = createSelector;
5812
5373
  exports.decrementPress = decrementPress;
5813
- exports.dispatchClickWithModifiers = dispatchClickWithModifiers;
5814
5374
  exports.enqueueFocus = enqueueFocus;
5815
5375
  exports.error = error;
5816
5376
  exports.escapeKey = escapeKey;
5817
- exports.evaluate = evaluate;
5818
5377
  exports.fastComponent = fastComponent;
5819
5378
  exports.fastComponentRef = fastComponentRef;
5820
5379
  exports.findNonDisabledListIndex = findNonDisabledListIndex;
5821
- exports.floor = floor;
5822
5380
  exports.focusOut = focusOut;
5823
5381
  exports.gecko = gecko;
5824
- exports.getAlignment = getAlignment;
5825
- exports.getAlignmentAxis = getAlignmentAxis;
5826
- exports.getAlignmentSides = getAlignmentSides;
5827
- exports.getAxisLength = getAxisLength;
5828
- exports.getComputedStyle = getComputedStyle;
5829
- exports.getContainingBlock = getContainingBlock;
5830
- exports.getDocumentElement = getDocumentElement;
5831
- exports.getExpandedPlacements = getExpandedPlacements;
5832
5382
  exports.getFloatingFocusElement = getFloatingFocusElement;
5833
- exports.getFrameElement = getFrameElement;
5834
5383
  exports.getGridNavigatedIndex = getGridNavigatedIndex;
5835
5384
  exports.getMaxListIndex = getMaxListIndex;
5836
5385
  exports.getMinListIndex = getMinListIndex;
5837
5386
  exports.getNextTabbable = getNextTabbable;
5838
5387
  exports.getNodeChildren = getNodeChildren;
5839
- exports.getNodeName = getNodeName;
5840
- exports.getNodeScroll = getNodeScroll;
5841
- exports.getOppositeAxis = getOppositeAxis;
5842
- exports.getOppositeAxisPlacements = getOppositeAxisPlacements;
5843
- exports.getOppositePlacement = getOppositePlacement;
5844
- exports.getOverflowAncestors = getOverflowAncestors;
5845
- exports.getPaddingObject = getPaddingObject;
5846
- exports.getParentNode = getParentNode;
5847
- exports.getSide = getSide;
5848
- exports.getSideAxis = getSideAxis;
5849
5388
  exports.getTabbableAfterElement = getTabbableAfterElement;
5850
5389
  exports.getTabbableBeforeElement = getTabbableBeforeElement;
5851
5390
  exports.getTarget = getTarget;
5852
- exports.getWindow = getWindow;
5853
5391
  exports.imperativeAction = imperativeAction;
5854
5392
  exports.incrementPress = incrementPress;
5855
5393
  exports.inertValue = inertValue;
@@ -5859,46 +5397,32 @@ exports.inputClear = inputClear;
5859
5397
  exports.inputPaste = inputPaste;
5860
5398
  exports.inputPress = inputPress;
5861
5399
  exports.ios = ios;
5862
- exports.isContainingBlock = isContainingBlock;
5863
- exports.isElement = isElement;
5864
5400
  exports.isElementVisible = isElementVisible;
5865
- exports.isHTMLElement = isHTMLElement;
5866
5401
  exports.isIndexOutOfListBounds = isIndexOutOfListBounds;
5867
5402
  exports.isInteractiveElement = isInteractiveElement;
5868
- exports.isLastTraversableNode = isLastTraversableNode;
5869
5403
  exports.isListIndexDisabled = isListIndexDisabled;
5870
5404
  exports.isMouseLikePointerType = isMouseLikePointerType;
5871
5405
  exports.isOutsideEvent = isOutsideEvent;
5872
- exports.isOverflowElement = isOverflowElement;
5873
- exports.isTableElement = isTableElement;
5874
5406
  exports.isTargetInsideEnabledTrigger = isTargetInsideEnabledTrigger;
5875
- exports.isTopLayer = isTopLayer;
5876
5407
  exports.isTypeableCombobox = isTypeableCombobox;
5877
5408
  exports.isTypeableElement = isTypeableElement;
5878
5409
  exports.isVirtualClick = isVirtualClick;
5879
5410
  exports.isVirtualPointerEvent = isVirtualPointerEvent;
5880
- exports.isWebKit = isWebKit;
5881
5411
  exports.itemPress = itemPress;
5882
5412
  exports.jsdom = jsdom;
5883
5413
  exports.keyboard = keyboard;
5884
5414
  exports.listNavigation = listNavigation;
5885
5415
  exports.mac = mac;
5886
5416
  exports.matchesFocusVisible = matchesFocusVisible;
5887
- exports.max = max;
5888
5417
  exports.mergeCleanups = mergeCleanups;
5889
- exports.min = min;
5890
5418
  exports.none = none;
5891
5419
  exports.outsidePress = outsidePress;
5892
5420
  exports.ownerDocument = ownerDocument;
5893
5421
  exports.pointer = pointer;
5894
5422
  exports.popupStateMapping = popupStateMapping;
5895
- exports.popupTransitionStateMapping = popupTransitionStateMapping;
5896
5423
  exports.pressableTriggerOpenStateMapping = pressableTriggerOpenStateMapping;
5897
- exports.rectToClientRect = rectToClientRect;
5898
- exports.round = round;
5899
5424
  exports.scrub = scrub;
5900
5425
  exports.setPopupOpenState = setPopupOpenState;
5901
- exports.shimExports = shimExports;
5902
5426
  exports.siblingOpen = siblingOpen;
5903
5427
  exports.stopEvent = stopEvent;
5904
5428
  exports.swipe = swipe;
@@ -5921,15 +5445,17 @@ exports.useFloatingParentNodeId = useFloatingParentNodeId;
5921
5445
  exports.useFloatingTree = useFloatingTree;
5922
5446
  exports.useId = useId;
5923
5447
  exports.useImplicitActiveTrigger = useImplicitActiveTrigger;
5448
+ exports.useInitialOpenSync = useInitialOpenSync;
5924
5449
  exports.useIsoLayoutEffect = useIsoLayoutEffect;
5450
+ exports.useOnFirstRender = useOnFirstRender;
5925
5451
  exports.useOnMount = useOnMount;
5926
5452
  exports.useOpenChangeComplete = useOpenChangeComplete;
5927
5453
  exports.useOpenInteractionType = useOpenInteractionType;
5928
5454
  exports.useOpenMethodTriggerProps = useOpenMethodTriggerProps;
5929
5455
  exports.useOpenStateTransitions = useOpenStateTransitions;
5930
5456
  exports.usePopupInteractionProps = usePopupInteractionProps;
5931
- exports.usePopupRootStore = usePopupRootStore;
5932
5457
  exports.usePopupRootSync = usePopupRootSync;
5458
+ exports.usePopupStore = usePopupStore;
5933
5459
  exports.useScrollLock = useScrollLock;
5934
5460
  exports.useStableCallback = useStableCallback;
5935
5461
  exports.useStore = useStore;
@@ -5942,7 +5468,6 @@ exports.useValueAsRef = useValueAsRef;
5942
5468
  exports.useValueChanged = useValueChanged;
5943
5469
  exports.visuallyHidden = visuallyHidden;
5944
5470
  exports.visuallyHiddenInput = visuallyHiddenInput;
5945
- exports.voiceOver = voiceOver;
5946
5471
  exports.webkit = webkit;
5947
5472
  exports.wheel = wheel;
5948
5473
  exports.windowResize = windowResize;