@jobber/components 9.5.3 → 9.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/Combobox.d.ts +1 -0
  2. package/Combobox.js +17 -0
  3. package/dist/Autocomplete/index.cjs +0 -2
  4. package/dist/Autocomplete/index.mjs +0 -2
  5. package/dist/Autocomplete-cjs.js +4 -5
  6. package/dist/Autocomplete-es.js +1 -2
  7. package/dist/Card/index.cjs +2 -2
  8. package/dist/Card/index.mjs +2 -2
  9. package/dist/Chip/index.cjs +0 -2
  10. package/dist/Chip/index.mjs +0 -2
  11. package/dist/Chips/InternalChipDismissible/hooks/index.cjs +0 -2
  12. package/dist/Chips/InternalChipDismissible/hooks/index.mjs +0 -2
  13. package/dist/Chips/InternalChipDismissible/index.cjs +0 -2
  14. package/dist/Chips/InternalChipDismissible/index.mjs +0 -2
  15. package/dist/Chips/index.cjs +0 -2
  16. package/dist/Chips/index.mjs +0 -2
  17. package/dist/Combobox/Combobox.contentSlots.d.ts +5 -0
  18. package/dist/Combobox/Combobox.context.d.ts +34 -0
  19. package/dist/Combobox/Combobox.d.ts +69 -0
  20. package/dist/Combobox/Combobox.footer.d.ts +7 -0
  21. package/dist/Combobox/Combobox.items.d.ts +25 -0
  22. package/dist/Combobox/Combobox.responsive.d.ts +54 -0
  23. package/dist/Combobox/Combobox.selectAll.d.ts +4 -0
  24. package/dist/Combobox/Combobox.slotFactory.d.ts +7 -0
  25. package/dist/Combobox/Combobox.testUtils.d.ts +12 -0
  26. package/dist/Combobox/Combobox.types.d.ts +166 -0
  27. package/dist/Combobox/index.cjs +35 -0
  28. package/dist/Combobox/index.d.ts +2 -0
  29. package/dist/Combobox/index.mjs +29 -0
  30. package/dist/Combobox-cjs.js +675 -0
  31. package/dist/Combobox-es.js +673 -0
  32. package/dist/ComboboxPrimitive-cjs.js +88 -47
  33. package/dist/ComboboxPrimitive-es.js +39 -23
  34. package/dist/{ComboboxChipRemove-cjs.js → ComboboxSeparator-cjs.js} +501 -455
  35. package/dist/{ComboboxChipRemove-es.js → ComboboxSeparator-es.js} +500 -456
  36. package/dist/ConfirmationModal/index.cjs +0 -2
  37. package/dist/ConfirmationModal/index.mjs +0 -2
  38. package/dist/ContentBlock/index.cjs +1 -0
  39. package/dist/ContentBlock/index.mjs +1 -0
  40. package/dist/ContentBlock-cjs.js +2 -18
  41. package/dist/ContentBlock-es.js +1 -17
  42. package/dist/DataDump/index.cjs +2 -2
  43. package/dist/DataDump/index.mjs +2 -2
  44. package/dist/DataList/components/DataListActions/index.cjs +0 -2
  45. package/dist/DataList/components/DataListActions/index.mjs +0 -2
  46. package/dist/DataList/components/DataListBulkActions/index.cjs +0 -2
  47. package/dist/DataList/components/DataListBulkActions/index.mjs +0 -2
  48. package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +0 -2
  49. package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +0 -2
  50. package/dist/DataList/components/DataListFilters/index.cjs +0 -2
  51. package/dist/DataList/components/DataListFilters/index.mjs +0 -2
  52. package/dist/DataList/components/DataListHeader/index.cjs +0 -2
  53. package/dist/DataList/components/DataListHeader/index.mjs +0 -2
  54. package/dist/DataList/components/DataListItem/index.cjs +0 -2
  55. package/dist/DataList/components/DataListItem/index.mjs +0 -2
  56. package/dist/DataList/components/DataListItemActions/index.cjs +0 -2
  57. package/dist/DataList/components/DataListItemActions/index.mjs +0 -2
  58. package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +0 -2
  59. package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +0 -2
  60. package/dist/DataList/components/DataListItems/index.cjs +0 -2
  61. package/dist/DataList/components/DataListItems/index.mjs +0 -2
  62. package/dist/DataList/components/DataListLayout/index.cjs +0 -2
  63. package/dist/DataList/components/DataListLayout/index.mjs +0 -2
  64. package/dist/DataList/components/DataListLayoutActions/index.cjs +0 -2
  65. package/dist/DataList/components/DataListLayoutActions/index.mjs +0 -2
  66. package/dist/DataList/index.cjs +0 -2
  67. package/dist/DataList/index.mjs +0 -2
  68. package/dist/DatePicker/index.cjs +0 -2
  69. package/dist/DatePicker/index.mjs +0 -2
  70. package/dist/DatePicker-cjs.js +4 -5
  71. package/dist/DatePicker-es.js +1 -2
  72. package/dist/Dialog/index.cjs +2 -2
  73. package/dist/Dialog/index.mjs +2 -2
  74. package/dist/DrawerDescription-cjs.js +268 -99
  75. package/dist/DrawerDescription-es.js +270 -103
  76. package/dist/DrawerTitle-cjs.js +2 -6
  77. package/dist/DrawerTitle-es.js +3 -7
  78. package/dist/FieldDescription-cjs.js +184 -181
  79. package/dist/FieldDescription-es.js +187 -184
  80. package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +0 -2
  81. package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +0 -2
  82. package/dist/FilterPicker/components/FilterPickerContent/index.cjs +0 -2
  83. package/dist/FilterPicker/components/FilterPickerContent/index.mjs +0 -2
  84. package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +0 -2
  85. package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +0 -2
  86. package/dist/FilterPicker/index.cjs +0 -2
  87. package/dist/FilterPicker/index.mjs +0 -2
  88. package/dist/FilterPickerContent-cjs.js +4 -5
  89. package/dist/FilterPickerContent-es.js +1 -2
  90. package/dist/FormatFile/index.cjs +0 -2
  91. package/dist/FormatFile/index.mjs +0 -2
  92. package/dist/Gallery/index.cjs +0 -2
  93. package/dist/Gallery/index.mjs +0 -2
  94. package/dist/InputDate/index.cjs +0 -2
  95. package/dist/InputDate/index.mjs +0 -2
  96. package/dist/InputNumber/index.cjs +2 -2
  97. package/dist/InputNumber/index.mjs +2 -2
  98. package/dist/InputNumber/types.d.ts +5 -0
  99. package/dist/InputNumber-cjs.js +2 -2
  100. package/dist/InputNumber-es.js +2 -2
  101. package/dist/LightBox/index.cjs +0 -2
  102. package/dist/LightBox/index.mjs +0 -2
  103. package/dist/Menu/index.cjs +2 -2
  104. package/dist/Menu/index.mjs +2 -2
  105. package/dist/Menu-cjs.js +4 -5
  106. package/dist/Menu-es.js +1 -2
  107. package/dist/MenuSubmenuTrigger-cjs.js +206 -164
  108. package/dist/MenuSubmenuTrigger-es.js +194 -152
  109. package/dist/Modal/index.cjs +0 -2
  110. package/dist/Modal/index.mjs +1 -3
  111. package/dist/NumberFieldInput-cjs.js +187 -308
  112. package/dist/NumberFieldInput-es.js +187 -308
  113. package/dist/Page/index.cjs +2 -2
  114. package/dist/Page/index.mjs +2 -2
  115. package/dist/Popover/index.cjs +0 -2
  116. package/dist/Popover/index.mjs +0 -2
  117. package/dist/Popover-cjs.js +7 -8
  118. package/dist/Popover-es.js +1 -2
  119. package/dist/ScrollAreaViewport-cjs.js +747 -1093
  120. package/dist/ScrollAreaViewport-es.js +734 -1081
  121. package/dist/Select/index.cjs +2 -2
  122. package/dist/Select/index.mjs +2 -2
  123. package/dist/SelectGroupLabel-cjs.js +207 -306
  124. package/dist/SelectGroupLabel-es.js +203 -302
  125. package/dist/SelectPrimitive-cjs.js +11 -17
  126. package/dist/SelectPrimitive-es.js +1 -7
  127. package/dist/Tooltip/index.cjs +0 -2
  128. package/dist/Tooltip/index.mjs +0 -2
  129. package/dist/Tooltip-cjs.js +6 -7
  130. package/dist/Tooltip-es.js +1 -2
  131. package/dist/buttonRenderAdapter-cjs.js +2 -1
  132. package/dist/buttonRenderAdapter-es.js +2 -1
  133. package/dist/dialogReturnFocus-cjs.js +1 -1
  134. package/dist/dialogReturnFocus-es.js +2 -2
  135. package/dist/docs/InputNumber/InputNumber.md +2 -2
  136. package/dist/docs/SelectPrimitive/SelectPrimitive.md +1 -1
  137. package/dist/floating-ui.react-cjs.js +2557 -185
  138. package/dist/floating-ui.react-es.js +2512 -149
  139. package/dist/getMappedBreakpointWidth-cjs.js +21 -0
  140. package/dist/getMappedBreakpointWidth-es.js +18 -0
  141. package/dist/index.cjs +15 -10
  142. package/dist/index.d.mts +1 -0
  143. package/dist/index.d.ts +1 -0
  144. package/dist/index.mjs +14 -10
  145. package/dist/mergeClassName-cjs.js +12 -0
  146. package/dist/mergeClassName-es.js +10 -0
  147. package/dist/primitives/BottomSheet/index.cjs +1 -1
  148. package/dist/primitives/BottomSheet/index.mjs +1 -1
  149. package/dist/primitives/ComboboxPrimitive/ComboboxPrimitive.d.ts +2 -2
  150. package/dist/primitives/ComboboxPrimitive/index.cjs +4 -5
  151. package/dist/primitives/ComboboxPrimitive/index.mjs +4 -5
  152. package/dist/primitives/SelectPrimitive/index.cjs +1 -2
  153. package/dist/primitives/SelectPrimitive/index.mjs +1 -2
  154. package/dist/primitives/index.cjs +3 -3
  155. package/dist/primitives/index.mjs +3 -3
  156. package/dist/scrollEdges-cjs.js +1 -11
  157. package/dist/scrollEdges-es.js +1 -11
  158. package/dist/scrollable-cjs.js +58 -0
  159. package/dist/scrollable-es.js +54 -0
  160. package/dist/styles.css +759 -42
  161. package/dist/unstyledPrimitives/index.cjs +720 -478
  162. package/dist/unstyledPrimitives/index.mjs +663 -421
  163. package/dist/useCompositeListItem-cjs.js +2108 -361
  164. package/dist/useCompositeListItem-es.js +2076 -331
  165. package/dist/useLabel-cjs.js +2 -3
  166. package/dist/useLabel-es.js +2 -3
  167. package/dist/useRenderElement-cjs.js +9 -7
  168. package/dist/useRenderElement-es.js +9 -7
  169. package/dist/useScrollLock-cjs.js +819 -344
  170. package/dist/useScrollLock-es.js +732 -296
  171. package/dist/useScrollToActive-cjs.js +4 -5
  172. package/dist/useScrollToActive-es.js +1 -2
  173. package/dist/utils/meta/meta.json +43 -1
  174. package/package.json +8 -3
  175. package/dist/floating-ui.react-dom-cjs.js +0 -2103
  176. package/dist/floating-ui.react-dom-es.js +0 -2072
  177. package/dist/floating-ui.utils-cjs.js +0 -342
  178. package/dist/floating-ui.utils-es.js +0 -300
@@ -2,10 +2,9 @@
2
2
 
3
3
  var React = require('react');
4
4
  var useScrollLock = require('./useScrollLock-cjs.js');
5
- var floatingUi_utils = require('./floating-ui.utils-cjs.js');
6
5
  var useRenderElement = require('./useRenderElement-cjs.js');
7
6
  var jsxRuntime = require('react/jsx-runtime');
8
- var floatingUi_reactDom = require('./floating-ui.react-dom-cjs.js');
7
+ var ReactDOM = require('react-dom');
9
8
 
10
9
  function _interopNamespaceDefault(e) {
11
10
  var n = Object.create(null);
@@ -25,6 +24,1718 @@ function _interopNamespaceDefault(e) {
25
24
  }
26
25
 
27
26
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
27
+ var ReactDOM__namespace = /*#__PURE__*/_interopNamespaceDefault(ReactDOM);
28
+
29
+ function useOnFirstRender(fn) {
30
+ const ref = React__namespace.useRef(true);
31
+ if (ref.current) {
32
+ ref.current = false;
33
+ fn();
34
+ }
35
+ }
36
+
37
+ function computeCoordsFromPlacement(_ref, placement, rtl) {
38
+ let {
39
+ reference,
40
+ floating
41
+ } = _ref;
42
+ const sideAxis = useScrollLock.getSideAxis(placement);
43
+ const alignmentAxis = useScrollLock.getAlignmentAxis(placement);
44
+ const alignLength = useScrollLock.getAxisLength(alignmentAxis);
45
+ const side = useScrollLock.getSide(placement);
46
+ const isVertical = sideAxis === 'y';
47
+ const commonX = reference.x + reference.width / 2 - floating.width / 2;
48
+ const commonY = reference.y + reference.height / 2 - floating.height / 2;
49
+ const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;
50
+ let coords;
51
+ switch (side) {
52
+ case 'top':
53
+ coords = {
54
+ x: commonX,
55
+ y: reference.y - floating.height
56
+ };
57
+ break;
58
+ case 'bottom':
59
+ coords = {
60
+ x: commonX,
61
+ y: reference.y + reference.height
62
+ };
63
+ break;
64
+ case 'right':
65
+ coords = {
66
+ x: reference.x + reference.width,
67
+ y: commonY
68
+ };
69
+ break;
70
+ case 'left':
71
+ coords = {
72
+ x: reference.x - floating.width,
73
+ y: commonY
74
+ };
75
+ break;
76
+ default:
77
+ coords = {
78
+ x: reference.x,
79
+ y: reference.y
80
+ };
81
+ }
82
+ const alignment = useScrollLock.getAlignment(placement);
83
+ if (alignment) {
84
+ coords[alignmentAxis] += commonAlign * (alignment === 'end' ? 1 : -1) * (rtl && isVertical ? -1 : 1);
85
+ }
86
+ return coords;
87
+ }
88
+
89
+ /**
90
+ * Resolves with an object of overflow side offsets that determine how much the
91
+ * element is overflowing a given clipping boundary on each side.
92
+ * - positive = overflowing the boundary by that number of pixels
93
+ * - negative = how many pixels left before it will overflow
94
+ * - 0 = lies flush with the boundary
95
+ * @see https://floating-ui.com/docs/detectOverflow
96
+ */
97
+ async function detectOverflow(state, options) {
98
+ var _await$platform$isEle;
99
+ if (options === void 0) {
100
+ options = {};
101
+ }
102
+ const {
103
+ x,
104
+ y,
105
+ platform,
106
+ rects,
107
+ elements,
108
+ strategy
109
+ } = state;
110
+ const {
111
+ boundary = 'clippingAncestors',
112
+ rootBoundary = 'viewport',
113
+ elementContext = 'floating',
114
+ altBoundary = false,
115
+ padding = 0
116
+ } = useScrollLock.evaluate(options, state);
117
+ const paddingObject = useScrollLock.getPaddingObject(padding);
118
+ const altContext = elementContext === 'floating' ? 'reference' : 'floating';
119
+ const element = elements[altBoundary ? altContext : elementContext];
120
+ const clippingClientRect = useScrollLock.rectToClientRect(await platform.getClippingRect({
121
+ element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),
122
+ boundary,
123
+ rootBoundary,
124
+ strategy
125
+ }));
126
+ const rect = elementContext === 'floating' ? {
127
+ x,
128
+ y,
129
+ width: rects.floating.width,
130
+ height: rects.floating.height
131
+ } : rects.reference;
132
+ const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
133
+ const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) && (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
134
+ x: 1,
135
+ y: 1
136
+ };
137
+ const elementClientRect = useScrollLock.rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({
138
+ elements,
139
+ rect,
140
+ offsetParent,
141
+ strategy
142
+ }) : rect);
143
+ return {
144
+ top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,
145
+ bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,
146
+ left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,
147
+ right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x
148
+ };
149
+ }
150
+
151
+ // Maximum number of resets that can occur before bailing to avoid infinite reset loops.
152
+ const MAX_RESET_COUNT = 50;
153
+
154
+ /**
155
+ * Computes the `x` and `y` coordinates that will place the floating element
156
+ * next to a given reference element.
157
+ *
158
+ * This export does not have any `platform` interface logic. You will need to
159
+ * write one for the platform you are using Floating UI with.
160
+ */
161
+ const computePosition$1 = async (reference, floating, config) => {
162
+ const {
163
+ placement = 'bottom',
164
+ strategy = 'absolute',
165
+ middleware = [],
166
+ platform
167
+ } = config;
168
+ const platformWithDetectOverflow = platform.detectOverflow ? platform : {
169
+ ...platform,
170
+ detectOverflow
171
+ };
172
+ const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));
173
+ let rects = await platform.getElementRects({
174
+ reference,
175
+ floating,
176
+ strategy
177
+ });
178
+ let {
179
+ x,
180
+ y
181
+ } = computeCoordsFromPlacement(rects, placement, rtl);
182
+ let statefulPlacement = placement;
183
+ let resetCount = 0;
184
+ const middlewareData = {};
185
+ for (let i = 0; i < middleware.length; i++) {
186
+ const currentMiddleware = middleware[i];
187
+ if (!currentMiddleware) {
188
+ continue;
189
+ }
190
+ const {
191
+ name,
192
+ fn
193
+ } = currentMiddleware;
194
+ const {
195
+ x: nextX,
196
+ y: nextY,
197
+ data,
198
+ reset
199
+ } = await fn({
200
+ x,
201
+ y,
202
+ initialPlacement: placement,
203
+ placement: statefulPlacement,
204
+ strategy,
205
+ middlewareData,
206
+ rects,
207
+ platform: platformWithDetectOverflow,
208
+ elements: {
209
+ reference,
210
+ floating
211
+ }
212
+ });
213
+ x = nextX != null ? nextX : x;
214
+ y = nextY != null ? nextY : y;
215
+ middlewareData[name] = {
216
+ ...middlewareData[name],
217
+ ...data
218
+ };
219
+ if (reset && resetCount < MAX_RESET_COUNT) {
220
+ resetCount++;
221
+ if (typeof reset === 'object') {
222
+ if (reset.placement) {
223
+ statefulPlacement = reset.placement;
224
+ }
225
+ if (reset.rects) {
226
+ rects = reset.rects === true ? await platform.getElementRects({
227
+ reference,
228
+ floating,
229
+ strategy
230
+ }) : reset.rects;
231
+ }
232
+ ({
233
+ x,
234
+ y
235
+ } = computeCoordsFromPlacement(rects, statefulPlacement, rtl));
236
+ }
237
+ i = -1;
238
+ }
239
+ }
240
+ return {
241
+ x,
242
+ y,
243
+ placement: statefulPlacement,
244
+ strategy,
245
+ middlewareData
246
+ };
247
+ };
248
+
249
+ /**
250
+ * Optimizes the visibility of the floating element by flipping the `placement`
251
+ * in order to keep it in view when the preferred placement(s) will overflow the
252
+ * clipping boundary. Alternative to `autoPlacement`.
253
+ * @see https://floating-ui.com/docs/flip
254
+ */
255
+ const flip$2 = function (options) {
256
+ if (options === void 0) {
257
+ options = {};
258
+ }
259
+ return {
260
+ name: 'flip',
261
+ options,
262
+ async fn(state) {
263
+ var _middlewareData$arrow, _middlewareData$flip;
264
+ const {
265
+ placement,
266
+ middlewareData,
267
+ rects,
268
+ initialPlacement,
269
+ platform,
270
+ elements
271
+ } = state;
272
+ const {
273
+ mainAxis: checkMainAxis = true,
274
+ crossAxis: checkCrossAxis = true,
275
+ fallbackPlacements: specifiedFallbackPlacements,
276
+ fallbackStrategy = 'bestFit',
277
+ fallbackAxisSideDirection = 'none',
278
+ flipAlignment = true,
279
+ ...detectOverflowOptions
280
+ } = useScrollLock.evaluate(options, state);
281
+
282
+ // If a reset by the arrow was caused due to an alignment offset being
283
+ // added, we should skip any logic now since `flip()` has already done its
284
+ // work.
285
+ // https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643
286
+ if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
287
+ return {};
288
+ }
289
+ const side = useScrollLock.getSide(placement);
290
+ const initialSideAxis = useScrollLock.getSideAxis(initialPlacement);
291
+ const isBasePlacement = useScrollLock.getSide(initialPlacement) === initialPlacement;
292
+ const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
293
+ const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [useScrollLock.getOppositePlacement(initialPlacement)] : useScrollLock.getExpandedPlacements(initialPlacement));
294
+ const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== 'none';
295
+ if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) {
296
+ fallbackPlacements.push(...useScrollLock.getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));
297
+ }
298
+ const placements = [initialPlacement, ...fallbackPlacements];
299
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
300
+ const overflows = [];
301
+ let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];
302
+ if (checkMainAxis) {
303
+ overflows.push(overflow[side]);
304
+ }
305
+ if (checkCrossAxis) {
306
+ const sides = useScrollLock.getAlignmentSides(placement, rects, rtl);
307
+ overflows.push(overflow[sides[0]], overflow[sides[1]]);
308
+ }
309
+ overflowsData = [...overflowsData, {
310
+ placement,
311
+ overflows
312
+ }];
313
+
314
+ // One or more sides is overflowing.
315
+ if (!overflows.every(side => side <= 0)) {
316
+ var _middlewareData$flip2, _overflowsData$filter;
317
+ const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;
318
+ const nextPlacement = placements[nextIndex];
319
+ if (nextPlacement) {
320
+ const ignoreCrossAxisOverflow = checkCrossAxis === 'alignment' ? initialSideAxis !== useScrollLock.getSideAxis(nextPlacement) : false;
321
+ if (!ignoreCrossAxisOverflow ||
322
+ // We leave the current main axis only if every placement on that axis
323
+ // overflows the main axis.
324
+ overflowsData.every(d => useScrollLock.getSideAxis(d.placement) === initialSideAxis ? d.overflows[0] > 0 : true)) {
325
+ // Try next placement and re-run the lifecycle.
326
+ return {
327
+ data: {
328
+ index: nextIndex,
329
+ overflows: overflowsData
330
+ },
331
+ reset: {
332
+ placement: nextPlacement
333
+ }
334
+ };
335
+ }
336
+ }
337
+
338
+ // First, find the candidates that fit on the mainAxis side of overflow,
339
+ // then find the placement that fits the best on the main crossAxis side.
340
+ let resetPlacement = (_overflowsData$filter = overflowsData.filter(d => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;
341
+
342
+ // Otherwise fallback.
343
+ if (!resetPlacement) {
344
+ switch (fallbackStrategy) {
345
+ case 'bestFit':
346
+ {
347
+ var _overflowsData$filter2;
348
+ const placement = (_overflowsData$filter2 = overflowsData.filter(d => {
349
+ if (hasFallbackAxisSideDirection) {
350
+ const currentSideAxis = useScrollLock.getSideAxis(d.placement);
351
+ return currentSideAxis === initialSideAxis ||
352
+ // Create a bias to the `y` side axis due to horizontal
353
+ // reading directions favoring greater width.
354
+ currentSideAxis === 'y';
355
+ }
356
+ return true;
357
+ }).map(d => [d.placement, d.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0];
358
+ if (placement) {
359
+ resetPlacement = placement;
360
+ }
361
+ break;
362
+ }
363
+ case 'initialPlacement':
364
+ resetPlacement = initialPlacement;
365
+ break;
366
+ }
367
+ }
368
+ if (placement !== resetPlacement) {
369
+ return {
370
+ reset: {
371
+ placement: resetPlacement
372
+ }
373
+ };
374
+ }
375
+ }
376
+ return {};
377
+ }
378
+ };
379
+ };
380
+
381
+ const originSides = /*#__PURE__*/new Set(['left', 'top']);
382
+
383
+ // For type backwards-compatibility, the `OffsetOptions` type was also
384
+ // Derivable.
385
+
386
+ async function convertValueToCoords(state, options) {
387
+ const {
388
+ placement,
389
+ platform,
390
+ elements
391
+ } = state;
392
+ const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
393
+ const side = useScrollLock.getSide(placement);
394
+ const alignment = useScrollLock.getAlignment(placement);
395
+ const isVertical = useScrollLock.getSideAxis(placement) === 'y';
396
+ const mainAxisMulti = originSides.has(side) ? -1 : 1;
397
+ const crossAxisMulti = rtl && isVertical ? -1 : 1;
398
+ const rawValue = useScrollLock.evaluate(options, state);
399
+
400
+ // eslint-disable-next-line prefer-const
401
+ let {
402
+ mainAxis,
403
+ crossAxis,
404
+ alignmentAxis
405
+ } = typeof rawValue === 'number' ? {
406
+ mainAxis: rawValue,
407
+ crossAxis: 0,
408
+ alignmentAxis: null
409
+ } : {
410
+ mainAxis: rawValue.mainAxis || 0,
411
+ crossAxis: rawValue.crossAxis || 0,
412
+ alignmentAxis: rawValue.alignmentAxis
413
+ };
414
+ if (alignment && typeof alignmentAxis === 'number') {
415
+ crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis;
416
+ }
417
+ return isVertical ? {
418
+ x: crossAxis * crossAxisMulti,
419
+ y: mainAxis * mainAxisMulti
420
+ } : {
421
+ x: mainAxis * mainAxisMulti,
422
+ y: crossAxis * crossAxisMulti
423
+ };
424
+ }
425
+
426
+ /**
427
+ * Modifies the placement by translating the floating element along the
428
+ * specified axes.
429
+ * A number (shorthand for `mainAxis` or distance), or an axes configuration
430
+ * object may be passed.
431
+ * @see https://floating-ui.com/docs/offset
432
+ */
433
+ const offset$2 = function (options) {
434
+ if (options === void 0) {
435
+ options = 0;
436
+ }
437
+ return {
438
+ name: 'offset',
439
+ options,
440
+ async fn(state) {
441
+ var _middlewareData$offse, _middlewareData$arrow;
442
+ const {
443
+ x,
444
+ y,
445
+ placement,
446
+ middlewareData
447
+ } = state;
448
+ const diffCoords = await convertValueToCoords(state, options);
449
+
450
+ // If the placement is the same and the arrow caused an alignment offset
451
+ // then we don't need to change the positioning coordinates.
452
+ if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
453
+ return {};
454
+ }
455
+ return {
456
+ x: x + diffCoords.x,
457
+ y: y + diffCoords.y,
458
+ data: {
459
+ ...diffCoords,
460
+ placement
461
+ }
462
+ };
463
+ }
464
+ };
465
+ };
466
+
467
+ /**
468
+ * Optimizes the visibility of the floating element by shifting it in order to
469
+ * keep it in view when it will overflow the clipping boundary.
470
+ * @see https://floating-ui.com/docs/shift
471
+ */
472
+ const shift$2 = function (options) {
473
+ if (options === void 0) {
474
+ options = {};
475
+ }
476
+ return {
477
+ name: 'shift',
478
+ options,
479
+ async fn(state) {
480
+ const {
481
+ x,
482
+ y,
483
+ placement,
484
+ platform
485
+ } = state;
486
+ const {
487
+ mainAxis: checkMainAxis = true,
488
+ crossAxis: checkCrossAxis = false,
489
+ limiter = {
490
+ fn: _ref => {
491
+ let {
492
+ x,
493
+ y
494
+ } = _ref;
495
+ return {
496
+ x,
497
+ y
498
+ };
499
+ }
500
+ },
501
+ ...detectOverflowOptions
502
+ } = useScrollLock.evaluate(options, state);
503
+ const coords = {
504
+ x,
505
+ y
506
+ };
507
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
508
+ const crossAxis = useScrollLock.getSideAxis(placement);
509
+ const mainAxis = useScrollLock.getOppositeAxis(crossAxis);
510
+ let mainAxisCoord = coords[mainAxis];
511
+ let crossAxisCoord = coords[crossAxis];
512
+ const clampCoord = (axis, coord) => useScrollLock.clamp(coord + overflow[axis === 'y' ? 'top' : 'left'], coord, coord - overflow[axis === 'y' ? 'bottom' : 'right']);
513
+ if (checkMainAxis) {
514
+ mainAxisCoord = clampCoord(mainAxis, mainAxisCoord);
515
+ }
516
+ if (checkCrossAxis) {
517
+ crossAxisCoord = clampCoord(crossAxis, crossAxisCoord);
518
+ }
519
+ const limitedCoords = limiter.fn({
520
+ ...state,
521
+ [mainAxis]: mainAxisCoord,
522
+ [crossAxis]: crossAxisCoord
523
+ });
524
+ return {
525
+ ...limitedCoords,
526
+ data: {
527
+ x: limitedCoords.x - x,
528
+ y: limitedCoords.y - y,
529
+ enabled: {
530
+ [mainAxis]: checkMainAxis,
531
+ [crossAxis]: checkCrossAxis
532
+ }
533
+ }
534
+ };
535
+ }
536
+ };
537
+ };
538
+ /**
539
+ * Built-in `limiter` that will stop `shift()` at a certain point.
540
+ */
541
+ const limitShift$2 = function (options) {
542
+ if (options === void 0) {
543
+ options = {};
544
+ }
545
+ return {
546
+ options,
547
+ fn(state) {
548
+ var _rawOffset$mainAxis, _rawOffset$crossAxis;
549
+ const {
550
+ x,
551
+ y,
552
+ placement,
553
+ rects,
554
+ middlewareData
555
+ } = state;
556
+ const {
557
+ offset = 0,
558
+ mainAxis: checkMainAxis = true,
559
+ crossAxis: checkCrossAxis = true
560
+ } = useScrollLock.evaluate(options, state);
561
+ const coords = {
562
+ x,
563
+ y
564
+ };
565
+ const crossAxis = useScrollLock.getSideAxis(placement);
566
+ const mainAxis = useScrollLock.getOppositeAxis(crossAxis);
567
+ let mainAxisCoord = coords[mainAxis];
568
+ let crossAxisCoord = coords[crossAxis];
569
+ const rawOffset = useScrollLock.evaluate(offset, state);
570
+ const computedOffset = typeof rawOffset === 'number' ? {
571
+ mainAxis: rawOffset,
572
+ crossAxis: 0
573
+ } : {
574
+ mainAxis: (_rawOffset$mainAxis = rawOffset.mainAxis) != null ? _rawOffset$mainAxis : 0,
575
+ crossAxis: (_rawOffset$crossAxis = rawOffset.crossAxis) != null ? _rawOffset$crossAxis : 0
576
+ };
577
+ if (checkMainAxis) {
578
+ const len = mainAxis === 'y' ? 'height' : 'width';
579
+ const limitMin = rects.reference[mainAxis] - rects.floating[len] + computedOffset.mainAxis;
580
+ const limitMax = rects.reference[mainAxis] + rects.reference[len] - computedOffset.mainAxis;
581
+ if (mainAxisCoord < limitMin) {
582
+ mainAxisCoord = limitMin;
583
+ } else if (mainAxisCoord > limitMax) {
584
+ mainAxisCoord = limitMax;
585
+ }
586
+ }
587
+ if (checkCrossAxis) {
588
+ var _middlewareData$offse, _middlewareData$offse2;
589
+ const len = mainAxis === 'y' ? 'width' : 'height';
590
+ const isOriginSide = originSides.has(useScrollLock.getSide(placement));
591
+ const limitMin = rects.reference[crossAxis] - rects.floating[len] + (isOriginSide ? ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse[crossAxis]) || 0 : 0) + (isOriginSide ? 0 : computedOffset.crossAxis);
592
+ const limitMax = rects.reference[crossAxis] + rects.reference[len] + (isOriginSide ? 0 : ((_middlewareData$offse2 = middlewareData.offset) == null ? void 0 : _middlewareData$offse2[crossAxis]) || 0) - (isOriginSide ? computedOffset.crossAxis : 0);
593
+ if (crossAxisCoord < limitMin) {
594
+ crossAxisCoord = limitMin;
595
+ } else if (crossAxisCoord > limitMax) {
596
+ crossAxisCoord = limitMax;
597
+ }
598
+ }
599
+ return {
600
+ [mainAxis]: mainAxisCoord,
601
+ [crossAxis]: crossAxisCoord
602
+ };
603
+ }
604
+ };
605
+ };
606
+
607
+ // Method syntax keeps callback parameters bivariant, but expressing the
608
+ // explicit `| undefined` required by `exactOptionalPropertyTypes` needs
609
+ // property syntax, which is contravariant under `strictFunctionTypes`.
610
+ // Extracting the function from a method position restores that bivariance so
611
+ // consumers can still assign callbacks with narrower parameter types.
612
+
613
+ /**
614
+ * Provides data that allows you to change the size of the floating element —
615
+ * for instance, prevent it from overflowing the clipping boundary or match the
616
+ * width of the reference element.
617
+ * @see https://floating-ui.com/docs/size
618
+ */
619
+ const size$2 = function (options) {
620
+ if (options === void 0) {
621
+ options = {};
622
+ }
623
+ return {
624
+ name: 'size',
625
+ options,
626
+ async fn(state) {
627
+ const {
628
+ placement,
629
+ rects,
630
+ platform,
631
+ elements
632
+ } = state;
633
+ const {
634
+ apply = () => {},
635
+ ...detectOverflowOptions
636
+ } = useScrollLock.evaluate(options, state);
637
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
638
+ const side = useScrollLock.getSide(placement);
639
+ const alignment = useScrollLock.getAlignment(placement);
640
+ const isYAxis = useScrollLock.getSideAxis(placement) === 'y';
641
+ const {
642
+ width,
643
+ height
644
+ } = rects.floating;
645
+ let heightSide;
646
+ let widthSide;
647
+ if (side === 'top' || side === 'bottom') {
648
+ heightSide = side;
649
+ widthSide = alignment === ((await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating))) ? 'start' : 'end') ? 'left' : 'right';
650
+ } else {
651
+ widthSide = side;
652
+ heightSide = alignment === 'end' ? 'top' : 'bottom';
653
+ }
654
+ const maximumClippingHeight = height - overflow.top - overflow.bottom;
655
+ const maximumClippingWidth = width - overflow.left - overflow.right;
656
+ const overflowAvailableHeight = useScrollLock.min(height - overflow[heightSide], maximumClippingHeight);
657
+ const overflowAvailableWidth = useScrollLock.min(width - overflow[widthSide], maximumClippingWidth);
658
+ const shiftData = state.middlewareData.shift;
659
+ const noShift = !shiftData;
660
+ let availableHeight = overflowAvailableHeight;
661
+ let availableWidth = overflowAvailableWidth;
662
+ if (shiftData != null && shiftData.enabled.x) {
663
+ availableWidth = maximumClippingWidth;
664
+ }
665
+ if (shiftData != null && shiftData.enabled.y) {
666
+ availableHeight = maximumClippingHeight;
667
+ }
668
+ if (noShift && !alignment) {
669
+ if (isYAxis) {
670
+ availableWidth = width - 2 * useScrollLock.max(overflow.left, overflow.right);
671
+ } else {
672
+ availableHeight = height - 2 * useScrollLock.max(overflow.top, overflow.bottom);
673
+ }
674
+ }
675
+ await apply({
676
+ ...state,
677
+ availableWidth,
678
+ availableHeight
679
+ });
680
+ const nextDimensions = await platform.getDimensions(elements.floating);
681
+ if (width !== nextDimensions.width || height !== nextDimensions.height) {
682
+ return {
683
+ reset: {
684
+ rects: true
685
+ }
686
+ };
687
+ }
688
+ return {};
689
+ }
690
+ };
691
+ };
692
+
693
+ function getCssDimensions(element) {
694
+ const css = useScrollLock.getComputedStyle(element);
695
+ // In testing environments, the `width` and `height` properties are empty
696
+ // strings for SVG elements, returning NaN. Fallback to `0` in this case.
697
+ let width = parseFloat(css.width) || 0;
698
+ let height = parseFloat(css.height) || 0;
699
+ const hasOffset = useScrollLock.isHTMLElement(element);
700
+ const offsetWidth = hasOffset ? element.offsetWidth : width;
701
+ const offsetHeight = hasOffset ? element.offsetHeight : height;
702
+ const shouldFallback = useScrollLock.round(width) !== offsetWidth || useScrollLock.round(height) !== offsetHeight;
703
+ if (shouldFallback) {
704
+ width = offsetWidth;
705
+ height = offsetHeight;
706
+ }
707
+ return {
708
+ width,
709
+ height,
710
+ $: shouldFallback
711
+ };
712
+ }
713
+
714
+ function unwrapElement(element) {
715
+ return !useScrollLock.isElement(element) ? element.contextElement : element;
716
+ }
717
+
718
+ function getScale(element) {
719
+ const domElement = unwrapElement(element);
720
+ if (!useScrollLock.isHTMLElement(domElement)) {
721
+ return useScrollLock.createCoords(1);
722
+ }
723
+ const rect = domElement.getBoundingClientRect();
724
+ const {
725
+ width,
726
+ height,
727
+ $
728
+ } = getCssDimensions(domElement);
729
+ let x = ($ ? useScrollLock.round(rect.width) : rect.width) / width;
730
+ let y = ($ ? useScrollLock.round(rect.height) : rect.height) / height;
731
+
732
+ // 0, NaN, or Infinity should always fallback to 1.
733
+
734
+ if (!x || !Number.isFinite(x)) {
735
+ x = 1;
736
+ }
737
+ if (!y || !Number.isFinite(y)) {
738
+ y = 1;
739
+ }
740
+ return {
741
+ x,
742
+ y
743
+ };
744
+ }
745
+
746
+ const noOffsets = /*#__PURE__*/useScrollLock.createCoords(0);
747
+ function getVisualOffsets(element) {
748
+ const win = useScrollLock.getWindow(element);
749
+ if (!useScrollLock.isWebKit() || !win.visualViewport) {
750
+ return noOffsets;
751
+ }
752
+ return {
753
+ x: win.visualViewport.offsetLeft,
754
+ y: win.visualViewport.offsetTop
755
+ };
756
+ }
757
+ function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
758
+ if (isFixed === void 0) {
759
+ isFixed = false;
760
+ }
761
+ return !!floatingOffsetParent && isFixed && floatingOffsetParent === useScrollLock.getWindow(element);
762
+ }
763
+
764
+ function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
765
+ if (includeScale === void 0) {
766
+ includeScale = false;
767
+ }
768
+ if (isFixedStrategy === void 0) {
769
+ isFixedStrategy = false;
770
+ }
771
+ const clientRect = element.getBoundingClientRect();
772
+ const domElement = unwrapElement(element);
773
+ let scale = useScrollLock.createCoords(1);
774
+ if (includeScale) {
775
+ if (offsetParent) {
776
+ if (useScrollLock.isElement(offsetParent)) {
777
+ scale = getScale(offsetParent);
778
+ }
779
+ } else {
780
+ scale = getScale(element);
781
+ }
782
+ }
783
+ const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : useScrollLock.createCoords(0);
784
+ let x = (clientRect.left + visualOffsets.x) / scale.x;
785
+ let y = (clientRect.top + visualOffsets.y) / scale.y;
786
+ let width = clientRect.width / scale.x;
787
+ let height = clientRect.height / scale.y;
788
+ if (domElement && offsetParent) {
789
+ const win = useScrollLock.getWindow(domElement);
790
+ const offsetWin = useScrollLock.isElement(offsetParent) ? useScrollLock.getWindow(offsetParent) : offsetParent;
791
+ let currentWin = win;
792
+ let currentIFrame = useScrollLock.getFrameElement(currentWin);
793
+ while (currentIFrame && offsetWin !== currentWin) {
794
+ const iframeScale = getScale(currentIFrame);
795
+ const iframeRect = currentIFrame.getBoundingClientRect();
796
+ const css = useScrollLock.getComputedStyle(currentIFrame);
797
+ const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
798
+ const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
799
+ x *= iframeScale.x;
800
+ y *= iframeScale.y;
801
+ width *= iframeScale.x;
802
+ height *= iframeScale.y;
803
+ x += left;
804
+ y += top;
805
+ currentWin = useScrollLock.getWindow(currentIFrame);
806
+ currentIFrame = useScrollLock.getFrameElement(currentWin);
807
+ }
808
+ }
809
+ return useScrollLock.rectToClientRect({
810
+ width,
811
+ height,
812
+ x,
813
+ y
814
+ });
815
+ }
816
+
817
+ // If <html> has a CSS width greater than the viewport, then this will be
818
+ // incorrect for RTL.
819
+ function getWindowScrollBarX(element, rect) {
820
+ const leftScroll = useScrollLock.getNodeScroll(element).scrollLeft;
821
+ if (!rect) {
822
+ return getBoundingClientRect(useScrollLock.getDocumentElement(element)).left + leftScroll;
823
+ }
824
+ return rect.left + leftScroll;
825
+ }
826
+
827
+ function getHTMLOffset(documentElement, scroll) {
828
+ const htmlRect = documentElement.getBoundingClientRect();
829
+ const x = htmlRect.left + scroll.scrollLeft - getWindowScrollBarX(documentElement, htmlRect);
830
+ const y = htmlRect.top + scroll.scrollTop;
831
+ return {
832
+ x,
833
+ y
834
+ };
835
+ }
836
+
837
+ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
838
+ let {
839
+ elements,
840
+ rect,
841
+ offsetParent,
842
+ strategy
843
+ } = _ref;
844
+ const isFixed = strategy === 'fixed';
845
+ const documentElement = useScrollLock.getDocumentElement(offsetParent);
846
+ const topLayer = elements ? useScrollLock.isTopLayer(elements.floating) : false;
847
+ if (offsetParent === documentElement || topLayer && isFixed) {
848
+ return rect;
849
+ }
850
+ let scroll = {
851
+ scrollLeft: 0,
852
+ scrollTop: 0
853
+ };
854
+ let scale = useScrollLock.createCoords(1);
855
+ const offsets = useScrollLock.createCoords(0);
856
+ const isOffsetParentAnElement = useScrollLock.isHTMLElement(offsetParent);
857
+ if (isOffsetParentAnElement || !isFixed) {
858
+ if (useScrollLock.getNodeName(offsetParent) !== 'body' || useScrollLock.isOverflowElement(documentElement)) {
859
+ scroll = useScrollLock.getNodeScroll(offsetParent);
860
+ }
861
+ if (isOffsetParentAnElement) {
862
+ const offsetRect = getBoundingClientRect(offsetParent);
863
+ scale = getScale(offsetParent);
864
+ offsets.x = offsetRect.x + offsetParent.clientLeft;
865
+ offsets.y = offsetRect.y + offsetParent.clientTop;
866
+ }
867
+ }
868
+ const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : useScrollLock.createCoords(0);
869
+ return {
870
+ width: rect.width * scale.x,
871
+ height: rect.height * scale.y,
872
+ x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x,
873
+ y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y
874
+ };
875
+ }
876
+
877
+ function getClientRects(element) {
878
+ return element.getClientRects ? Array.from(element.getClientRects()) : [];
879
+ }
880
+
881
+ // Gets the entire size of the scrollable document area, even extending outside
882
+ // of the `<html>` and `<body>` rect bounds if horizontally scrollable.
883
+ function getDocumentRect(html) {
884
+ const scroll = useScrollLock.getNodeScroll(html);
885
+ const body = html.ownerDocument.body;
886
+ const width = useScrollLock.max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
887
+ const height = useScrollLock.max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
888
+ let x = -scroll.scrollLeft + getWindowScrollBarX(html);
889
+ const y = -scroll.scrollTop;
890
+ if (useScrollLock.getComputedStyle(body).direction === 'rtl') {
891
+ x += useScrollLock.max(html.clientWidth, body.clientWidth) - width;
892
+ }
893
+ return {
894
+ width,
895
+ height,
896
+ x,
897
+ y
898
+ };
899
+ }
900
+
901
+ // Safety check: ensure the scrollbar space is reasonable in case this
902
+ // calculation is affected by unusual styles.
903
+ // Most scrollbars leave 15-18px of space.
904
+ const SCROLLBAR_MAX = 25;
905
+ function getViewportRect(element, strategy, rootBoundary) {
906
+ if (rootBoundary === void 0) {
907
+ rootBoundary = 'viewport';
908
+ }
909
+ const isLayoutViewport = rootBoundary === 'layoutViewport';
910
+ const win = useScrollLock.getWindow(element);
911
+ const html = useScrollLock.getDocumentElement(element);
912
+ const visualViewport = win.visualViewport;
913
+ let width = html.clientWidth;
914
+ let height = html.clientHeight;
915
+ let x = 0;
916
+ let y = 0;
917
+ if (visualViewport) {
918
+ // Client coordinates are relative to the layout viewport, except in
919
+ // WebKit with an `absolute` strategy, where they are relative to the
920
+ // visual viewport.
921
+ const layoutRelativeClientCoords = !useScrollLock.isWebKit() || strategy === 'fixed';
922
+ if (isLayoutViewport) {
923
+ if (!layoutRelativeClientCoords) {
924
+ x = -visualViewport.offsetLeft;
925
+ y = -visualViewport.offsetTop;
926
+ }
927
+ } else {
928
+ width = visualViewport.width;
929
+ height = visualViewport.height;
930
+ if (layoutRelativeClientCoords) {
931
+ x = visualViewport.offsetLeft;
932
+ y = visualViewport.offsetTop;
933
+ }
934
+ }
935
+ }
936
+ const windowScrollbarX = getWindowScrollBarX(html);
937
+ // `scrollbar-gutter: stable` on the <html> reserves gutter space that shrinks
938
+ // the visual width but isn't reflected in `html.clientWidth`, so subtract it.
939
+ // Only the inline-end (right) gutter can hold the scrollbar; `both-edges` also
940
+ // reserves an empty inline-start gutter that clips nothing, so exclude just
941
+ // the one scrollbar-side gutter — halve the measured (two-gutter) total. A
942
+ // left-side scrollbar (`windowScrollbarX > 0`) is already handled by
943
+ // `getHTMLOffset`/`visualViewport.width`; skip it here.
944
+ if (windowScrollbarX <= 0) {
945
+ const doc = html.ownerDocument;
946
+ const body = doc.body;
947
+ const bodyStyles = getComputedStyle(body);
948
+ const bodyMarginInline = doc.compatMode === 'CSS1Compat' ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0;
949
+ const reservedWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);
950
+ const gutter = getComputedStyle(html).scrollbarGutter === 'stable both-edges' ? reservedWidth / 2 : reservedWidth;
951
+ if (gutter <= SCROLLBAR_MAX) {
952
+ width -= gutter;
953
+ }
954
+ }
955
+ return {
956
+ width,
957
+ height,
958
+ x,
959
+ y
960
+ };
961
+ }
962
+
963
+ // Returns the inner client rect, subtracting scrollbars if present.
964
+ function getInnerBoundingClientRect(element, strategy) {
965
+ const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
966
+ const top = clientRect.top + element.clientTop;
967
+ const left = clientRect.left + element.clientLeft;
968
+ const scale = getScale(element);
969
+ const width = element.clientWidth * scale.x;
970
+ const height = element.clientHeight * scale.y;
971
+ const x = left * scale.x;
972
+ const y = top * scale.y;
973
+ return {
974
+ width,
975
+ height,
976
+ x,
977
+ y
978
+ };
979
+ }
980
+ function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
981
+ let rect;
982
+ if (clippingAncestor === 'viewport' || clippingAncestor === 'layoutViewport') {
983
+ rect = getViewportRect(element, strategy, clippingAncestor);
984
+ } else if (clippingAncestor === 'document') {
985
+ rect = getDocumentRect(useScrollLock.getDocumentElement(element));
986
+ } else if (useScrollLock.isElement(clippingAncestor)) {
987
+ rect = getInnerBoundingClientRect(clippingAncestor, strategy);
988
+ } else {
989
+ const visualOffsets = getVisualOffsets(element);
990
+ rect = {
991
+ x: clippingAncestor.x - visualOffsets.x,
992
+ y: clippingAncestor.y - visualOffsets.y,
993
+ width: clippingAncestor.width,
994
+ height: clippingAncestor.height
995
+ };
996
+ }
997
+ return useScrollLock.rectToClientRect(rect);
998
+ }
999
+
1000
+ // A "clipping ancestor" is an `overflow` element with the characteristic of
1001
+ // clipping (or hiding) child elements. This returns all clipping ancestors
1002
+ // of the given element up the tree.
1003
+ function getClippingElementAncestors(element, cache) {
1004
+ const cachedResult = cache.get(element);
1005
+ if (cachedResult) {
1006
+ return cachedResult;
1007
+ }
1008
+ let result = useScrollLock.getOverflowAncestors(element, [], false).filter(el => useScrollLock.isElement(el) && useScrollLock.getNodeName(el) !== 'body');
1009
+ let lastKeptComputedStyle = null;
1010
+ const elementIsFixed = useScrollLock.getComputedStyle(element).position === 'fixed';
1011
+ let currentNode = elementIsFixed ? useScrollLock.getParentNode(element) : element;
1012
+
1013
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
1014
+ while (useScrollLock.isElement(currentNode) && !useScrollLock.isLastTraversableNode(currentNode)) {
1015
+ const computedStyle = useScrollLock.getComputedStyle(currentNode);
1016
+ const currentNodeIsContaining = useScrollLock.isContainingBlock(currentNode);
1017
+ // Position of the containing block chain below the current node. A fixed
1018
+ // element whose containing block hasn't been found yet is a fixed chain.
1019
+ const lastPosition = lastKeptComputedStyle ? lastKeptComputedStyle.position : elementIsFixed ? 'fixed' : '';
1020
+
1021
+ // A non-containing ancestor does not clip the element when the chain
1022
+ // below it escapes it: a fixed chain escapes all ancestors up to the
1023
+ // next containing block, an absolute chain escapes static ancestors.
1024
+ const shouldDropCurrentNode = !currentNodeIsContaining && (lastPosition === 'fixed' || lastPosition === 'absolute' && computedStyle.position === 'static');
1025
+ if (shouldDropCurrentNode) {
1026
+ // Drop non-containing blocks.
1027
+ result = result.filter(ancestor => ancestor !== currentNode);
1028
+ } else {
1029
+ // The kept node carries the chain position for the next iteration.
1030
+ lastKeptComputedStyle = computedStyle;
1031
+ }
1032
+ currentNode = useScrollLock.getParentNode(currentNode);
1033
+ }
1034
+ cache.set(element, result);
1035
+ return result;
1036
+ }
1037
+
1038
+ // Gets the maximum area that the element is visible in due to any number of
1039
+ // clipping ancestors.
1040
+ function getClippingRect(_ref) {
1041
+ let {
1042
+ element,
1043
+ boundary,
1044
+ rootBoundary,
1045
+ strategy
1046
+ } = _ref;
1047
+ const elementClippingAncestors = boundary === 'clippingAncestors' ? useScrollLock.isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary);
1048
+ const clippingAncestors = [...elementClippingAncestors, rootBoundary];
1049
+ const firstRect = getClientRectFromClippingAncestor(element, clippingAncestors[0], strategy);
1050
+ let top = firstRect.top;
1051
+ let right = firstRect.right;
1052
+ let bottom = firstRect.bottom;
1053
+ let left = firstRect.left;
1054
+ for (let i = 1; i < clippingAncestors.length; i++) {
1055
+ const rect = getClientRectFromClippingAncestor(element, clippingAncestors[i], strategy);
1056
+ top = useScrollLock.max(rect.top, top);
1057
+ right = useScrollLock.min(rect.right, right);
1058
+ bottom = useScrollLock.min(rect.bottom, bottom);
1059
+ left = useScrollLock.max(rect.left, left);
1060
+ }
1061
+ return {
1062
+ width: right - left,
1063
+ height: bottom - top,
1064
+ x: left,
1065
+ y: top
1066
+ };
1067
+ }
1068
+
1069
+ function getDimensions(element) {
1070
+ const {
1071
+ width,
1072
+ height
1073
+ } = getCssDimensions(element);
1074
+ return {
1075
+ width,
1076
+ height
1077
+ };
1078
+ }
1079
+
1080
+ function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
1081
+ const isOffsetParentAnElement = useScrollLock.isHTMLElement(offsetParent);
1082
+ const documentElement = useScrollLock.getDocumentElement(offsetParent);
1083
+ const isFixed = strategy === 'fixed';
1084
+ const rect = getBoundingClientRect(element, true, isFixed, offsetParent);
1085
+ let scroll = {
1086
+ scrollLeft: 0,
1087
+ scrollTop: 0
1088
+ };
1089
+ const offsets = useScrollLock.createCoords(0);
1090
+ if (isOffsetParentAnElement || !isFixed) {
1091
+ if (useScrollLock.getNodeName(offsetParent) !== 'body' || useScrollLock.isOverflowElement(documentElement)) {
1092
+ scroll = useScrollLock.getNodeScroll(offsetParent);
1093
+ }
1094
+ if (isOffsetParentAnElement) {
1095
+ const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
1096
+ offsets.x = offsetRect.x + offsetParent.clientLeft;
1097
+ offsets.y = offsetRect.y + offsetParent.clientTop;
1098
+ }
1099
+ }
1100
+
1101
+ // If the <body> scrollbar appears on the left (e.g. RTL systems). Use
1102
+ // Firefox with layout.scrollbar.side = 3 in about:config to test this.
1103
+ if (!isOffsetParentAnElement && documentElement) {
1104
+ offsets.x = getWindowScrollBarX(documentElement);
1105
+ }
1106
+ const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : useScrollLock.createCoords(0);
1107
+ const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;
1108
+ const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y;
1109
+ return {
1110
+ x,
1111
+ y,
1112
+ width: rect.width,
1113
+ height: rect.height
1114
+ };
1115
+ }
1116
+
1117
+ function isStaticPositioned(element) {
1118
+ return useScrollLock.getComputedStyle(element).position === 'static';
1119
+ }
1120
+
1121
+ function getTrueOffsetParent(element, polyfill) {
1122
+ if (!useScrollLock.isHTMLElement(element) || useScrollLock.getComputedStyle(element).position === 'fixed') {
1123
+ return null;
1124
+ }
1125
+ if (polyfill) {
1126
+ return polyfill(element);
1127
+ }
1128
+ let rawOffsetParent = element.offsetParent;
1129
+
1130
+ // Firefox returns the <html> element as the offsetParent if it's non-static,
1131
+ // while Chrome and Safari return the <body> element. The <body> element must
1132
+ // be used to perform the correct calculations even if the <html> element is
1133
+ // non-static.
1134
+ if (useScrollLock.getDocumentElement(element) === rawOffsetParent) {
1135
+ rawOffsetParent = rawOffsetParent.ownerDocument.body;
1136
+ }
1137
+ return rawOffsetParent;
1138
+ }
1139
+
1140
+ // Gets the closest ancestor positioned element. Handles some edge cases,
1141
+ // such as table ancestors and cross browser bugs.
1142
+ function getOffsetParent(element, polyfill) {
1143
+ const win = useScrollLock.getWindow(element);
1144
+ if (useScrollLock.isTopLayer(element)) {
1145
+ return win;
1146
+ }
1147
+ if (!useScrollLock.isHTMLElement(element)) {
1148
+ let svgOffsetParent = useScrollLock.getParentNode(element);
1149
+ while (svgOffsetParent && !useScrollLock.isLastTraversableNode(svgOffsetParent)) {
1150
+ if (useScrollLock.isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) {
1151
+ return svgOffsetParent;
1152
+ }
1153
+ svgOffsetParent = useScrollLock.getParentNode(svgOffsetParent);
1154
+ }
1155
+ return win;
1156
+ }
1157
+ let offsetParent = getTrueOffsetParent(element, polyfill);
1158
+ while (offsetParent && useScrollLock.isTableElement(offsetParent) && isStaticPositioned(offsetParent)) {
1159
+ offsetParent = getTrueOffsetParent(offsetParent, polyfill);
1160
+ }
1161
+ if (offsetParent && useScrollLock.isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !useScrollLock.isContainingBlock(offsetParent)) {
1162
+ return win;
1163
+ }
1164
+ return offsetParent || useScrollLock.getContainingBlock(element) || win;
1165
+ }
1166
+
1167
+ const getElementRects = async function (data) {
1168
+ const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
1169
+ const getDimensionsFn = this.getDimensions;
1170
+ const floatingDimensions = await getDimensionsFn(data.floating);
1171
+ return {
1172
+ reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),
1173
+ floating: {
1174
+ x: 0,
1175
+ y: 0,
1176
+ width: floatingDimensions.width,
1177
+ height: floatingDimensions.height
1178
+ }
1179
+ };
1180
+ };
1181
+
1182
+ function isRTL(element) {
1183
+ return useScrollLock.getComputedStyle(element).direction === 'rtl';
1184
+ }
1185
+
1186
+ const platform = {
1187
+ convertOffsetParentRelativeRectToViewportRelativeRect,
1188
+ getDocumentElement: useScrollLock.getDocumentElement,
1189
+ getClippingRect,
1190
+ getOffsetParent,
1191
+ getElementRects,
1192
+ getClientRects,
1193
+ getDimensions,
1194
+ getScale,
1195
+ isElement: useScrollLock.isElement,
1196
+ isRTL
1197
+ };
1198
+
1199
+ function rectsAreEqual(a, b) {
1200
+ return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
1201
+ }
1202
+
1203
+ // https://samthor.au/2021/observing-dom/
1204
+ function observeMove(element, onMove, ancestorResize) {
1205
+ let io = null;
1206
+ let timeoutId;
1207
+ const root = useScrollLock.getDocumentElement(element);
1208
+ function cleanup() {
1209
+ var _io;
1210
+ clearTimeout(timeoutId);
1211
+ (_io = io) == null || _io.disconnect();
1212
+ io = null;
1213
+ }
1214
+ function refresh(skip, threshold) {
1215
+ if (skip === void 0) {
1216
+ skip = false;
1217
+ }
1218
+ if (threshold === void 0) {
1219
+ threshold = 1;
1220
+ }
1221
+ cleanup();
1222
+ const elementRectForRootMargin = element.getBoundingClientRect();
1223
+ const {
1224
+ left,
1225
+ top,
1226
+ width,
1227
+ height
1228
+ } = elementRectForRootMargin;
1229
+ if (!skip) {
1230
+ onMove();
1231
+ }
1232
+ if (!width || !height) {
1233
+ return;
1234
+ }
1235
+ const insetTop = useScrollLock.floor(top);
1236
+ const insetRight = useScrollLock.floor(root.clientWidth - (left + width));
1237
+ const insetBottom = useScrollLock.floor(root.clientHeight - (top + height));
1238
+ const insetLeft = useScrollLock.floor(left);
1239
+ const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
1240
+ const options = {
1241
+ rootMargin,
1242
+ threshold: useScrollLock.max(0, useScrollLock.min(1, threshold)) || 1
1243
+ };
1244
+ let isFirstUpdate = true;
1245
+ function handleObserve(entries) {
1246
+ const ratio = entries[0].intersectionRatio;
1247
+
1248
+ // The entry is a snapshot, so the reference may have moved since the
1249
+ // intersection was computed (under performance constraints, or between
1250
+ // consecutive frames of a multi-frame layout shift). The reported ratio
1251
+ // and the observed area are stale in that case and cannot be trusted to
1252
+ // detect subsequent movement, so refresh regardless of the ratio.
1253
+ if (!rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
1254
+ return refresh();
1255
+ }
1256
+ if (ratio !== threshold) {
1257
+ if (!isFirstUpdate) {
1258
+ return refresh();
1259
+ }
1260
+ if (!ratio) {
1261
+ // If the reference is clipped in place, the ratio is 0. Throttle
1262
+ // the refresh to prevent an infinite loop of updates.
1263
+ timeoutId = setTimeout(() => {
1264
+ refresh(false, 1e-7);
1265
+ }, 1000);
1266
+ } else {
1267
+ refresh(false, ratio);
1268
+ }
1269
+ }
1270
+ isFirstUpdate = false;
1271
+ }
1272
+
1273
+ // Older browsers don't support a `document` as the root and will throw an
1274
+ // error.
1275
+ try {
1276
+ io = new IntersectionObserver(handleObserve, {
1277
+ ...options,
1278
+ // Handle <iframe>s
1279
+ root: root.ownerDocument
1280
+ });
1281
+ } catch (_e) {
1282
+ io = new IntersectionObserver(handleObserve, options);
1283
+ }
1284
+ io.observe(element);
1285
+ }
1286
+ const win = useScrollLock.getWindow(element);
1287
+ // The window is a resize ancestor, so when `ancestorResize` is enabled its
1288
+ // listener already runs the update on resize. Here we only need to rebuild
1289
+ // the `IntersectionObserver` for the new root size, skipping a redundant
1290
+ // update. When `ancestorResize` is disabled, this becomes the sole update.
1291
+ const handleResize = () => refresh(ancestorResize);
1292
+ win.addEventListener('resize', handleResize);
1293
+ refresh(true);
1294
+ return () => {
1295
+ win.removeEventListener('resize', handleResize);
1296
+ cleanup();
1297
+ };
1298
+ }
1299
+
1300
+ /**
1301
+ * Automatically updates the position of the floating element when necessary.
1302
+ * Should only be called when the floating element is mounted on the DOM or
1303
+ * visible on the screen.
1304
+ * @returns cleanup function that should be invoked when the floating element is
1305
+ * removed from the DOM or hidden from the screen.
1306
+ * @see https://floating-ui.com/docs/autoUpdate
1307
+ */
1308
+ function autoUpdate(reference, floating, update, options) {
1309
+ if (options === void 0) {
1310
+ options = {};
1311
+ }
1312
+ const {
1313
+ ancestorScroll = true,
1314
+ ancestorResize = true,
1315
+ elementResize = typeof ResizeObserver === 'function',
1316
+ layoutShift = typeof IntersectionObserver === 'function',
1317
+ animationFrame = false
1318
+ } = options;
1319
+ const referenceEl = unwrapElement(reference);
1320
+ const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? useScrollLock.getOverflowAncestors(referenceEl) : []), ...(floating ? useScrollLock.getOverflowAncestors(floating) : [])] : [];
1321
+ ancestors.forEach(ancestor => {
1322
+ ancestorScroll && ancestor.addEventListener('scroll', update);
1323
+ ancestorResize && ancestor.addEventListener('resize', update);
1324
+ });
1325
+ const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update, ancestorResize) : null;
1326
+ let reobserveFrame = -1;
1327
+ let resizeObserver = null;
1328
+ if (elementResize) {
1329
+ resizeObserver = new ResizeObserver(_ref => {
1330
+ let [firstEntry] = _ref;
1331
+ if (firstEntry && firstEntry.target === referenceEl && resizeObserver && floating) {
1332
+ // Prevent update loops when using the `size` middleware.
1333
+ // https://github.com/floating-ui/floating-ui/issues/1740
1334
+ resizeObserver.unobserve(floating);
1335
+ cancelAnimationFrame(reobserveFrame);
1336
+ reobserveFrame = requestAnimationFrame(() => {
1337
+ var _resizeObserver;
1338
+ (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);
1339
+ });
1340
+ }
1341
+ update();
1342
+ });
1343
+ if (referenceEl && !animationFrame) {
1344
+ resizeObserver.observe(referenceEl);
1345
+ }
1346
+ if (floating) {
1347
+ resizeObserver.observe(floating);
1348
+ }
1349
+ }
1350
+ let frameId;
1351
+ let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
1352
+ if (animationFrame) {
1353
+ frameLoop();
1354
+ }
1355
+ function frameLoop() {
1356
+ const nextRefRect = getBoundingClientRect(reference);
1357
+ if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) {
1358
+ update();
1359
+ }
1360
+ prevRefRect = nextRefRect;
1361
+ frameId = requestAnimationFrame(frameLoop);
1362
+ }
1363
+ update();
1364
+ return () => {
1365
+ var _resizeObserver2;
1366
+ ancestors.forEach(ancestor => {
1367
+ ancestorScroll && ancestor.removeEventListener('scroll', update);
1368
+ ancestorResize && ancestor.removeEventListener('resize', update);
1369
+ });
1370
+ cleanupIo == null || cleanupIo();
1371
+ (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();
1372
+ resizeObserver = null;
1373
+ if (animationFrame) {
1374
+ cancelAnimationFrame(frameId);
1375
+ }
1376
+ };
1377
+ }
1378
+
1379
+ /**
1380
+ * Modifies the placement by translating the floating element along the
1381
+ * specified axes.
1382
+ * A number (shorthand for `mainAxis` or distance), or an axes configuration
1383
+ * object may be passed.
1384
+ * @see https://floating-ui.com/docs/offset
1385
+ */
1386
+ const offset$1 = offset$2;
1387
+
1388
+ /**
1389
+ * Optimizes the visibility of the floating element by shifting it in order to
1390
+ * keep it in view when it will overflow the clipping boundary.
1391
+ * @see https://floating-ui.com/docs/shift
1392
+ */
1393
+ const shift$1 = shift$2;
1394
+
1395
+ /**
1396
+ * Optimizes the visibility of the floating element by flipping the `placement`
1397
+ * in order to keep it in view when the preferred placement(s) will overflow the
1398
+ * clipping boundary. Alternative to `autoPlacement`.
1399
+ * @see https://floating-ui.com/docs/flip
1400
+ */
1401
+ const flip$1 = flip$2;
1402
+
1403
+ /**
1404
+ * Provides data that allows you to change the size of the floating element —
1405
+ * for instance, prevent it from overflowing the clipping boundary or match the
1406
+ * width of the reference element.
1407
+ * @see https://floating-ui.com/docs/size
1408
+ */
1409
+ const size$1 = size$2;
1410
+
1411
+ /**
1412
+ * Built-in `limiter` that will stop `shift()` at a certain point.
1413
+ */
1414
+ const limitShift$1 = limitShift$2;
1415
+
1416
+ /**
1417
+ * Computes the `x` and `y` coordinates that will place the floating element
1418
+ * next to a given reference element.
1419
+ */
1420
+ const computePosition = (reference, floating, options) => {
1421
+ // This caches the expensive `getClippingElementAncestors` function so that
1422
+ // multiple lifecycle resets re-use the same result. It only lives for a
1423
+ // single call. If other functions become expensive, we can add them as well.
1424
+ const cache = new Map();
1425
+ const mergedOptions = options != null ? options : {};
1426
+ const platformWithCache = {
1427
+ ...platform,
1428
+ ...mergedOptions.platform,
1429
+ _c: cache
1430
+ };
1431
+ return computePosition$1(reference, floating, {
1432
+ ...mergedOptions,
1433
+ platform: platformWithCache
1434
+ });
1435
+ };
1436
+
1437
+ var isClient = typeof document !== 'undefined';
1438
+
1439
+ var noop = function noop() {};
1440
+ var index = isClient ? React.useLayoutEffect : noop;
1441
+
1442
+ // Fork of `fast-deep-equal` that only does the comparisons we need and compares
1443
+ // functions
1444
+ function deepEqual(a, b) {
1445
+ if (a === b) {
1446
+ return true;
1447
+ }
1448
+ if (typeof a !== typeof b) {
1449
+ return false;
1450
+ }
1451
+ if (typeof a === 'function' && a.toString() === b.toString()) {
1452
+ return true;
1453
+ }
1454
+ let length;
1455
+ let i;
1456
+ let keys;
1457
+ if (a && b && typeof a === 'object') {
1458
+ if (Array.isArray(a)) {
1459
+ length = a.length;
1460
+ if (length !== b.length) return false;
1461
+ for (i = length; i-- !== 0;) {
1462
+ if (!deepEqual(a[i], b[i])) {
1463
+ return false;
1464
+ }
1465
+ }
1466
+ return true;
1467
+ }
1468
+ keys = Object.keys(a);
1469
+ length = keys.length;
1470
+ if (length !== Object.keys(b).length) {
1471
+ return false;
1472
+ }
1473
+ for (i = length; i-- !== 0;) {
1474
+ if (!{}.hasOwnProperty.call(b, keys[i])) {
1475
+ return false;
1476
+ }
1477
+ }
1478
+ for (i = length; i-- !== 0;) {
1479
+ const key = keys[i];
1480
+ if (key === '_owner' && a.$$typeof) {
1481
+ continue;
1482
+ }
1483
+ if (!deepEqual(a[key], b[key])) {
1484
+ return false;
1485
+ }
1486
+ }
1487
+ return true;
1488
+ }
1489
+ return a !== a && b !== b;
1490
+ }
1491
+
1492
+ function getDPR(element) {
1493
+ if (typeof window === 'undefined') {
1494
+ return 1;
1495
+ }
1496
+ const win = element.ownerDocument.defaultView || window;
1497
+ return win.devicePixelRatio || 1;
1498
+ }
1499
+
1500
+ function roundByDPR(element, value) {
1501
+ const dpr = getDPR(element);
1502
+ return Math.round(value * dpr) / dpr;
1503
+ }
1504
+
1505
+ function useLatestRef(value) {
1506
+ const ref = React__namespace.useRef(value);
1507
+ index(() => {
1508
+ ref.current = value;
1509
+ });
1510
+ return ref;
1511
+ }
1512
+
1513
+ /**
1514
+ * Provides data to position a floating element.
1515
+ * @see https://floating-ui.com/docs/useFloating
1516
+ */
1517
+ function useFloating(options) {
1518
+ if (options === void 0) {
1519
+ options = {};
1520
+ }
1521
+ const {
1522
+ placement = 'bottom',
1523
+ strategy = 'absolute',
1524
+ middleware = [],
1525
+ platform,
1526
+ elements: {
1527
+ reference: externalReference,
1528
+ floating: externalFloating
1529
+ } = {},
1530
+ transform = true,
1531
+ whileElementsMounted,
1532
+ open
1533
+ } = options;
1534
+ const [data, setData] = React__namespace.useState({
1535
+ x: 0,
1536
+ y: 0,
1537
+ strategy,
1538
+ placement,
1539
+ middlewareData: {},
1540
+ isPositioned: false
1541
+ });
1542
+ const [latestMiddleware, setLatestMiddleware] = React__namespace.useState(middleware);
1543
+ if (!deepEqual(latestMiddleware, middleware)) {
1544
+ setLatestMiddleware(middleware);
1545
+ }
1546
+ const [_reference, _setReference] = React__namespace.useState(null);
1547
+ const [_floating, _setFloating] = React__namespace.useState(null);
1548
+ const setReference = React__namespace.useCallback(node => {
1549
+ if (node !== referenceRef.current) {
1550
+ referenceRef.current = node;
1551
+ _setReference(node);
1552
+ }
1553
+ }, []);
1554
+ const setFloating = React__namespace.useCallback(node => {
1555
+ if (node !== floatingRef.current) {
1556
+ floatingRef.current = node;
1557
+ _setFloating(node);
1558
+ }
1559
+ }, []);
1560
+ const referenceEl = externalReference || _reference;
1561
+ const floatingEl = externalFloating || _floating;
1562
+ const referenceRef = React__namespace.useRef(null);
1563
+ const floatingRef = React__namespace.useRef(null);
1564
+ const dataRef = React__namespace.useRef(data);
1565
+ const hasWhileElementsMounted = whileElementsMounted != null;
1566
+ const whileElementsMountedRef = useLatestRef(whileElementsMounted);
1567
+ const platformRef = useLatestRef(platform);
1568
+ const openRef = useLatestRef(open);
1569
+ const update = React__namespace.useCallback(() => {
1570
+ if (!referenceRef.current || !floatingRef.current) {
1571
+ return;
1572
+ }
1573
+ const config = {
1574
+ placement,
1575
+ strategy,
1576
+ middleware: latestMiddleware
1577
+ };
1578
+ if (platformRef.current) {
1579
+ config.platform = platformRef.current;
1580
+ }
1581
+ computePosition(referenceRef.current, floatingRef.current, config).then(data => {
1582
+ const fullData = {
1583
+ ...data,
1584
+ // The floating element's position may be recomputed while it's closed
1585
+ // but still mounted (such as when transitioning out). To ensure
1586
+ // `isPositioned` will be `false` initially on the next open, avoid
1587
+ // setting it to `true` when `open === false` (must be specified).
1588
+ isPositioned: openRef.current !== false
1589
+ };
1590
+ if (isMountedRef.current && !deepEqual(dataRef.current, fullData)) {
1591
+ dataRef.current = fullData;
1592
+ ReactDOM__namespace.flushSync(() => {
1593
+ setData(fullData);
1594
+ });
1595
+ }
1596
+ });
1597
+ }, [latestMiddleware, placement, strategy, platformRef, openRef]);
1598
+ index(() => {
1599
+ if (open === false && dataRef.current.isPositioned) {
1600
+ dataRef.current.isPositioned = false;
1601
+ setData(data => ({
1602
+ ...data,
1603
+ isPositioned: false
1604
+ }));
1605
+ }
1606
+ }, [open]);
1607
+ const isMountedRef = React__namespace.useRef(false);
1608
+ index(() => {
1609
+ isMountedRef.current = true;
1610
+ return () => {
1611
+ isMountedRef.current = false;
1612
+ };
1613
+ }, []);
1614
+ index(() => {
1615
+ if (referenceEl) referenceRef.current = referenceEl;
1616
+ if (floatingEl) floatingRef.current = floatingEl;
1617
+ if (referenceEl && floatingEl) {
1618
+ if (whileElementsMountedRef.current) {
1619
+ return whileElementsMountedRef.current(referenceEl, floatingEl, update);
1620
+ }
1621
+ update();
1622
+ }
1623
+ }, [referenceEl, floatingEl, update, whileElementsMountedRef, hasWhileElementsMounted]);
1624
+ const refs = React__namespace.useMemo(() => ({
1625
+ reference: referenceRef,
1626
+ floating: floatingRef,
1627
+ setReference,
1628
+ setFloating
1629
+ }), [setReference, setFloating]);
1630
+ const elements = React__namespace.useMemo(() => ({
1631
+ reference: referenceEl,
1632
+ floating: floatingEl
1633
+ }), [referenceEl, floatingEl]);
1634
+ const floatingStyles = React__namespace.useMemo(() => {
1635
+ const initialStyles = {
1636
+ position: strategy,
1637
+ left: 0,
1638
+ top: 0
1639
+ };
1640
+ if (!elements.floating) {
1641
+ return initialStyles;
1642
+ }
1643
+ const x = roundByDPR(elements.floating, data.x);
1644
+ const y = roundByDPR(elements.floating, data.y);
1645
+ if (transform) {
1646
+ return {
1647
+ ...initialStyles,
1648
+ transform: "translate(" + x + "px, " + y + "px)",
1649
+ ...(getDPR(elements.floating) >= 1.5 && {
1650
+ willChange: 'transform'
1651
+ })
1652
+ };
1653
+ }
1654
+ return {
1655
+ position: strategy,
1656
+ left: x,
1657
+ top: y
1658
+ };
1659
+ }, [strategy, transform, elements.floating, data.x, data.y]);
1660
+ return React__namespace.useMemo(() => ({
1661
+ ...data,
1662
+ update,
1663
+ refs,
1664
+ elements,
1665
+ floatingStyles
1666
+ }), [data, update, refs, elements, floatingStyles]);
1667
+ }
1668
+
1669
+ /**
1670
+ * Modifies the placement by translating the floating element along the
1671
+ * specified axes.
1672
+ * A number (shorthand for `mainAxis` or distance), or an axes configuration
1673
+ * object may be passed.
1674
+ * @see https://floating-ui.com/docs/offset
1675
+ */
1676
+ const offset = (options, deps) => {
1677
+ const result = offset$1(options);
1678
+ return {
1679
+ name: result.name,
1680
+ fn: result.fn,
1681
+ options: [options, deps]
1682
+ };
1683
+ };
1684
+
1685
+ /**
1686
+ * Optimizes the visibility of the floating element by shifting it in order to
1687
+ * keep it in view when it will overflow the clipping boundary.
1688
+ * @see https://floating-ui.com/docs/shift
1689
+ */
1690
+ const shift = (options, deps) => {
1691
+ const result = shift$1(options);
1692
+ return {
1693
+ name: result.name,
1694
+ fn: result.fn,
1695
+ options: [options, deps]
1696
+ };
1697
+ };
1698
+
1699
+ /**
1700
+ * Built-in `limiter` that will stop `shift()` at a certain point.
1701
+ */
1702
+ const limitShift = (options, deps) => {
1703
+ const result = limitShift$1(options);
1704
+ return {
1705
+ fn: result.fn,
1706
+ options: [options, deps]
1707
+ };
1708
+ };
1709
+
1710
+ /**
1711
+ * Optimizes the visibility of the floating element by flipping the `placement`
1712
+ * in order to keep it in view when the preferred placement(s) will overflow the
1713
+ * clipping boundary. Alternative to `autoPlacement`.
1714
+ * @see https://floating-ui.com/docs/flip
1715
+ */
1716
+ const flip = (options, deps) => {
1717
+ const result = flip$1(options);
1718
+ return {
1719
+ name: result.name,
1720
+ fn: result.fn,
1721
+ options: [options, deps]
1722
+ };
1723
+ };
1724
+
1725
+ /**
1726
+ * Provides data that allows you to change the size of the floating element —
1727
+ * for instance, prevent it from overflowing the clipping boundary or match the
1728
+ * width of the reference element.
1729
+ * @see https://floating-ui.com/docs/size
1730
+ */
1731
+ const size = (options, deps) => {
1732
+ const result = size$1(options);
1733
+ return {
1734
+ name: result.name,
1735
+ fn: result.fn,
1736
+ options: [options, deps]
1737
+ };
1738
+ };
28
1739
 
29
1740
  function useFloatingRootContext(options) {
30
1741
  const {
@@ -36,7 +1747,7 @@ function useFloatingRootContext(options) {
36
1747
  const nested = useScrollLock.useFloatingParentNodeId() != null;
37
1748
  if (process.env.NODE_ENV !== 'production') {
38
1749
  const optionDomReference = elements.reference;
39
- if (optionDomReference && !floatingUi_utils.isElement(optionDomReference)) {
1750
+ if (optionDomReference && !useScrollLock.isElement(optionDomReference)) {
40
1751
  console.error('Cannot pass a virtual element to the `elements.reference` option,', 'as it must be a real DOM element. Use `context.setPositionReference()`', 'instead.');
41
1752
  }
42
1753
  }
@@ -60,7 +1771,7 @@ function useFloatingRootContext(options) {
60
1771
  // Only sync elements that are defined to avoid overwriting existing ones
61
1772
  if (elements.reference !== undefined) {
62
1773
  valuesToSync.referenceElement = elements.reference;
63
- valuesToSync.domReferenceElement = floatingUi_utils.isElement(elements.reference) ? elements.reference : null;
1774
+ valuesToSync.domReferenceElement = useScrollLock.isElement(elements.reference) ? elements.reference : null;
64
1775
  }
65
1776
  if (elements.floating !== undefined) {
66
1777
  valuesToSync.floatingElement = elements.floating;
@@ -73,16 +1784,17 @@ function useFloatingRootContext(options) {
73
1784
  }
74
1785
 
75
1786
  /**
76
- * Provides data to position a floating element and context to add interactions.
77
- * @see https://floating-ui.com/docs/useFloating
1787
+ * Base UI's private `useFloating` path. The caller must supply the root store, so this skips the
1788
+ * internal root-context hook used by the public Floating UI-compatible API.
78
1789
  */
79
- function useFloating(options = {}) {
1790
+ function useBaseUIFloating(options) {
1791
+ return useFloatingWithStore(options, options.rootContext);
1792
+ }
1793
+ function useFloatingWithStore(options, store) {
80
1794
  const {
81
1795
  nodeId,
82
1796
  externalTree
83
1797
  } = options;
84
- const internalStore = useFloatingRootContext(options);
85
- const store = options.rootContext || internalStore;
86
1798
  const referenceElement = store.useState('referenceElement');
87
1799
  const floatingElement = store.useState('floatingElement');
88
1800
  const domReferenceElement = store.useState('domReferenceElement');
@@ -98,7 +1810,7 @@ function useFloating(options = {}) {
98
1810
  floating: floatingElement,
99
1811
  domReference: domReferenceElement
100
1812
  }), [referenceElement, floatingElement, domReferenceElement]);
101
- const position = floatingUi_reactDom.useFloating({
1813
+ const position = useFloating({
102
1814
  ...options,
103
1815
  elements: {
104
1816
  ...storeElements,
@@ -107,13 +1819,13 @@ function useFloating(options = {}) {
107
1819
  })
108
1820
  }
109
1821
  });
110
- const localDomReferenceElement = floatingUi_utils.isElement(localDomReference) ? localDomReference : null;
1822
+ const localDomReferenceElement = useScrollLock.isElement(localDomReference) ? localDomReference : null;
111
1823
  const syncedFloatingElement = localFloatingElement === undefined ? store.state.floatingElement : localFloatingElement;
112
1824
  store.useSyncedValue('referenceElement', localDomReference ?? null);
113
1825
  store.useSyncedValue('domReferenceElement', localDomReference === undefined ? domReferenceElement : localDomReferenceElement);
114
1826
  store.useSyncedValue('floatingElement', syncedFloatingElement);
115
1827
  const setPositionReference = React__namespace.useCallback(node => {
116
- const computedPositionReference = floatingUi_utils.isElement(node) ? {
1828
+ const computedPositionReference = useScrollLock.isElement(node) ? {
117
1829
  getBoundingClientRect: () => node.getBoundingClientRect(),
118
1830
  getClientRects: () => node.getClientRects(),
119
1831
  contextElement: node
@@ -124,18 +1836,18 @@ function useFloating(options = {}) {
124
1836
  position.refs.setReference(computedPositionReference);
125
1837
  }, [position.refs]);
126
1838
  const setReference = React__namespace.useCallback(node => {
127
- if (floatingUi_utils.isElement(node) || node === null) {
1839
+ if (useScrollLock.isElement(node) || node === null) {
128
1840
  domReferenceRef.current = node;
129
1841
  setLocalDomReference(node);
130
1842
  }
131
1843
 
132
1844
  // Backwards-compatibility for passing a virtual element to `reference`
133
1845
  // after it has set the DOM reference.
134
- if (floatingUi_utils.isElement(position.refs.reference.current) || position.refs.reference.current === null ||
1846
+ if (useScrollLock.isElement(position.refs.reference.current) || position.refs.reference.current === null ||
135
1847
  // Don't allow setting virtual elements using the old technique back to
136
1848
  // `null` to support `positionReference` + an unstable `reference`
137
1849
  // callback ref.
138
- node !== null && !floatingUi_utils.isElement(node)) {
1850
+ node !== null && !useScrollLock.isElement(node)) {
139
1851
  position.refs.setReference(node);
140
1852
  }
141
1853
  }, [position.refs, setLocalDomReference]);
@@ -188,6 +1900,13 @@ function useFloating(options = {}) {
188
1900
  }
189
1901
 
190
1902
  const ESCAPE = 'Escape';
1903
+
1904
+ // WebKit fires zero-delta `mousemove`/`pointermove` events when the list scrolls
1905
+ // beneath a stationary pointer, moving the highlight during keyboard navigation.
1906
+ // https://github.com/mui/base-ui/issues/4002
1907
+ function isStationaryWebKitPointer(event) {
1908
+ return useScrollLock.webkit && event.movementX === 0 && event.movementY === 0;
1909
+ }
191
1910
  function doSwitch(orientation, vertical, horizontal) {
192
1911
  switch (orientation) {
193
1912
  case 'vertical':
@@ -484,7 +2203,7 @@ function useListNavigation(context, props) {
484
2203
  useScrollLock.stopEvent(event);
485
2204
  }
486
2205
  store.setOpen(false, useScrollLock.createChangeEventDetails(useScrollLock.listNavigation, event.nativeEvent));
487
- if (floatingUi_utils.isHTMLElement(domReferenceElement)) {
2206
+ if (useScrollLock.isHTMLElement(domReferenceElement)) {
488
2207
  if (virtual) {
489
2208
  tree?.events.emit('virtualfocus', domReferenceElement);
490
2209
  } else {
@@ -594,6 +2313,9 @@ function useListNavigation(context, props) {
594
2313
  }),
595
2314
  // Safari
596
2315
  onMouseMove(event) {
2316
+ if (isStationaryWebKitPointer(event)) {
2317
+ return;
2318
+ }
597
2319
  forceSyncFocusRef.current = true;
598
2320
  forceScrollIntoViewRef.current = false;
599
2321
  if (focusItemOnHover) {
@@ -650,14 +2372,17 @@ function useListNavigation(context, props) {
650
2372
  }
651
2373
  useScrollLock.stopEvent(event);
652
2374
  store.setOpen(false, useScrollLock.createChangeEventDetails(useScrollLock.focusOut, event.nativeEvent));
653
- if (floatingUi_utils.isHTMLElement(domReferenceElement)) {
2375
+ if (useScrollLock.isHTMLElement(domReferenceElement)) {
654
2376
  domReferenceElement.focus();
655
2377
  }
656
2378
  return;
657
2379
  }
658
2380
  commonOnKeyDown(event);
659
2381
  },
660
- onPointerMove() {
2382
+ onPointerMove(event) {
2383
+ if (isStationaryWebKitPointer(event)) {
2384
+ return;
2385
+ }
661
2386
  isPointerModalityRef.current = true;
662
2387
  }
663
2388
  };
@@ -778,18 +2503,19 @@ function useTypeahead(context, props) {
778
2503
  const prevIndexRef = React__namespace.useRef(selectedIndex ?? activeIndex ?? -1);
779
2504
  const matchIndexRef = React__namespace.useRef(null);
780
2505
  const onKeyDown = useScrollLock.useStableCallback(event => {
781
- function isVisible(index) {
782
- const element = elementsRef?.current[index];
783
- return !element || useScrollLock.isElementVisible(element);
2506
+ function getElement(index) {
2507
+ return elementsRef?.current[index];
784
2508
  }
785
2509
  function isItemAvailable(index) {
786
- if (!isVisible(index)) {
2510
+ const element = getElement(index);
2511
+ if (element && !useScrollLock.isElementVisible(element) || element?.matches(':disabled')) {
787
2512
  return false;
788
2513
  }
789
- // Visibility is handled above; pass an empty element list so `isListIndexDisabled`
790
- // resolves only the explicit `disabledIndices` (array/predicate) and skips its own
791
- // visibility/attribute fallbacks. Consumers that don't opt in keep matching every
792
- // visible item.
2514
+ // Visibility and native disabled state are handled above; pass an empty
2515
+ // element list so `isListIndexDisabled` resolves only the explicit
2516
+ // `disabledIndices` (array/predicate) and skips its own fallbacks.
2517
+ // Consumers that don't pass `disabledIndices` keep matching every visible
2518
+ // item except native disabled elements provided through `elementsRef`.
793
2519
  return disabledIndices == null || !useScrollLock.isListIndexDisabled(useRenderElement.EMPTY_ARRAY, index, disabledIndices);
794
2520
  }
795
2521
  function getMatchingIndex(list, string, startIndex = 0) {
@@ -897,12 +2623,6 @@ function useTypeahead(context, props) {
897
2623
  stringRef.current = '';
898
2624
  }
899
2625
  }, [open, selectedIndex, timeout]);
900
- useScrollLock.useIsoLayoutEffect(() => {
901
- // Sync arrow key navigation but not typeahead navigation.
902
- if (open && stringRef.current === '') {
903
- prevIndexRef.current = selectedIndex ?? activeIndex ?? -1;
904
- }
905
- }, [open, selectedIndex, activeIndex]);
906
2626
  const sharedProps = React__namespace.useMemo(() => ({
907
2627
  onKeyDown,
908
2628
  onBlur
@@ -942,6 +2662,12 @@ function findItemIndex(itemValues, selectedValue, comparer) {
942
2662
  return compareItemEquality(itemValue, selectedValue, comparer);
943
2663
  });
944
2664
  }
2665
+ function findSelectionIndex(itemValues, selectedValue, comparer, multiple) {
2666
+ // Only unwrap in multiple mode: an array can itself be a valid single-select value.
2667
+ const lastValue = multiple && Array.isArray(selectedValue) ? selectedValue[selectedValue.length - 1] : selectedValue;
2668
+ const index = findItemIndex(itemValues, lastValue, comparer);
2669
+ return index === -1 ? null : index;
2670
+ }
945
2671
  function removeItem(selectedValues, itemValue, comparer) {
946
2672
  return selectedValues.filter(selectedValue => !compareItemEquality(itemValue, selectedValue, comparer));
947
2673
  }
@@ -1064,38 +2790,6 @@ function resolveMultipleLabels(values, items, itemToStringLabel) {
1064
2790
  }, []);
1065
2791
  }
1066
2792
 
1067
- let FieldControlDataAttributes = /*#__PURE__*/function (FieldControlDataAttributes) {
1068
- /**
1069
- * Present when the field is disabled.
1070
- */
1071
- FieldControlDataAttributes["disabled"] = "data-disabled";
1072
- /**
1073
- * Present when the field is in a valid state.
1074
- */
1075
- FieldControlDataAttributes["valid"] = "data-valid";
1076
- /**
1077
- * Present when the field is in an invalid state.
1078
- */
1079
- FieldControlDataAttributes["invalid"] = "data-invalid";
1080
- /**
1081
- * Present when the field has been touched.
1082
- */
1083
- FieldControlDataAttributes["touched"] = "data-touched";
1084
- /**
1085
- * Present when the field's value has changed.
1086
- */
1087
- FieldControlDataAttributes["dirty"] = "data-dirty";
1088
- /**
1089
- * Present when the field is filled.
1090
- */
1091
- FieldControlDataAttributes["filled"] = "data-filled";
1092
- /**
1093
- * Present when the field control is focused.
1094
- */
1095
- FieldControlDataAttributes["focused"] = "data-focused";
1096
- return FieldControlDataAttributes;
1097
- }({});
1098
-
1099
2793
  const DEFAULT_VALIDITY_STATE = {
1100
2794
  badInput: false,
1101
2795
  customError: false,
@@ -1127,11 +2821,11 @@ const fieldValidityMapping = {
1127
2821
  }
1128
2822
  if (value) {
1129
2823
  return {
1130
- [FieldControlDataAttributes.valid]: ''
2824
+ 'data-valid': ''
1131
2825
  };
1132
2826
  }
1133
2827
  return {
1134
- [FieldControlDataAttributes.invalid]: ''
2828
+ 'data-invalid': ''
1135
2829
  };
1136
2830
  }
1137
2831
  };
@@ -1148,29 +2842,22 @@ const DEFAULT_FIELD_ROOT_CONTEXT = {
1148
2842
  },
1149
2843
  setValidityData: useRenderElement.NOOP,
1150
2844
  disabled: undefined,
1151
- touched: DEFAULT_FIELD_STATE_ATTRIBUTES.touched,
1152
2845
  setTouched: useRenderElement.NOOP,
1153
- dirty: DEFAULT_FIELD_STATE_ATTRIBUTES.dirty,
1154
2846
  setDirty: useRenderElement.NOOP,
1155
- filled: DEFAULT_FIELD_STATE_ATTRIBUTES.filled,
1156
2847
  setFilled: useRenderElement.NOOP,
1157
- focused: DEFAULT_FIELD_STATE_ATTRIBUTES.focused,
1158
2848
  setFocused: useRenderElement.NOOP,
1159
- validate: () => null,
1160
2849
  validationMode: 'onSubmit',
1161
- validationDebounceTime: 0,
1162
2850
  shouldValidateOnChange: () => false,
1163
2851
  state: DEFAULT_FIELD_ROOT_STATE,
1164
- markedDirtyRef: {
1165
- current: false
1166
- },
1167
2852
  registerFieldControl: useRenderElement.NOOP,
1168
2853
  validation: {
1169
2854
  getValidationProps: (_disabled, props = useRenderElement.EMPTY_OBJECT) => props,
1170
2855
  inputRef: {
1171
2856
  current: null
1172
2857
  },
2858
+ registeredInputs: new Map(),
1173
2859
  registerInput: useRenderElement.NOOP,
2860
+ getInputControl: () => null,
1174
2861
  commit: async () => {},
1175
2862
  change: useRenderElement.NOOP
1176
2863
  }
@@ -1189,14 +2876,16 @@ function useRegisterFieldControl(controlRef, id, value, getFormValueOverride, en
1189
2876
  const {
1190
2877
  registerFieldControl
1191
2878
  } = useFieldRootContext();
1192
- const sourceRef = React__namespace.useRef(null);
1193
- if (!sourceRef.current) {
1194
- sourceRef.current = Symbol();
1195
- }
2879
+ const sourceRef = useRenderElement.useRefWithInit(() => Symbol());
2880
+
2881
+ // Re-register without unregistering first: re-registration with the same id updates the
2882
+ // form's fields Map entry in place, while a delete + re-add would move the field to the
2883
+ // end of the Map every time its value changes.
1196
2884
  useScrollLock.useIsoLayoutEffect(() => {
1197
2885
  const source = sourceRef.current;
1198
- if (!source || !enabled) {
1199
- return undefined;
2886
+ if (!enabled) {
2887
+ registerFieldControl(source, undefined);
2888
+ return;
1200
2889
  }
1201
2890
  const registration = {
1202
2891
  controlRef,
@@ -1206,13 +2895,19 @@ function useRegisterFieldControl(controlRef, id, value, getFormValueOverride, en
1206
2895
  value
1207
2896
  };
1208
2897
  registerFieldControl(source, registration);
2898
+ }, [controlRef, enabled, getFormValueOverride, id, name, registerFieldControl, sourceRef, value]);
2899
+ useScrollLock.useIsoLayoutEffect(() => {
2900
+ const source = sourceRef.current;
1209
2901
  return () => {
1210
2902
  registerFieldControl(source, undefined);
1211
2903
  };
1212
- }, [controlRef, enabled, getFormValueOverride, id, name, registerFieldControl, value]);
2904
+ }, [registerFieldControl, sourceRef]);
1213
2905
  }
1214
2906
 
1215
2907
  const FormContext = /*#__PURE__*/React__namespace.createContext({
2908
+ elementRef: {
2909
+ current: null
2910
+ },
1216
2911
  formRef: {
1217
2912
  current: {
1218
2913
  fields: new Map()
@@ -1260,7 +2955,7 @@ function useLabelableId(params = {}) {
1260
2955
  } = useLabelableContext();
1261
2956
  const defaultId = useScrollLock.useBaseUiId(id);
1262
2957
  const controlIdForEffect = implicit ? controlId : undefined;
1263
- const controlSourceRef = useRenderElement.useRefWithInit(() => Symbol('labelable-control'));
2958
+ const controlSourceRef = useRenderElement.useRefWithInit(() => Symbol());
1264
2959
  const hasRegisteredRef = React__namespace.useRef(false);
1265
2960
  const hadExplicitIdRef = React__namespace.useRef(id != null);
1266
2961
  const unregisterControlId = useScrollLock.useStableCallback(() => {
@@ -1277,7 +2972,7 @@ function useLabelableId(params = {}) {
1277
2972
  let nextId;
1278
2973
  if (implicit) {
1279
2974
  const elem = controlRef?.current;
1280
- if (floatingUi_utils.isElement(elem) && elem.closest('label') != null) {
2975
+ if (useScrollLock.isElement(elem) && elem.closest('label') != null) {
1281
2976
  nextId = id ?? null;
1282
2977
  } else {
1283
2978
  nextId = controlIdForEffect ?? defaultId;
@@ -1309,9 +3004,22 @@ function areArraysEqual(array1, array2, itemComparer = (a, b) => a === b) {
1309
3004
  return array1.length === array2.length && array1.every((value, index) => itemComparer(value, array2[index]));
1310
3005
  }
1311
3006
 
3007
+ // Tolerance around the element bounds so a fast click whose pointer drifts slightly
3008
+ // during press-release isn't mistaken for a drag-off-and-release cancellation.
3009
+ // Matches typical OS/browser drag-initiation thresholds.
3010
+ const BOUNDARY_OFFSET = 5;
3011
+
3012
+ /**
3013
+ * Determines if a mouse event occurred within the bounds of an element
3014
+ * (including its pseudo-elements), with a small tolerance for pointer drift.
3015
+ */
3016
+ function isMouseWithinBounds(event, element) {
3017
+ const bounds = getPseudoElementBounds(element);
3018
+ return event.clientX >= bounds.left - BOUNDARY_OFFSET && event.clientX <= bounds.right + BOUNDARY_OFFSET && event.clientY >= bounds.top - BOUNDARY_OFFSET && event.clientY <= bounds.bottom + BOUNDARY_OFFSET;
3019
+ }
1312
3020
  function getPseudoElementBounds(element) {
1313
3021
  const elementRect = element.getBoundingClientRect();
1314
- const win = floatingUi_utils.getWindow(element);
3022
+ const win = useScrollLock.getWindow(element);
1315
3023
 
1316
3024
  // Avoid "Not implemented: window.getComputedStyle(elt, pseudoElt)" in jsdom.
1317
3025
  if (useScrollLock.jsdom) {
@@ -1355,12 +3063,7 @@ function resolveAriaLabelledBy(fieldLabelId, localLabelId) {
1355
3063
  const CompositeListContext = /*#__PURE__*/React__namespace.createContext({
1356
3064
  register: () => {},
1357
3065
  unregister: () => {},
1358
- subscribeMapChange: () => {
1359
- return () => {};
1360
- },
1361
- elementsRef: {
1362
- current: []
1363
- },
3066
+ subscribeMapChange: () => () => {},
1364
3067
  nextIndexRef: {
1365
3068
  current: 0
1366
3069
  }
@@ -1373,7 +3076,6 @@ function useCompositeListContext() {
1373
3076
  /* eslint-disable no-bitwise */
1374
3077
  /**
1375
3078
  * Provides context for a list of items in a composite component.
1376
- * @internal
1377
3079
  */
1378
3080
  function CompositeList(props) {
1379
3081
  const {
@@ -1383,114 +3085,146 @@ function CompositeList(props) {
1383
3085
  onMapChange: onMapChangeProp
1384
3086
  } = props;
1385
3087
  const onMapChange = useScrollLock.useStableCallback(onMapChangeProp);
1386
- const nextIndexRef = React__namespace.useRef(0);
3088
+ const [, setMapTick] = React__namespace.useState(false);
1387
3089
  const listeners = useRenderElement.useRefWithInit(createListeners).current;
1388
-
1389
- // We use a stable `map` to avoid O(n^2) re-allocation costs for large lists.
1390
- // `mapTick` is our re-render trigger mechanism. We also need to update the
1391
- // elements and label refs, but there's a lot of async work going on and sometimes
1392
- // the effect that handles `onMapChange` gets called after those refs have been
1393
- // filled, and we don't want to lose those values by setting their lengths to `0`.
1394
- // We also need to have them at the proper length because floating-ui uses that
1395
- // information for list navigation.
1396
-
1397
3090
  const map = useRenderElement.useRefWithInit(createMap).current;
1398
- // `mapTick` uses a counter rather than objects for low precision-loss risk and better memory efficiency
1399
- const [mapTick, setMapTick] = React__namespace.useState(0);
1400
- const lastTickRef = React__namespace.useRef(mapTick);
1401
- const register = useScrollLock.useStableCallback((node, metadata) => {
1402
- map.set(node, metadata ?? null);
1403
- lastTickRef.current += 1;
1404
- setMapTick(lastTickRef.current);
3091
+ const nextIndexRef = React__namespace.useRef(0);
3092
+ const isDirtyRef = React__namespace.useRef(true);
3093
+ const itemsRef = React__namespace.useRef([]);
3094
+ const mutationObserverRef = React__namespace.useRef(null);
3095
+
3096
+ // Item effects can run without their parent rendering. Schedule one synchronous
3097
+ // parent update for the whole commit so refs are rebuilt before paint and while
3098
+ // the originating React event is still inside `act()` in tests.
3099
+ const scheduleMapUpdate = useScrollLock.useStableCallback(() => {
3100
+ if (isDirtyRef.current) {
3101
+ return;
3102
+ }
3103
+ isDirtyRef.current = true;
3104
+ setMapTick(tick => !tick);
3105
+ });
3106
+ const register = useScrollLock.useStableCallback((node, registration) => {
3107
+ map.set(node, registration);
3108
+ scheduleMapUpdate();
1405
3109
  });
1406
3110
  const unregister = useScrollLock.useStableCallback(node => {
1407
3111
  map.delete(node);
1408
- lastTickRef.current += 1;
1409
- setMapTick(lastTickRef.current);
3112
+ scheduleMapUpdate();
1410
3113
  });
1411
- const sortedMap = React__namespace.useMemo(() => {
1412
- const newMap = new Map();
1413
- // Filter out disconnected elements before sorting to avoid inconsistent
1414
- // compareDocumentPosition results when elements are detached from the DOM.
1415
- const sortedNodes = Array.from(map.keys()).filter(node => node.isConnected).sort(sortByDocumentPosition);
1416
- sortedNodes.forEach((node, index) => {
1417
- const metadata = map.get(node) ?? {};
1418
- newMap.set(node, {
1419
- ...metadata,
1420
- index
3114
+ const syncRefs = useScrollLock.useStableCallback(items => {
3115
+ const nextMap = new Map();
3116
+ elementsRef.current.length = 0;
3117
+ if (labelsRef) {
3118
+ labelsRef.current.length = 0;
3119
+ }
3120
+ items.forEach(item => {
3121
+ nextMap.set(item.element, {
3122
+ ...(item.registration.metadata ?? {}),
3123
+ index: item.index
1421
3124
  });
3125
+ elementsRef.current[item.index] = item.element;
3126
+ if (labelsRef) {
3127
+ labelsRef.current[item.index] = item.registration.label !== undefined ? item.registration.label : item.registration.textRef?.current?.textContent ?? item.element.textContent;
3128
+ }
1422
3129
  });
1423
- return newMap;
1424
- }, [map, mapTick]);
1425
- useScrollLock.useIsoLayoutEffect(() => {
1426
- if (typeof MutationObserver !== 'function' || sortedMap.size === 0) {
1427
- return undefined;
3130
+ nextIndexRef.current = elementsRef.current.length;
3131
+ return nextMap;
3132
+ });
3133
+ function observe(sortedNodes) {
3134
+ mutationObserverRef.current?.disconnect();
3135
+ mutationObserverRef.current = null;
3136
+
3137
+ // A single item can't reorder.
3138
+ if (typeof MutationObserver !== 'function' || sortedNodes.length < 2) {
3139
+ return;
1428
3140
  }
1429
3141
  const mutationObserver = new MutationObserver(entries => {
1430
- const diff = new Set();
1431
- const updateDiff = node => diff.has(node) ? diff.delete(node) : diff.add(node);
1432
- entries.forEach(entry => {
1433
- entry.removedNodes.forEach(updateDiff);
1434
- entry.addedNodes.forEach(updateDiff);
1435
- });
1436
- if (diff.size === 0) {
1437
- lastTickRef.current += 1;
1438
- setMapTick(lastTickRef.current);
3142
+ // Only verify the order after a move: a node that was removed and later
3143
+ // re-added within the same batch. Additions and removals alone can't
3144
+ // change the relative order of the remaining items, and items that mount
3145
+ // or unmount re-sort through `register`/`unregister`.
3146
+ if (!hasMovedNode(entries)) {
3147
+ return;
1439
3148
  }
1440
- });
1441
- sortedMap.forEach((_, node) => {
1442
- if (node.parentElement) {
1443
- mutationObserver.observe(node.parentElement, {
1444
- childList: true
1445
- });
3149
+ let previousConnectedNode = null;
3150
+
3151
+ // If any connected node now appears before the previous connected node,
3152
+ // wrappers/items moved and the index map needs to be rebuilt.
3153
+ for (const node of sortedNodes) {
3154
+ if (!node.isConnected) {
3155
+ continue;
3156
+ }
3157
+ if (previousConnectedNode && sortByDocumentPosition(previousConnectedNode, node) > 0) {
3158
+ mutationObserver.disconnect();
3159
+ scheduleMapUpdate();
3160
+ return;
3161
+ }
3162
+ previousConnectedNode = node;
1446
3163
  }
1447
3164
  });
1448
- return () => {
1449
- mutationObserver.disconnect();
1450
- };
1451
- }, [sortedMap]);
1452
- useScrollLock.useIsoLayoutEffect(() => {
1453
- const shouldUpdateLengths = lastTickRef.current === mapTick;
1454
- if (shouldUpdateLengths) {
1455
- if (elementsRef.current.length !== sortedMap.size) {
1456
- elementsRef.current.length = sortedMap.size;
3165
+ mutationObserverRef.current = mutationObserver;
3166
+
3167
+ // A reorder that changes item indexes must invert at least one adjacent pair
3168
+ // from the previous sorted order. Observing each pair's common parent catches
3169
+ // both direct item moves and ancestor wrapper moves at the boundary.
3170
+ const roots = new Set();
3171
+ for (let i = 1; i < sortedNodes.length; i += 1) {
3172
+ const root = getCommonAncestor(sortedNodes[i - 1], sortedNodes[i]);
3173
+ if (root) {
3174
+ roots.add(root);
1457
3175
  }
1458
- if (labelsRef && labelsRef.current.length !== sortedMap.size) {
1459
- labelsRef.current.length = sortedMap.size;
1460
- }
1461
- nextIndexRef.current = sortedMap.size;
1462
3176
  }
1463
- onMapChange(sortedMap);
1464
- }, [onMapChange, sortedMap, elementsRef, labelsRef, mapTick]);
3177
+ roots.forEach(root => mutationObserver.observe(root, {
3178
+ childList: true
3179
+ }));
3180
+ }
3181
+ const flush = useScrollLock.useStableCallback(() => {
3182
+ const [items, automaticNodes] = getCompositeListSnapshot(map);
3183
+ const nextMap = syncRefs(items);
3184
+ observe(automaticNodes);
3185
+ itemsRef.current = items;
3186
+ isDirtyRef.current = false;
3187
+ listeners.forEach(listener => listener(nextMap));
3188
+ onMapChange(nextMap);
3189
+ });
1465
3190
  useScrollLock.useIsoLayoutEffect(() => {
3191
+ // Re-copy the last committed snapshot when the ref objects change or Strict Mode replays
3192
+ // effects without reattaching callback refs.
3193
+ if (!isDirtyRef.current) {
3194
+ syncRefs(itemsRef.current);
3195
+ }
1466
3196
  return () => {
1467
3197
  elementsRef.current = [];
1468
- };
1469
- }, [elementsRef]);
1470
- useScrollLock.useIsoLayoutEffect(() => {
1471
- return () => {
1472
3198
  if (labelsRef) {
1473
3199
  labelsRef.current = [];
1474
3200
  }
1475
3201
  };
1476
- }, [labelsRef]);
3202
+ }, [elementsRef, labelsRef, syncRefs]);
3203
+ useScrollLock.useIsoLayoutEffect(() => {
3204
+ if (isDirtyRef.current) {
3205
+ flush();
3206
+ }
3207
+ });
3208
+ useScrollLock.useIsoLayoutEffect(() => {
3209
+ return () => {
3210
+ mutationObserverRef.current?.disconnect();
3211
+ // React 18 Strict Mode replays effects without replaying callback refs.
3212
+ // Mark the retained map dirty so the replay rebuilds refs and observation.
3213
+ isDirtyRef.current = true;
3214
+ };
3215
+ }, []);
1477
3216
  const subscribeMapChange = useScrollLock.useStableCallback(fn => {
1478
3217
  listeners.add(fn);
1479
3218
  return () => {
1480
3219
  listeners.delete(fn);
1481
3220
  };
1482
3221
  });
1483
- useScrollLock.useIsoLayoutEffect(() => {
1484
- listeners.forEach(l => l(sortedMap));
1485
- }, [listeners, sortedMap]);
1486
3222
  const contextValue = React__namespace.useMemo(() => ({
1487
3223
  register,
1488
3224
  unregister,
1489
3225
  subscribeMapChange,
1490
- elementsRef,
1491
- labelsRef,
1492
3226
  nextIndexRef
1493
- }), [register, unregister, subscribeMapChange, elementsRef, labelsRef, nextIndexRef]);
3227
+ }), [register, unregister, subscribeMapChange, nextIndexRef]);
1494
3228
  return /*#__PURE__*/jsxRuntime.jsx(CompositeListContext.Provider, {
1495
3229
  value: contextValue,
1496
3230
  children: children
@@ -1502,15 +3236,66 @@ function createMap() {
1502
3236
  function createListeners() {
1503
3237
  return new Set();
1504
3238
  }
1505
- function sortByDocumentPosition(a, b) {
1506
- const position = a.compareDocumentPosition(b);
1507
- if (position & Node.DOCUMENT_POSITION_FOLLOWING || position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
1508
- return -1;
3239
+ function getCompositeListSnapshot(map) {
3240
+ const reservedIndices = new Set();
3241
+ const items = [];
3242
+ const automaticItems = [];
3243
+ map.forEach((registration, node) => {
3244
+ if (!node.isConnected) {
3245
+ return;
3246
+ }
3247
+ const index = registration.index;
3248
+ const item = {
3249
+ index: index ?? -1,
3250
+ element: node,
3251
+ registration
3252
+ };
3253
+ if (index === null) {
3254
+ automaticItems.push(item);
3255
+ } else if (index >= 0) {
3256
+ reservedIndices.add(index);
3257
+ items.push(item);
3258
+ }
3259
+ });
3260
+ let nextAutomaticIndex = 0;
3261
+ automaticItems.sort((a, b) => sortByDocumentPosition(a.element, b.element));
3262
+ automaticItems.forEach(item => {
3263
+ while (reservedIndices.has(nextAutomaticIndex)) {
3264
+ nextAutomaticIndex += 1;
3265
+ }
3266
+ item.index = nextAutomaticIndex;
3267
+ items.push(item);
3268
+ nextAutomaticIndex += 1;
3269
+ });
3270
+ if (reservedIndices.size > 0) {
3271
+ items.sort((a, b) => a.index - b.index);
1509
3272
  }
1510
- if (position & Node.DOCUMENT_POSITION_PRECEDING || position & Node.DOCUMENT_POSITION_CONTAINS) {
1511
- return 1;
3273
+ return [items, automaticItems.map(item => item.element)];
3274
+ }
3275
+ function getCommonAncestor(firstNode, lastNode) {
3276
+ let ancestor = firstNode.parentElement;
3277
+
3278
+ // The `parentElement` walk cannot cross shadow boundaries, so the native
3279
+ // `contains` is sufficient here.
3280
+ while (ancestor && !ancestor.contains(lastNode)) {
3281
+ ancestor = ancestor.parentElement;
3282
+ }
3283
+ return ancestor;
3284
+ }
3285
+ function hasMovedNode(entries) {
3286
+ for (const entry of entries) {
3287
+ for (let i = 0; i < entry.removedNodes.length; i += 1) {
3288
+ if (entry.removedNodes[i].isConnected) {
3289
+ return true;
3290
+ }
3291
+ }
1512
3292
  }
1513
- return 0;
3293
+ return false;
3294
+ }
3295
+ function sortByDocumentPosition(a, b) {
3296
+ // `DOCUMENT_POSITION_CONTAINED_BY` is always reported alongside `FOLLOWING`, and `CONTAINS`
3297
+ // alongside `PRECEDING`, so testing `FOLLOWING` alone orders siblings and nested items alike.
3298
+ return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
1514
3299
  }
1515
3300
 
1516
3301
  /**
@@ -1535,17 +3320,17 @@ const baseArrow = options => ({
1535
3320
  element,
1536
3321
  padding = 0,
1537
3322
  offsetParent = 'real'
1538
- } = floatingUi_utils.evaluate(options, state) || {};
3323
+ } = useScrollLock.evaluate(options, state) || {};
1539
3324
  if (element == null) {
1540
3325
  return {};
1541
3326
  }
1542
- const paddingObject = floatingUi_utils.getPaddingObject(padding);
3327
+ const paddingObject = useScrollLock.getPaddingObject(padding);
1543
3328
  const coords = {
1544
3329
  x,
1545
3330
  y
1546
3331
  };
1547
- const axis = floatingUi_utils.getAlignmentAxis(placement);
1548
- const length = floatingUi_utils.getAxisLength(axis);
3332
+ const axis = useScrollLock.getAlignmentAxis(placement);
3333
+ const length = useScrollLock.getAxisLength(axis);
1549
3334
  const arrowDimensions = await platform.getDimensions(element);
1550
3335
  const isYAxis = axis === 'y';
1551
3336
  const minProp = isYAxis ? 'top' : 'left';
@@ -1573,13 +3358,13 @@ const baseArrow = options => ({
1573
3358
  const min = minPadding;
1574
3359
  const max = clientSize - arrowDimensions[length] - maxPadding;
1575
3360
  const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
1576
- const offset = floatingUi_utils.clamp(min, center, max);
3361
+ const offset = useScrollLock.clamp(min, center, max);
1577
3362
 
1578
3363
  // If the reference is small enough that the arrow's padding causes it to
1579
3364
  // to point to nothing for an aligned placement, adjust the offset of the
1580
3365
  // floating element itself. To ensure `shift()` continues to take action,
1581
3366
  // a single reset is performed when this is true.
1582
- const shouldAddOffset = !middlewareData.arrow && floatingUi_utils.getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
3367
+ const shouldAddOffset = !middlewareData.arrow && useScrollLock.getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
1583
3368
  // eslint-disable-next-line no-nested-ternary
1584
3369
  const alignmentOffset = shouldAddOffset ? center < min ? center - min : center - max : 0;
1585
3370
  return {
@@ -1607,7 +3392,6 @@ const arrow = (options, deps) => ({
1607
3392
  options: [options, deps]
1608
3393
  });
1609
3394
 
1610
- const nativeHideFn = floatingUi_reactDom.hide().fn;
1611
3395
  const hide = {
1612
3396
  name: 'hide',
1613
3397
  async fn(state) {
@@ -1618,10 +3402,15 @@ const hide = {
1618
3402
  y
1619
3403
  } = state.rects.reference;
1620
3404
  const anchorHidden = width === 0 && height === 0 && x === 0 && y === 0;
1621
- const nativeHideResult = await nativeHideFn(state);
3405
+ // Mirrors Floating UI's `hide()` referenceHidden strategy. Floating UI injects
3406
+ // `detectOverflow` into the middleware platform before invoking middleware.
3407
+ const overflow = await state.platform.detectOverflow(state, {
3408
+ elementContext: 'reference'
3409
+ });
3410
+ const referenceHidden = overflow.top - height >= 0 || overflow.right - width >= 0 || overflow.bottom - height >= 0 || overflow.left - width >= 0;
1622
3411
  return {
1623
3412
  data: {
1624
- referenceHidden: nativeHideResult.data?.referenceHidden || anchorHidden
3413
+ referenceHidden: referenceHidden || anchorHidden
1625
3414
  }
1626
3415
  };
1627
3416
  }
@@ -1631,75 +3420,13 @@ const DEFAULT_SIDES = {
1631
3420
  sideX: 'left',
1632
3421
  sideY: 'top'
1633
3422
  };
1634
- const adaptiveOrigin = {
1635
- name: 'adaptiveOrigin',
1636
- async fn(state) {
1637
- const {
1638
- x: rawX,
1639
- y: rawY,
1640
- rects: {
1641
- floating: floatRect
1642
- },
1643
- elements: {
1644
- floating
1645
- },
1646
- platform,
1647
- strategy,
1648
- placement
1649
- } = state;
1650
- const win = floatingUi_utils.getWindow(floating);
1651
- const styles = win.getComputedStyle(floating);
1652
- const hasTransition = styles.transitionDuration !== '0s' && styles.transitionDuration !== '';
1653
- if (!hasTransition) {
1654
- return {
1655
- x: rawX,
1656
- y: rawY,
1657
- data: DEFAULT_SIDES
1658
- };
1659
- }
1660
- const offsetParent = await platform.getOffsetParent?.(floating);
1661
- let offsetDimensions = {
1662
- width: 0,
1663
- height: 0
1664
- };
1665
3423
 
1666
- // For fixed strategy, prefer visualViewport if available
1667
- if (strategy === 'fixed' && win?.visualViewport) {
1668
- offsetDimensions = {
1669
- width: win.visualViewport.width,
1670
- height: win.visualViewport.height
1671
- };
1672
- } else if (offsetParent === win) {
1673
- const doc = useScrollLock.ownerDocument(floating);
1674
- offsetDimensions = {
1675
- width: doc.documentElement.clientWidth,
1676
- height: doc.documentElement.clientHeight
1677
- };
1678
- } else if (await platform.isElement?.(offsetParent)) {
1679
- offsetDimensions = await platform.getDimensions(offsetParent);
1680
- }
1681
- const currentSide = floatingUi_utils.getSide(placement);
1682
- let x = rawX;
1683
- let y = rawY;
1684
- if (currentSide === 'left') {
1685
- x = offsetDimensions.width - (rawX + floatRect.width);
1686
- }
1687
- if (currentSide === 'top') {
1688
- y = offsetDimensions.height - (rawY + floatRect.height);
1689
- }
1690
- const sideX = currentSide === 'left' ? 'right' : DEFAULT_SIDES.sideX;
1691
- const sideY = currentSide === 'top' ? 'bottom' : DEFAULT_SIDES.sideY;
1692
- return {
1693
- x,
1694
- y,
1695
- data: {
1696
- sideX,
1697
- sideY
1698
- }
1699
- };
1700
- }
1701
- };
3424
+ // Self-contained stand-in for Floating UI's `Middleware` type. Referencing the real type in
3425
+ // store state makes `tsc` declaration emit reference `Platform`/`detectOverflow` from
3426
+ // `@floating-ui/core` internals, which fails as non-portable (TS2883) in consuming builds.
1702
3427
 
3428
+ const AVAILABLE_WIDTH_VAR = '--available-width';
3429
+ const AVAILABLE_HEIGHT_VAR = '--available-height';
1703
3430
  function getLogicalSide(sideParam, renderedSide, isRtl) {
1704
3431
  const isLogicalSideParam = sideParam === 'inline-start' || sideParam === 'inline-end';
1705
3432
  const logicalRight = isRtl ? 'inline-start' : 'inline-end';
@@ -1717,8 +3444,8 @@ function getOffsetData(state, sideParam, isRtl) {
1717
3444
  placement
1718
3445
  } = state;
1719
3446
  const data = {
1720
- side: getLogicalSide(sideParam, floatingUi_utils.getSide(placement), isRtl),
1721
- align: floatingUi_utils.getAlignment(placement) || 'center',
3447
+ side: getLogicalSide(sideParam, useScrollLock.getSide(placement), isRtl),
3448
+ align: useScrollLock.getAlignment(placement) || 'center',
1722
3449
  anchor: {
1723
3450
  width: rects.reference.width,
1724
3451
  height: rects.reference.height
@@ -1735,6 +3462,9 @@ function getOffsetData(state, sideParam, isRtl) {
1735
3462
  * `useFloating` hook.
1736
3463
  */
1737
3464
  function useAnchorPositioning(params) {
3465
+ return useAnchorPositioningWithHook(params, useBaseUIFloating);
3466
+ }
3467
+ function useAnchorPositioningWithHook(params, useFloatingHook) {
1738
3468
  const {
1739
3469
  // Public parameters
1740
3470
  anchor,
@@ -1754,7 +3484,7 @@ function useAnchorPositioning(params) {
1754
3484
  floatingRootContext,
1755
3485
  mounted,
1756
3486
  collisionAvoidance,
1757
- shiftCrossAxis = false,
3487
+ shift: shift$1,
1758
3488
  nodeId,
1759
3489
  adaptiveOrigin,
1760
3490
  lazyFlip = false,
@@ -1767,6 +3497,8 @@ function useAnchorPositioning(params) {
1767
3497
  const collisionAvoidanceSide = collisionAvoidance.side || 'flip';
1768
3498
  const collisionAvoidanceAlign = collisionAvoidance.align || 'flip';
1769
3499
  const collisionAvoidanceFallbackAxisSide = collisionAvoidance.fallbackAxisSide || 'end';
3500
+ const shiftCrossAxis = shift$1?.crossAxis ?? false;
3501
+ const shiftRootBoundary = shift$1?.rootBoundary;
1770
3502
  const anchorFn = typeof anchor === 'function' ? anchor : undefined;
1771
3503
  const anchorFnCallback = useScrollLock.useStableCallback(anchorFn);
1772
3504
  const anchorDep = anchorFn ? anchorFnCallback : anchor;
@@ -1784,30 +3516,32 @@ function useAnchorPositioning(params) {
1784
3516
  }[sideParam];
1785
3517
  const placement = align === 'center' ? side : `${side}-${align}`;
1786
3518
  let collisionPadding = collisionPaddingParam;
3519
+ if (typeof collisionPadding === 'number') {
3520
+ collisionPadding = {
3521
+ top: collisionPadding,
3522
+ right: collisionPadding,
3523
+ bottom: collisionPadding,
3524
+ left: collisionPadding
3525
+ };
3526
+ } else if (collisionPadding) {
3527
+ collisionPadding = {
3528
+ top: collisionPadding.top || 0,
3529
+ right: collisionPadding.right || 0,
3530
+ bottom: collisionPadding.bottom || 0,
3531
+ left: collisionPadding.left || 0
3532
+ };
3533
+ }
1787
3534
 
1788
3535
  // Create a bias to the preferred side.
1789
3536
  // On iOS, when the mobile software keyboard opens, the input is exactly centered
1790
3537
  // in the viewport, but this can cause it to flip to the top undesirably.
3538
+ // The bias is only applied to `flip()` so it doesn't shift the resting position
3539
+ // computed by `shift()` and `size()` away from the requested `collisionPadding`.
1791
3540
  const bias = 1;
1792
3541
  const biasTop = sideParam === 'bottom' ? bias : 0;
1793
3542
  const biasBottom = sideParam === 'top' ? bias : 0;
1794
3543
  const biasLeft = sideParam === 'right' ? bias : 0;
1795
3544
  const biasRight = sideParam === 'left' ? bias : 0;
1796
- if (typeof collisionPadding === 'number') {
1797
- collisionPadding = {
1798
- top: collisionPadding + biasTop,
1799
- right: collisionPadding + biasRight,
1800
- bottom: collisionPadding + biasBottom,
1801
- left: collisionPadding + biasLeft
1802
- };
1803
- } else if (collisionPadding) {
1804
- collisionPadding = {
1805
- top: (collisionPadding.top || 0) + biasTop,
1806
- right: (collisionPadding.right || 0) + biasRight,
1807
- bottom: (collisionPadding.bottom || 0) + biasBottom,
1808
- left: (collisionPadding.left || 0) + biasLeft
1809
- };
1810
- }
1811
3545
  const commonCollisionProps = {
1812
3546
  boundary: collisionBoundary === 'clipping-ancestors' ? 'clippingAncestors' : collisionBoundary,
1813
3547
  padding: collisionPadding
@@ -1827,7 +3561,7 @@ function useAnchorPositioning(params) {
1827
3561
  if (inlineMiddleware) {
1828
3562
  middleware.push(inlineMiddleware);
1829
3563
  }
1830
- middleware.push(floatingUi_reactDom.offset(state => {
3564
+ middleware.push(offset(state => {
1831
3565
  const data = getOffsetData(state, sideParam, isRtl);
1832
3566
  const sideAxis = typeof sideOffsetRef.current === 'function' ? sideOffsetRef.current(data) : sideOffsetRef.current;
1833
3567
  const alignAxis = typeof alignOffsetRef.current === 'function' ? alignOffsetRef.current(data) : alignOffsetRef.current;
@@ -1839,51 +3573,42 @@ function useAnchorPositioning(params) {
1839
3573
  }, [sideOffsetDep, alignOffsetDep, isRtl, sideParam]));
1840
3574
  const shiftDisabled = collisionAvoidanceAlign === 'none' && collisionAvoidanceSide !== 'shift';
1841
3575
  const crossAxisShiftEnabled = !shiftDisabled && (sticky || shiftCrossAxis || collisionAvoidanceSide === 'shift');
1842
- const flipMiddleware = collisionAvoidanceSide === 'none' ? null : floatingUi_reactDom.flip({
3576
+ const flipMiddleware = collisionAvoidanceSide === 'none' ? null : flip({
1843
3577
  ...commonCollisionProps,
1844
3578
  // Ensure the popup flips if it's been limited by its --available-height and it resizes.
1845
3579
  // Since the size() padding is smaller than the flip() padding, flip() will take precedence.
1846
3580
  padding: {
1847
- top: collisionPadding.top + bias,
1848
- right: collisionPadding.right + bias,
1849
- bottom: collisionPadding.bottom + bias,
1850
- left: collisionPadding.left + bias
3581
+ top: collisionPadding.top + bias + biasTop,
3582
+ right: collisionPadding.right + bias + biasRight,
3583
+ bottom: collisionPadding.bottom + bias + biasBottom,
3584
+ left: collisionPadding.left + bias + biasLeft
1851
3585
  },
1852
3586
  mainAxis: !shiftCrossAxis && collisionAvoidanceSide === 'flip',
1853
3587
  crossAxis: collisionAvoidanceAlign === 'flip' ? 'alignment' : false,
1854
3588
  fallbackAxisSideDirection: collisionAvoidanceFallbackAxisSide
1855
3589
  });
1856
- const shiftMiddleware = shiftDisabled ? null : floatingUi_reactDom.shift(data => {
1857
- const html = useScrollLock.ownerDocument(data.elements.floating).documentElement;
1858
- return {
1859
- ...commonCollisionProps,
1860
- // Use the Layout Viewport to avoid shifting around when pinch-zooming
1861
- // for context menus.
1862
- rootBoundary: shiftCrossAxis ? {
1863
- x: 0,
1864
- y: 0,
1865
- width: html.clientWidth,
1866
- height: html.clientHeight
1867
- } : undefined,
1868
- mainAxis: collisionAvoidanceAlign !== 'none',
1869
- crossAxis: crossAxisShiftEnabled,
1870
- limiter: sticky || shiftCrossAxis ? undefined : floatingUi_reactDom.limitShift(limitData => {
1871
- if (!arrowRef.current) {
1872
- return {};
1873
- }
1874
- const {
1875
- width,
1876
- height
1877
- } = arrowRef.current.getBoundingClientRect();
1878
- const sideAxis = floatingUi_utils.getSideAxis(floatingUi_utils.getSide(limitData.placement));
1879
- const arrowSize = sideAxis === 'y' ? width : height;
1880
- const offsetAmount = sideAxis === 'y' ? collisionPadding.left + collisionPadding.right : collisionPadding.top + collisionPadding.bottom;
1881
- return {
1882
- offset: arrowSize / 2 + offsetAmount / 2
1883
- };
1884
- })
1885
- };
1886
- }, [commonCollisionProps, sticky, shiftCrossAxis, collisionPadding, collisionAvoidanceAlign]);
3590
+ const shiftMiddleware = shiftDisabled ? null : shift({
3591
+ ...commonCollisionProps,
3592
+ // Use the Layout Viewport to avoid shifting around when pinch-zooming.
3593
+ rootBoundary: shiftRootBoundary,
3594
+ mainAxis: collisionAvoidanceAlign !== 'none',
3595
+ crossAxis: crossAxisShiftEnabled,
3596
+ limiter: sticky || shiftCrossAxis ? undefined : limitShift(limitData => {
3597
+ if (!arrowRef.current) {
3598
+ return {};
3599
+ }
3600
+ const {
3601
+ width,
3602
+ height
3603
+ } = arrowRef.current.getBoundingClientRect();
3604
+ const sideAxis = useScrollLock.getSideAxis(useScrollLock.getSide(limitData.placement));
3605
+ const arrowSize = sideAxis === 'y' ? width : height;
3606
+ const offsetAmount = sideAxis === 'y' ? collisionPadding.left + collisionPadding.right : collisionPadding.top + collisionPadding.bottom;
3607
+ return {
3608
+ offset: arrowSize / 2 + offsetAmount / 2
3609
+ };
3610
+ })
3611
+ }, [commonCollisionProps, sticky, shiftCrossAxis, shiftRootBoundary, collisionPadding, collisionAvoidanceAlign]);
1887
3612
 
1888
3613
  // https://floating-ui.com/docs/flip#combining-with-shift
1889
3614
  if (collisionAvoidanceSide === 'shift' || collisionAvoidanceAlign === 'shift' || align === 'center') {
@@ -1891,7 +3616,7 @@ function useAnchorPositioning(params) {
1891
3616
  } else {
1892
3617
  middleware.push(flipMiddleware, shiftMiddleware);
1893
3618
  }
1894
- middleware.push(floatingUi_reactDom.size({
3619
+ middleware.push(size({
1895
3620
  ...commonCollisionProps,
1896
3621
  apply({
1897
3622
  elements: {
@@ -1905,11 +3630,11 @@ function useAnchorPositioning(params) {
1905
3630
  return;
1906
3631
  }
1907
3632
  const floatingStyle = floating.style;
1908
- floatingStyle.setProperty('--available-width', `${availableWidth}px`);
1909
- floatingStyle.setProperty('--available-height', `${availableHeight}px`);
3633
+ floatingStyle.setProperty(AVAILABLE_WIDTH_VAR, `${availableWidth}px`);
3634
+ floatingStyle.setProperty(AVAILABLE_HEIGHT_VAR, `${availableHeight}px`);
1910
3635
 
1911
3636
  // Snap anchor dimensions to device pixels to ensure the popup's visual width matches the anchor's one.
1912
- const dpr = floatingUi_utils.getWindow(floating).devicePixelRatio || 1;
3637
+ const dpr = useScrollLock.getWindow(floating).devicePixelRatio || 1;
1913
3638
  const {
1914
3639
  x,
1915
3640
  y,
@@ -1937,8 +3662,8 @@ function useAnchorPositioning(params) {
1937
3662
  rects,
1938
3663
  y
1939
3664
  } = state;
1940
- const currentRenderedSide = floatingUi_utils.getSide(renderedPlacement);
1941
- const currentRenderedAxis = floatingUi_utils.getSideAxis(currentRenderedSide);
3665
+ const currentRenderedSide = useScrollLock.getSide(renderedPlacement);
3666
+ const currentRenderedAxis = useScrollLock.getSideAxis(currentRenderedSide);
1942
3667
  const arrowEl = arrowRef.current;
1943
3668
  const arrowX = middlewareData.arrow?.x || 0;
1944
3669
  const arrowY = middlewareData.arrow?.y || 0;
@@ -1988,13 +3713,13 @@ function useAnchorPositioning(params) {
1988
3713
  context,
1989
3714
  isPositioned,
1990
3715
  floatingStyles: originalFloatingStyles
1991
- } = useFloating({
3716
+ } = useFloatingHook({
1992
3717
  rootContext: floatingRootContext,
1993
3718
  open: keepMounted ? mounted : undefined,
1994
3719
  placement,
1995
3720
  middleware,
1996
3721
  strategy: positionMethod,
1997
- whileElementsMounted: keepMounted ? undefined : (...args) => floatingUi_reactDom.autoUpdate(...args, autoUpdateOptions),
3722
+ whileElementsMounted: keepMounted ? undefined : (...args) => autoUpdate(...args, autoUpdateOptions),
1998
3723
  nodeId,
1999
3724
  externalTree
2000
3725
  });
@@ -2007,14 +3732,41 @@ function useAnchorPositioning(params) {
2007
3732
  // This ensures the popup is inside the viewport initially before it gets positioned.
2008
3733
  const resolvedPosition = isPositioned ? positionMethod : 'fixed';
2009
3734
  const floatingStyles = React__namespace.useMemo(() => {
2010
- const base = adaptiveOrigin ? {
2011
- position: resolvedPosition,
2012
- [sideX]: x,
2013
- [sideY]: y
2014
- } : {
2015
- position: resolvedPosition,
2016
- ...originalFloatingStyles
2017
- };
3735
+ let base;
3736
+ if (!isPositioned) {
3737
+ // Until a position for the current open is computed, ignore any coordinates retained from a
3738
+ // previous open (or from a pass that measured the hidden popup as 0x0). Rendering the
3739
+ // full-size popup at such stale coordinates can overflow the layout viewport, which makes
3740
+ // mobile Chrome zoom the page out and reflow everything the popup is anchored to.
3741
+ base = {
3742
+ position: resolvedPosition,
3743
+ top: 0,
3744
+ left: 0
3745
+ };
3746
+ } else if (adaptiveOrigin) {
3747
+ base = {
3748
+ position: resolvedPosition,
3749
+ [sideX]: x,
3750
+ [sideY]: y
3751
+ };
3752
+ } else {
3753
+ base = {
3754
+ ...originalFloatingStyles,
3755
+ position: resolvedPosition
3756
+ };
3757
+ }
3758
+
3759
+ // Seed the available size vars so consumer `max-height: min(x, var(--available-height))` rules
3760
+ // resolve to a valid length on the first positioning pass, before `size()` writes the real
3761
+ // values. Without a fallback the unresolved `var()` invalidates the whole declaration, so the
3762
+ // popup is measured unconstrained while `flip()` picks its side, against the full content
3763
+ // height rather than the capped one. Seeded unconditionally (not only while `!isPositioned`):
3764
+ // the keys must stay present with a constant value so React's per-property style diff never
3765
+ // rewrites them after mount, preserving the px values `size()` sets imperatively. Moving them
3766
+ // into the `!isPositioned` branch makes React remove them once positioned, wiping `size()`'s
3767
+ // values and leaving the popup unconstrained.
3768
+ base[AVAILABLE_WIDTH_VAR] = '100vw';
3769
+ base[AVAILABLE_HEIGHT_VAR] = '100vh';
2018
3770
  if (!isPositioned) {
2019
3771
  base.opacity = 0;
2020
3772
  }
@@ -2052,23 +3804,23 @@ function useAnchorPositioning(params) {
2052
3804
  }, [mounted, refs, anchorDep, anchorValueRef]);
2053
3805
  React__namespace.useEffect(() => {
2054
3806
  if (keepMounted && mounted && elements.reference && elements.floating) {
2055
- return floatingUi_reactDom.autoUpdate(elements.reference, elements.floating, update, autoUpdateOptions);
3807
+ return autoUpdate(elements.reference, elements.floating, update, autoUpdateOptions);
2056
3808
  }
2057
3809
  return undefined;
2058
3810
  }, [keepMounted, mounted, elements, update, autoUpdateOptions]);
2059
- const renderedSide = floatingUi_utils.getSide(renderedPlacement);
3811
+ const renderedSide = useScrollLock.getSide(renderedPlacement);
2060
3812
  const logicalRenderedSide = getLogicalSide(sideParam, renderedSide, isRtl);
2061
- const renderedAlign = floatingUi_utils.getAlignment(renderedPlacement) || 'center';
3813
+ const renderedAlign = useScrollLock.getAlignment(renderedPlacement) || 'center';
2062
3814
  const anchorHidden = Boolean(middlewareData.hide?.referenceHidden);
2063
3815
 
2064
3816
  // Locks the flip (makes it "sticky") so it doesn't prefer a given placement
2065
3817
  // and flips back lazily, not eagerly. Ideal for filtered lists that change
2066
3818
  // the size of the popup dynamically to avoid unwanted flipping when typing.
2067
3819
  useScrollLock.useIsoLayoutEffect(() => {
2068
- if (lazyFlip && mounted && isPositioned) {
3820
+ if (lazyFlip && mounted && isPositioned && renderedSide !== side) {
2069
3821
  setMountSide(renderedSide);
2070
3822
  }
2071
- }, [lazyFlip, mounted, isPositioned, renderedSide]);
3823
+ }, [lazyFlip, mounted, isPositioned, renderedSide, side]);
2072
3824
  const arrowStyles = React__namespace.useMemo(() => ({
2073
3825
  position: 'absolute',
2074
3826
  top: middlewareData.arrow?.y,
@@ -2153,64 +3905,57 @@ function useAnchoredPopupScrollLock(enabled, touchOpen, positionerElement, refer
2153
3905
  useScrollLock.useScrollLock(enabled && (!touchOpen || touchOpenShouldLockScroll), referenceElement);
2154
3906
  }
2155
3907
 
2156
- let IndexGuessBehavior = /*#__PURE__*/function (IndexGuessBehavior) {
2157
- IndexGuessBehavior[IndexGuessBehavior["None"] = 0] = "None";
2158
- IndexGuessBehavior[IndexGuessBehavior["GuessFromOrder"] = 1] = "GuessFromOrder";
2159
- return IndexGuessBehavior;
2160
- }({});
2161
-
2162
3908
  /**
2163
3909
  * Used to register a list item and its index (DOM position) in the `CompositeList`.
2164
3910
  */
2165
3911
  function useCompositeListItem(params = {}) {
2166
3912
  const {
3913
+ guess,
2167
3914
  label,
2168
3915
  metadata,
2169
3916
  textRef,
2170
- indexGuessBehavior,
2171
3917
  index: externalIndex
2172
3918
  } = params;
2173
3919
  const {
2174
3920
  register,
2175
3921
  unregister,
2176
3922
  subscribeMapChange,
2177
- elementsRef,
2178
- labelsRef,
2179
3923
  nextIndexRef
2180
3924
  } = useCompositeListContext();
3925
+
3926
+ // Guess the index from the render order. This avoids a re-render after mount for
3927
+ // flat lists rendered in DOM order; when the guess is wrong (grouped or out-of-order
3928
+ // rendering), the commit flush corrects it before paint.
2181
3929
  const indexRef = React__namespace.useRef(-1);
2182
- const [index, setIndex] = React__namespace.useState(externalIndex ?? (indexGuessBehavior === IndexGuessBehavior.GuessFromOrder ? () => {
3930
+ const [internalIndex, setInternalIndex] = React__namespace.useState(externalIndex == null && guess ? () => {
2183
3931
  if (indexRef.current === -1) {
2184
3932
  const newIndex = nextIndexRef.current;
2185
3933
  nextIndexRef.current += 1;
2186
3934
  indexRef.current = newIndex;
2187
3935
  }
2188
3936
  return indexRef.current;
2189
- } : -1));
3937
+ } : -1);
3938
+ const index = externalIndex ?? internalIndex;
2190
3939
  const componentRef = React__namespace.useRef(null);
3940
+
3941
+ // Deliberately identity-sensitive: nested items sharing one DOM node rely on ref attachment
3942
+ // order to decide which registration wins, and republishing from an effect instead would let
3943
+ // an inner item's later update silently take ownership from the outer one.
2191
3944
  const ref = React__namespace.useCallback(node => {
2192
- componentRef.current = node;
2193
- if (index !== -1 && node !== null) {
2194
- elementsRef.current[index] = node;
2195
- if (labelsRef) {
2196
- const isLabelDefined = label !== undefined;
2197
- labelsRef.current[index] = isLabelDefined ? label : textRef?.current?.textContent ?? node.textContent;
2198
- }
3945
+ const previousNode = componentRef.current;
3946
+ if (previousNode) {
3947
+ unregister(previousNode);
2199
3948
  }
2200
- }, [index, elementsRef, labelsRef, label, textRef]);
2201
- useScrollLock.useIsoLayoutEffect(() => {
2202
- if (externalIndex != null) {
2203
- return undefined;
2204
- }
2205
- const node = componentRef.current;
3949
+ componentRef.current = node;
2206
3950
  if (node) {
2207
- register(node, metadata);
2208
- return () => {
2209
- unregister(node);
2210
- };
3951
+ register(node, {
3952
+ metadata: metadata ?? null,
3953
+ index: externalIndex ?? null,
3954
+ label,
3955
+ textRef
3956
+ });
2211
3957
  }
2212
- return undefined;
2213
- }, [externalIndex, register, unregister, metadata]);
3958
+ }, [externalIndex, register, unregister, metadata, label, textRef]);
2214
3959
  useScrollLock.useIsoLayoutEffect(() => {
2215
3960
  if (externalIndex != null) {
2216
3961
  return undefined;
@@ -2218,10 +3963,10 @@ function useCompositeListItem(params = {}) {
2218
3963
  return subscribeMapChange(map => {
2219
3964
  const i = componentRef.current ? map.get(componentRef.current)?.index : null;
2220
3965
  if (i != null) {
2221
- setIndex(i);
3966
+ setInternalIndex(i);
2222
3967
  }
2223
3968
  });
2224
- }, [externalIndex, subscribeMapChange, setIndex]);
3969
+ }, [externalIndex, subscribeMapChange]);
2225
3970
  return {
2226
3971
  ref,
2227
3972
  index
@@ -2231,21 +3976,22 @@ function useCompositeListItem(params = {}) {
2231
3976
  exports.CompositeList = CompositeList;
2232
3977
  exports.DEFAULT_FIELD_ROOT_CONTEXT = DEFAULT_FIELD_ROOT_CONTEXT;
2233
3978
  exports.DEFAULT_FIELD_STATE_ATTRIBUTES = DEFAULT_FIELD_STATE_ATTRIBUTES;
3979
+ exports.DEFAULT_SIDES = DEFAULT_SIDES;
2234
3980
  exports.DEFAULT_VALIDITY_STATE = DEFAULT_VALIDITY_STATE;
2235
3981
  exports.FieldRootContext = FieldRootContext;
2236
- exports.IndexGuessBehavior = IndexGuessBehavior;
2237
3982
  exports.LabelableContext = LabelableContext;
2238
- exports.adaptiveOrigin = adaptiveOrigin;
2239
3983
  exports.areArraysEqual = areArraysEqual;
2240
3984
  exports.compareItemEquality = compareItemEquality;
2241
3985
  exports.defaultItemEquality = defaultItemEquality;
2242
3986
  exports.fieldValidityMapping = fieldValidityMapping;
2243
3987
  exports.findItemIndex = findItemIndex;
3988
+ exports.findSelectionIndex = findSelectionIndex;
2244
3989
  exports.getDefaultLabelId = getDefaultLabelId;
2245
3990
  exports.getDisabledMountTransitionStyles = getDisabledMountTransitionStyles;
2246
- exports.getPseudoElementBounds = getPseudoElementBounds;
2247
3991
  exports.hasNullItemLabel = hasNullItemLabel;
2248
3992
  exports.isGroupedItems = isGroupedItems;
3993
+ exports.isMouseWithinBounds = isMouseWithinBounds;
3994
+ exports.platform = platform;
2249
3995
  exports.removeItem = removeItem;
2250
3996
  exports.resolveAriaLabelledBy = resolveAriaLabelledBy;
2251
3997
  exports.resolveMultipleLabels = resolveMultipleLabels;
@@ -2262,6 +4008,7 @@ exports.useFormContext = useFormContext;
2262
4008
  exports.useLabelableContext = useLabelableContext;
2263
4009
  exports.useLabelableId = useLabelableId;
2264
4010
  exports.useListNavigation = useListNavigation;
4011
+ exports.useOnFirstRender = useOnFirstRender;
2265
4012
  exports.usePositioner = usePositioner;
2266
4013
  exports.useRegisterFieldControl = useRegisterFieldControl;
2267
4014
  exports.useTypeahead = useTypeahead;