@jobber/components 9.6.1 → 9.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Autocomplete/index.cjs +2 -0
- package/dist/Autocomplete/index.mjs +2 -0
- package/dist/Autocomplete-cjs.js +5 -4
- package/dist/Autocomplete-es.js +2 -1
- package/dist/Card/index.cjs +2 -1
- package/dist/Card/index.mjs +2 -1
- package/dist/Chip/index.cjs +2 -0
- package/dist/Chip/index.mjs +2 -0
- package/dist/Chips/InternalChipDismissible/hooks/index.cjs +2 -0
- package/dist/Chips/InternalChipDismissible/hooks/index.mjs +2 -0
- package/dist/Chips/InternalChipDismissible/index.cjs +2 -0
- package/dist/Chips/InternalChipDismissible/index.mjs +2 -0
- package/dist/Chips/index.cjs +2 -0
- package/dist/Chips/index.mjs +2 -0
- package/dist/Combobox/index.cjs +4 -2
- package/dist/Combobox/index.mjs +4 -2
- package/dist/{ComboboxSeparator-cjs.js → ComboboxChipRemove-cjs.js} +455 -501
- package/dist/{ComboboxSeparator-es.js → ComboboxChipRemove-es.js} +456 -500
- package/dist/ComboboxPrimitive-cjs.js +30 -29
- package/dist/ComboboxPrimitive-es.js +3 -2
- package/dist/ConfirmationModal/index.cjs +2 -0
- package/dist/ConfirmationModal/index.mjs +2 -0
- package/dist/DataDump/index.cjs +2 -1
- package/dist/DataDump/index.mjs +2 -1
- package/dist/DataList/components/DataListActions/index.cjs +2 -0
- package/dist/DataList/components/DataListActions/index.mjs +2 -0
- package/dist/DataList/components/DataListBulkActions/index.cjs +2 -0
- package/dist/DataList/components/DataListBulkActions/index.mjs +2 -0
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +2 -0
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +2 -0
- package/dist/DataList/components/DataListFilters/index.cjs +2 -0
- package/dist/DataList/components/DataListFilters/index.mjs +2 -0
- package/dist/DataList/components/DataListHeader/index.cjs +2 -0
- package/dist/DataList/components/DataListHeader/index.mjs +2 -0
- package/dist/DataList/components/DataListItem/index.cjs +2 -0
- package/dist/DataList/components/DataListItem/index.mjs +2 -0
- package/dist/DataList/components/DataListItemActions/index.cjs +2 -0
- package/dist/DataList/components/DataListItemActions/index.mjs +2 -0
- package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +2 -0
- package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +2 -0
- package/dist/DataList/components/DataListItems/index.cjs +2 -0
- package/dist/DataList/components/DataListItems/index.mjs +2 -0
- package/dist/DataList/components/DataListLayout/index.cjs +2 -0
- package/dist/DataList/components/DataListLayout/index.mjs +2 -0
- package/dist/DataList/components/DataListLayoutActions/index.cjs +2 -0
- package/dist/DataList/components/DataListLayoutActions/index.mjs +2 -0
- package/dist/DataList/index.cjs +2 -0
- package/dist/DataList/index.mjs +2 -0
- package/dist/DatePicker/index.cjs +2 -0
- package/dist/DatePicker/index.mjs +2 -0
- package/dist/DatePicker-cjs.js +5 -4
- package/dist/DatePicker-es.js +2 -1
- package/dist/Dialog/index.cjs +2 -1
- package/dist/Dialog/index.mjs +2 -1
- package/dist/DrawerDescription-cjs.js +99 -268
- package/dist/DrawerDescription-es.js +103 -270
- package/dist/DrawerTitle-cjs.js +6 -2
- package/dist/DrawerTitle-es.js +7 -3
- package/dist/FieldDescription-cjs.js +181 -184
- package/dist/FieldDescription-es.js +184 -187
- package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +2 -0
- package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +2 -0
- package/dist/FilterPicker/components/FilterPickerContent/index.cjs +2 -0
- package/dist/FilterPicker/components/FilterPickerContent/index.mjs +2 -0
- package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +2 -0
- package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +2 -0
- package/dist/FilterPicker/index.cjs +2 -0
- package/dist/FilterPicker/index.mjs +2 -0
- package/dist/FilterPickerContent-cjs.js +5 -4
- package/dist/FilterPickerContent-es.js +2 -1
- package/dist/FormatFile/index.cjs +2 -0
- package/dist/FormatFile/index.mjs +2 -0
- package/dist/Gallery/index.cjs +2 -0
- package/dist/Gallery/index.mjs +2 -0
- package/dist/InputDate/index.cjs +2 -0
- package/dist/InputDate/index.mjs +2 -0
- package/dist/InputNumber/index.cjs +2 -1
- package/dist/InputNumber/index.mjs +2 -1
- package/dist/LightBox/index.cjs +2 -0
- package/dist/LightBox/index.mjs +2 -0
- package/dist/Menu/index.cjs +2 -1
- package/dist/Menu/index.mjs +2 -1
- package/dist/Menu-cjs.js +5 -4
- package/dist/Menu-es.js +2 -1
- package/dist/MenuSubmenuTrigger-cjs.js +164 -206
- package/dist/MenuSubmenuTrigger-es.js +152 -194
- package/dist/Modal/index.cjs +2 -0
- package/dist/Modal/index.mjs +3 -1
- package/dist/NumberFieldInput-cjs.js +308 -187
- package/dist/NumberFieldInput-es.js +308 -187
- package/dist/Page/index.cjs +2 -1
- package/dist/Page/index.mjs +2 -1
- package/dist/Popover/index.cjs +2 -0
- package/dist/Popover/index.mjs +2 -0
- package/dist/Popover-cjs.js +8 -7
- package/dist/Popover-es.js +2 -1
- package/dist/ScrollAreaViewport-cjs.js +1093 -747
- package/dist/ScrollAreaViewport-es.js +1081 -734
- package/dist/Select/index.cjs +2 -1
- package/dist/Select/index.mjs +2 -1
- package/dist/SelectGroupLabel-cjs.js +306 -207
- package/dist/SelectGroupLabel-es.js +302 -203
- package/dist/Tooltip/index.cjs +2 -0
- package/dist/Tooltip/index.mjs +2 -0
- package/dist/Tooltip-cjs.js +7 -6
- package/dist/Tooltip-es.js +2 -1
- package/dist/dialogReturnFocus-cjs.js +1 -1
- package/dist/dialogReturnFocus-es.js +2 -2
- package/dist/floating-ui.react-cjs.js +192 -2564
- package/dist/floating-ui.react-dom-cjs.js +2103 -0
- package/dist/floating-ui.react-dom-es.js +2072 -0
- package/dist/floating-ui.react-es.js +156 -2519
- package/dist/floating-ui.utils-cjs.js +342 -0
- package/dist/floating-ui.utils-es.js +300 -0
- package/dist/index.cjs +4 -3
- package/dist/index.mjs +4 -3
- package/dist/primitives/BottomSheet/index.cjs +1 -1
- package/dist/primitives/BottomSheet/index.mjs +1 -1
- package/dist/primitives/ComboboxPrimitive/index.cjs +4 -2
- package/dist/primitives/ComboboxPrimitive/index.mjs +4 -2
- package/dist/primitives/SelectPrimitive/index.cjs +2 -0
- package/dist/primitives/SelectPrimitive/index.mjs +2 -0
- package/dist/primitives/index.cjs +3 -2
- package/dist/primitives/index.mjs +3 -2
- package/dist/scrollEdges-cjs.js +11 -1
- package/dist/scrollEdges-es.js +11 -1
- package/dist/unstyledPrimitives/index.cjs +478 -720
- package/dist/unstyledPrimitives/index.mjs +421 -663
- package/dist/useCompositeListItem-cjs.js +361 -2108
- package/dist/useCompositeListItem-es.js +331 -2076
- package/dist/useLabel-cjs.js +3 -2
- package/dist/useLabel-es.js +3 -2
- package/dist/useRenderElement-cjs.js +7 -9
- package/dist/useRenderElement-es.js +7 -9
- package/dist/useScrollLock-cjs.js +344 -819
- package/dist/useScrollLock-es.js +296 -732
- package/dist/useScrollToActive-cjs.js +5 -4
- package/dist/useScrollToActive-es.js +2 -1
- package/package.json +3 -3
- package/dist/scrollable-cjs.js +0 -58
- package/dist/scrollable-es.js +0 -54
|
@@ -1,1720 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { aa as useId, ab as useFloatingParentNodeId, ac as FloatingRootStore, ad as PopupTriggerMap, a as useIsoLayoutEffect, ae as useFloatingTree, Z as getFloatingFocusElement, af as isTypeableCombobox, q as useValueAsRef, b as useStableCallback, a5 as useAnimationFrame, ag as isIndexOutOfListBounds, ah as getMinListIndex, ai as getMaxListIndex, D as activeElement, o as ownerDocument, _ as contains, L as stopEvent, d as createChangeEventDetails, aj as listNavigation, ak as findNonDisabledListIndex, g as getTarget, W as focusOut, al as enqueueFocus, a8 as isVirtualClick, am as isVirtualPointerEvent, an as ARROW_UP, ao as ARROW_DOWN, ap as ARROW_LEFT, aq as ARROW_RIGHT, k as useTimeout, ar as isListIndexDisabled, as as isElementVisible, u as useBaseUiId, at as jsdom, a4 as useDirection, au as DISABLED_TRANSITIONS_STYLE, p as popupStateMapping, av as useScrollLock } from './useScrollLock-es.js';
|
|
3
|
+
import { b as isElement, i as isHTMLElement, K as getWindow, p as evaluate, q as getPaddingObject, m as getAlignmentAxis, o as getAlignment, z as getAxisLength, w as clamp, n as getSide, l as getSideAxis } from './floating-ui.utils-es.js';
|
|
4
4
|
import { a as useRefWithInit, c as EMPTY_ARRAY, N as NOOP, E as EMPTY_OBJECT, f as formatErrorMessage, u as useRenderElement } from './useRenderElement-es.js';
|
|
5
5
|
import { jsx } from 'react/jsx-runtime';
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
function useOnFirstRender(fn) {
|
|
9
|
-
const ref = React.useRef(true);
|
|
10
|
-
if (ref.current) {
|
|
11
|
-
ref.current = false;
|
|
12
|
-
fn();
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function computeCoordsFromPlacement(_ref, placement, rtl) {
|
|
17
|
-
let {
|
|
18
|
-
reference,
|
|
19
|
-
floating
|
|
20
|
-
} = _ref;
|
|
21
|
-
const sideAxis = getSideAxis(placement);
|
|
22
|
-
const alignmentAxis = getAlignmentAxis(placement);
|
|
23
|
-
const alignLength = getAxisLength(alignmentAxis);
|
|
24
|
-
const side = getSide(placement);
|
|
25
|
-
const isVertical = sideAxis === 'y';
|
|
26
|
-
const commonX = reference.x + reference.width / 2 - floating.width / 2;
|
|
27
|
-
const commonY = reference.y + reference.height / 2 - floating.height / 2;
|
|
28
|
-
const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;
|
|
29
|
-
let coords;
|
|
30
|
-
switch (side) {
|
|
31
|
-
case 'top':
|
|
32
|
-
coords = {
|
|
33
|
-
x: commonX,
|
|
34
|
-
y: reference.y - floating.height
|
|
35
|
-
};
|
|
36
|
-
break;
|
|
37
|
-
case 'bottom':
|
|
38
|
-
coords = {
|
|
39
|
-
x: commonX,
|
|
40
|
-
y: reference.y + reference.height
|
|
41
|
-
};
|
|
42
|
-
break;
|
|
43
|
-
case 'right':
|
|
44
|
-
coords = {
|
|
45
|
-
x: reference.x + reference.width,
|
|
46
|
-
y: commonY
|
|
47
|
-
};
|
|
48
|
-
break;
|
|
49
|
-
case 'left':
|
|
50
|
-
coords = {
|
|
51
|
-
x: reference.x - floating.width,
|
|
52
|
-
y: commonY
|
|
53
|
-
};
|
|
54
|
-
break;
|
|
55
|
-
default:
|
|
56
|
-
coords = {
|
|
57
|
-
x: reference.x,
|
|
58
|
-
y: reference.y
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
const alignment = getAlignment(placement);
|
|
62
|
-
if (alignment) {
|
|
63
|
-
coords[alignmentAxis] += commonAlign * (alignment === 'end' ? 1 : -1) * (rtl && isVertical ? -1 : 1);
|
|
64
|
-
}
|
|
65
|
-
return coords;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Resolves with an object of overflow side offsets that determine how much the
|
|
70
|
-
* element is overflowing a given clipping boundary on each side.
|
|
71
|
-
* - positive = overflowing the boundary by that number of pixels
|
|
72
|
-
* - negative = how many pixels left before it will overflow
|
|
73
|
-
* - 0 = lies flush with the boundary
|
|
74
|
-
* @see https://floating-ui.com/docs/detectOverflow
|
|
75
|
-
*/
|
|
76
|
-
async function detectOverflow(state, options) {
|
|
77
|
-
var _await$platform$isEle;
|
|
78
|
-
if (options === void 0) {
|
|
79
|
-
options = {};
|
|
80
|
-
}
|
|
81
|
-
const {
|
|
82
|
-
x,
|
|
83
|
-
y,
|
|
84
|
-
platform,
|
|
85
|
-
rects,
|
|
86
|
-
elements,
|
|
87
|
-
strategy
|
|
88
|
-
} = state;
|
|
89
|
-
const {
|
|
90
|
-
boundary = 'clippingAncestors',
|
|
91
|
-
rootBoundary = 'viewport',
|
|
92
|
-
elementContext = 'floating',
|
|
93
|
-
altBoundary = false,
|
|
94
|
-
padding = 0
|
|
95
|
-
} = evaluate(options, state);
|
|
96
|
-
const paddingObject = getPaddingObject(padding);
|
|
97
|
-
const altContext = elementContext === 'floating' ? 'reference' : 'floating';
|
|
98
|
-
const element = elements[altBoundary ? altContext : elementContext];
|
|
99
|
-
const clippingClientRect = rectToClientRect(await platform.getClippingRect({
|
|
100
|
-
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))),
|
|
101
|
-
boundary,
|
|
102
|
-
rootBoundary,
|
|
103
|
-
strategy
|
|
104
|
-
}));
|
|
105
|
-
const rect = elementContext === 'floating' ? {
|
|
106
|
-
x,
|
|
107
|
-
y,
|
|
108
|
-
width: rects.floating.width,
|
|
109
|
-
height: rects.floating.height
|
|
110
|
-
} : rects.reference;
|
|
111
|
-
const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
|
|
112
|
-
const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) && (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
|
|
113
|
-
x: 1,
|
|
114
|
-
y: 1
|
|
115
|
-
};
|
|
116
|
-
const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({
|
|
117
|
-
elements,
|
|
118
|
-
rect,
|
|
119
|
-
offsetParent,
|
|
120
|
-
strategy
|
|
121
|
-
}) : rect);
|
|
122
|
-
return {
|
|
123
|
-
top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,
|
|
124
|
-
bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,
|
|
125
|
-
left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,
|
|
126
|
-
right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Maximum number of resets that can occur before bailing to avoid infinite reset loops.
|
|
131
|
-
const MAX_RESET_COUNT = 50;
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Computes the `x` and `y` coordinates that will place the floating element
|
|
135
|
-
* next to a given reference element.
|
|
136
|
-
*
|
|
137
|
-
* This export does not have any `platform` interface logic. You will need to
|
|
138
|
-
* write one for the platform you are using Floating UI with.
|
|
139
|
-
*/
|
|
140
|
-
const computePosition$1 = async (reference, floating, config) => {
|
|
141
|
-
const {
|
|
142
|
-
placement = 'bottom',
|
|
143
|
-
strategy = 'absolute',
|
|
144
|
-
middleware = [],
|
|
145
|
-
platform
|
|
146
|
-
} = config;
|
|
147
|
-
const platformWithDetectOverflow = platform.detectOverflow ? platform : {
|
|
148
|
-
...platform,
|
|
149
|
-
detectOverflow
|
|
150
|
-
};
|
|
151
|
-
const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));
|
|
152
|
-
let rects = await platform.getElementRects({
|
|
153
|
-
reference,
|
|
154
|
-
floating,
|
|
155
|
-
strategy
|
|
156
|
-
});
|
|
157
|
-
let {
|
|
158
|
-
x,
|
|
159
|
-
y
|
|
160
|
-
} = computeCoordsFromPlacement(rects, placement, rtl);
|
|
161
|
-
let statefulPlacement = placement;
|
|
162
|
-
let resetCount = 0;
|
|
163
|
-
const middlewareData = {};
|
|
164
|
-
for (let i = 0; i < middleware.length; i++) {
|
|
165
|
-
const currentMiddleware = middleware[i];
|
|
166
|
-
if (!currentMiddleware) {
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
const {
|
|
170
|
-
name,
|
|
171
|
-
fn
|
|
172
|
-
} = currentMiddleware;
|
|
173
|
-
const {
|
|
174
|
-
x: nextX,
|
|
175
|
-
y: nextY,
|
|
176
|
-
data,
|
|
177
|
-
reset
|
|
178
|
-
} = await fn({
|
|
179
|
-
x,
|
|
180
|
-
y,
|
|
181
|
-
initialPlacement: placement,
|
|
182
|
-
placement: statefulPlacement,
|
|
183
|
-
strategy,
|
|
184
|
-
middlewareData,
|
|
185
|
-
rects,
|
|
186
|
-
platform: platformWithDetectOverflow,
|
|
187
|
-
elements: {
|
|
188
|
-
reference,
|
|
189
|
-
floating
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
x = nextX != null ? nextX : x;
|
|
193
|
-
y = nextY != null ? nextY : y;
|
|
194
|
-
middlewareData[name] = {
|
|
195
|
-
...middlewareData[name],
|
|
196
|
-
...data
|
|
197
|
-
};
|
|
198
|
-
if (reset && resetCount < MAX_RESET_COUNT) {
|
|
199
|
-
resetCount++;
|
|
200
|
-
if (typeof reset === 'object') {
|
|
201
|
-
if (reset.placement) {
|
|
202
|
-
statefulPlacement = reset.placement;
|
|
203
|
-
}
|
|
204
|
-
if (reset.rects) {
|
|
205
|
-
rects = reset.rects === true ? await platform.getElementRects({
|
|
206
|
-
reference,
|
|
207
|
-
floating,
|
|
208
|
-
strategy
|
|
209
|
-
}) : reset.rects;
|
|
210
|
-
}
|
|
211
|
-
({
|
|
212
|
-
x,
|
|
213
|
-
y
|
|
214
|
-
} = computeCoordsFromPlacement(rects, statefulPlacement, rtl));
|
|
215
|
-
}
|
|
216
|
-
i = -1;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return {
|
|
220
|
-
x,
|
|
221
|
-
y,
|
|
222
|
-
placement: statefulPlacement,
|
|
223
|
-
strategy,
|
|
224
|
-
middlewareData
|
|
225
|
-
};
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Optimizes the visibility of the floating element by flipping the `placement`
|
|
230
|
-
* in order to keep it in view when the preferred placement(s) will overflow the
|
|
231
|
-
* clipping boundary. Alternative to `autoPlacement`.
|
|
232
|
-
* @see https://floating-ui.com/docs/flip
|
|
233
|
-
*/
|
|
234
|
-
const flip$2 = function (options) {
|
|
235
|
-
if (options === void 0) {
|
|
236
|
-
options = {};
|
|
237
|
-
}
|
|
238
|
-
return {
|
|
239
|
-
name: 'flip',
|
|
240
|
-
options,
|
|
241
|
-
async fn(state) {
|
|
242
|
-
var _middlewareData$arrow, _middlewareData$flip;
|
|
243
|
-
const {
|
|
244
|
-
placement,
|
|
245
|
-
middlewareData,
|
|
246
|
-
rects,
|
|
247
|
-
initialPlacement,
|
|
248
|
-
platform,
|
|
249
|
-
elements
|
|
250
|
-
} = state;
|
|
251
|
-
const {
|
|
252
|
-
mainAxis: checkMainAxis = true,
|
|
253
|
-
crossAxis: checkCrossAxis = true,
|
|
254
|
-
fallbackPlacements: specifiedFallbackPlacements,
|
|
255
|
-
fallbackStrategy = 'bestFit',
|
|
256
|
-
fallbackAxisSideDirection = 'none',
|
|
257
|
-
flipAlignment = true,
|
|
258
|
-
...detectOverflowOptions
|
|
259
|
-
} = evaluate(options, state);
|
|
260
|
-
|
|
261
|
-
// If a reset by the arrow was caused due to an alignment offset being
|
|
262
|
-
// added, we should skip any logic now since `flip()` has already done its
|
|
263
|
-
// work.
|
|
264
|
-
// https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643
|
|
265
|
-
if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
|
|
266
|
-
return {};
|
|
267
|
-
}
|
|
268
|
-
const side = getSide(placement);
|
|
269
|
-
const initialSideAxis = getSideAxis(initialPlacement);
|
|
270
|
-
const isBasePlacement = getSide(initialPlacement) === initialPlacement;
|
|
271
|
-
const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
|
|
272
|
-
const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));
|
|
273
|
-
const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== 'none';
|
|
274
|
-
if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) {
|
|
275
|
-
fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));
|
|
276
|
-
}
|
|
277
|
-
const placements = [initialPlacement, ...fallbackPlacements];
|
|
278
|
-
const overflow = await platform.detectOverflow(state, detectOverflowOptions);
|
|
279
|
-
const overflows = [];
|
|
280
|
-
let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];
|
|
281
|
-
if (checkMainAxis) {
|
|
282
|
-
overflows.push(overflow[side]);
|
|
283
|
-
}
|
|
284
|
-
if (checkCrossAxis) {
|
|
285
|
-
const sides = getAlignmentSides(placement, rects, rtl);
|
|
286
|
-
overflows.push(overflow[sides[0]], overflow[sides[1]]);
|
|
287
|
-
}
|
|
288
|
-
overflowsData = [...overflowsData, {
|
|
289
|
-
placement,
|
|
290
|
-
overflows
|
|
291
|
-
}];
|
|
292
|
-
|
|
293
|
-
// One or more sides is overflowing.
|
|
294
|
-
if (!overflows.every(side => side <= 0)) {
|
|
295
|
-
var _middlewareData$flip2, _overflowsData$filter;
|
|
296
|
-
const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;
|
|
297
|
-
const nextPlacement = placements[nextIndex];
|
|
298
|
-
if (nextPlacement) {
|
|
299
|
-
const ignoreCrossAxisOverflow = checkCrossAxis === 'alignment' ? initialSideAxis !== getSideAxis(nextPlacement) : false;
|
|
300
|
-
if (!ignoreCrossAxisOverflow ||
|
|
301
|
-
// We leave the current main axis only if every placement on that axis
|
|
302
|
-
// overflows the main axis.
|
|
303
|
-
overflowsData.every(d => getSideAxis(d.placement) === initialSideAxis ? d.overflows[0] > 0 : true)) {
|
|
304
|
-
// Try next placement and re-run the lifecycle.
|
|
305
|
-
return {
|
|
306
|
-
data: {
|
|
307
|
-
index: nextIndex,
|
|
308
|
-
overflows: overflowsData
|
|
309
|
-
},
|
|
310
|
-
reset: {
|
|
311
|
-
placement: nextPlacement
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// First, find the candidates that fit on the mainAxis side of overflow,
|
|
318
|
-
// then find the placement that fits the best on the main crossAxis side.
|
|
319
|
-
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;
|
|
320
|
-
|
|
321
|
-
// Otherwise fallback.
|
|
322
|
-
if (!resetPlacement) {
|
|
323
|
-
switch (fallbackStrategy) {
|
|
324
|
-
case 'bestFit':
|
|
325
|
-
{
|
|
326
|
-
var _overflowsData$filter2;
|
|
327
|
-
const placement = (_overflowsData$filter2 = overflowsData.filter(d => {
|
|
328
|
-
if (hasFallbackAxisSideDirection) {
|
|
329
|
-
const currentSideAxis = getSideAxis(d.placement);
|
|
330
|
-
return currentSideAxis === initialSideAxis ||
|
|
331
|
-
// Create a bias to the `y` side axis due to horizontal
|
|
332
|
-
// reading directions favoring greater width.
|
|
333
|
-
currentSideAxis === 'y';
|
|
334
|
-
}
|
|
335
|
-
return true;
|
|
336
|
-
}).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];
|
|
337
|
-
if (placement) {
|
|
338
|
-
resetPlacement = placement;
|
|
339
|
-
}
|
|
340
|
-
break;
|
|
341
|
-
}
|
|
342
|
-
case 'initialPlacement':
|
|
343
|
-
resetPlacement = initialPlacement;
|
|
344
|
-
break;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
if (placement !== resetPlacement) {
|
|
348
|
-
return {
|
|
349
|
-
reset: {
|
|
350
|
-
placement: resetPlacement
|
|
351
|
-
}
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
return {};
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
const originSides = /*#__PURE__*/new Set(['left', 'top']);
|
|
361
|
-
|
|
362
|
-
// For type backwards-compatibility, the `OffsetOptions` type was also
|
|
363
|
-
// Derivable.
|
|
364
|
-
|
|
365
|
-
async function convertValueToCoords(state, options) {
|
|
366
|
-
const {
|
|
367
|
-
placement,
|
|
368
|
-
platform,
|
|
369
|
-
elements
|
|
370
|
-
} = state;
|
|
371
|
-
const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
|
|
372
|
-
const side = getSide(placement);
|
|
373
|
-
const alignment = getAlignment(placement);
|
|
374
|
-
const isVertical = getSideAxis(placement) === 'y';
|
|
375
|
-
const mainAxisMulti = originSides.has(side) ? -1 : 1;
|
|
376
|
-
const crossAxisMulti = rtl && isVertical ? -1 : 1;
|
|
377
|
-
const rawValue = evaluate(options, state);
|
|
378
|
-
|
|
379
|
-
// eslint-disable-next-line prefer-const
|
|
380
|
-
let {
|
|
381
|
-
mainAxis,
|
|
382
|
-
crossAxis,
|
|
383
|
-
alignmentAxis
|
|
384
|
-
} = typeof rawValue === 'number' ? {
|
|
385
|
-
mainAxis: rawValue,
|
|
386
|
-
crossAxis: 0,
|
|
387
|
-
alignmentAxis: null
|
|
388
|
-
} : {
|
|
389
|
-
mainAxis: rawValue.mainAxis || 0,
|
|
390
|
-
crossAxis: rawValue.crossAxis || 0,
|
|
391
|
-
alignmentAxis: rawValue.alignmentAxis
|
|
392
|
-
};
|
|
393
|
-
if (alignment && typeof alignmentAxis === 'number') {
|
|
394
|
-
crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis;
|
|
395
|
-
}
|
|
396
|
-
return isVertical ? {
|
|
397
|
-
x: crossAxis * crossAxisMulti,
|
|
398
|
-
y: mainAxis * mainAxisMulti
|
|
399
|
-
} : {
|
|
400
|
-
x: mainAxis * mainAxisMulti,
|
|
401
|
-
y: crossAxis * crossAxisMulti
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* Modifies the placement by translating the floating element along the
|
|
407
|
-
* specified axes.
|
|
408
|
-
* A number (shorthand for `mainAxis` or distance), or an axes configuration
|
|
409
|
-
* object may be passed.
|
|
410
|
-
* @see https://floating-ui.com/docs/offset
|
|
411
|
-
*/
|
|
412
|
-
const offset$2 = function (options) {
|
|
413
|
-
if (options === void 0) {
|
|
414
|
-
options = 0;
|
|
415
|
-
}
|
|
416
|
-
return {
|
|
417
|
-
name: 'offset',
|
|
418
|
-
options,
|
|
419
|
-
async fn(state) {
|
|
420
|
-
var _middlewareData$offse, _middlewareData$arrow;
|
|
421
|
-
const {
|
|
422
|
-
x,
|
|
423
|
-
y,
|
|
424
|
-
placement,
|
|
425
|
-
middlewareData
|
|
426
|
-
} = state;
|
|
427
|
-
const diffCoords = await convertValueToCoords(state, options);
|
|
428
|
-
|
|
429
|
-
// If the placement is the same and the arrow caused an alignment offset
|
|
430
|
-
// then we don't need to change the positioning coordinates.
|
|
431
|
-
if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
|
|
432
|
-
return {};
|
|
433
|
-
}
|
|
434
|
-
return {
|
|
435
|
-
x: x + diffCoords.x,
|
|
436
|
-
y: y + diffCoords.y,
|
|
437
|
-
data: {
|
|
438
|
-
...diffCoords,
|
|
439
|
-
placement
|
|
440
|
-
}
|
|
441
|
-
};
|
|
442
|
-
}
|
|
443
|
-
};
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* Optimizes the visibility of the floating element by shifting it in order to
|
|
448
|
-
* keep it in view when it will overflow the clipping boundary.
|
|
449
|
-
* @see https://floating-ui.com/docs/shift
|
|
450
|
-
*/
|
|
451
|
-
const shift$2 = function (options) {
|
|
452
|
-
if (options === void 0) {
|
|
453
|
-
options = {};
|
|
454
|
-
}
|
|
455
|
-
return {
|
|
456
|
-
name: 'shift',
|
|
457
|
-
options,
|
|
458
|
-
async fn(state) {
|
|
459
|
-
const {
|
|
460
|
-
x,
|
|
461
|
-
y,
|
|
462
|
-
placement,
|
|
463
|
-
platform
|
|
464
|
-
} = state;
|
|
465
|
-
const {
|
|
466
|
-
mainAxis: checkMainAxis = true,
|
|
467
|
-
crossAxis: checkCrossAxis = false,
|
|
468
|
-
limiter = {
|
|
469
|
-
fn: _ref => {
|
|
470
|
-
let {
|
|
471
|
-
x,
|
|
472
|
-
y
|
|
473
|
-
} = _ref;
|
|
474
|
-
return {
|
|
475
|
-
x,
|
|
476
|
-
y
|
|
477
|
-
};
|
|
478
|
-
}
|
|
479
|
-
},
|
|
480
|
-
...detectOverflowOptions
|
|
481
|
-
} = evaluate(options, state);
|
|
482
|
-
const coords = {
|
|
483
|
-
x,
|
|
484
|
-
y
|
|
485
|
-
};
|
|
486
|
-
const overflow = await platform.detectOverflow(state, detectOverflowOptions);
|
|
487
|
-
const crossAxis = getSideAxis(placement);
|
|
488
|
-
const mainAxis = getOppositeAxis(crossAxis);
|
|
489
|
-
let mainAxisCoord = coords[mainAxis];
|
|
490
|
-
let crossAxisCoord = coords[crossAxis];
|
|
491
|
-
const clampCoord = (axis, coord) => clamp(coord + overflow[axis === 'y' ? 'top' : 'left'], coord, coord - overflow[axis === 'y' ? 'bottom' : 'right']);
|
|
492
|
-
if (checkMainAxis) {
|
|
493
|
-
mainAxisCoord = clampCoord(mainAxis, mainAxisCoord);
|
|
494
|
-
}
|
|
495
|
-
if (checkCrossAxis) {
|
|
496
|
-
crossAxisCoord = clampCoord(crossAxis, crossAxisCoord);
|
|
497
|
-
}
|
|
498
|
-
const limitedCoords = limiter.fn({
|
|
499
|
-
...state,
|
|
500
|
-
[mainAxis]: mainAxisCoord,
|
|
501
|
-
[crossAxis]: crossAxisCoord
|
|
502
|
-
});
|
|
503
|
-
return {
|
|
504
|
-
...limitedCoords,
|
|
505
|
-
data: {
|
|
506
|
-
x: limitedCoords.x - x,
|
|
507
|
-
y: limitedCoords.y - y,
|
|
508
|
-
enabled: {
|
|
509
|
-
[mainAxis]: checkMainAxis,
|
|
510
|
-
[crossAxis]: checkCrossAxis
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
};
|
|
516
|
-
};
|
|
517
|
-
/**
|
|
518
|
-
* Built-in `limiter` that will stop `shift()` at a certain point.
|
|
519
|
-
*/
|
|
520
|
-
const limitShift$2 = function (options) {
|
|
521
|
-
if (options === void 0) {
|
|
522
|
-
options = {};
|
|
523
|
-
}
|
|
524
|
-
return {
|
|
525
|
-
options,
|
|
526
|
-
fn(state) {
|
|
527
|
-
var _rawOffset$mainAxis, _rawOffset$crossAxis;
|
|
528
|
-
const {
|
|
529
|
-
x,
|
|
530
|
-
y,
|
|
531
|
-
placement,
|
|
532
|
-
rects,
|
|
533
|
-
middlewareData
|
|
534
|
-
} = state;
|
|
535
|
-
const {
|
|
536
|
-
offset = 0,
|
|
537
|
-
mainAxis: checkMainAxis = true,
|
|
538
|
-
crossAxis: checkCrossAxis = true
|
|
539
|
-
} = evaluate(options, state);
|
|
540
|
-
const coords = {
|
|
541
|
-
x,
|
|
542
|
-
y
|
|
543
|
-
};
|
|
544
|
-
const crossAxis = getSideAxis(placement);
|
|
545
|
-
const mainAxis = getOppositeAxis(crossAxis);
|
|
546
|
-
let mainAxisCoord = coords[mainAxis];
|
|
547
|
-
let crossAxisCoord = coords[crossAxis];
|
|
548
|
-
const rawOffset = evaluate(offset, state);
|
|
549
|
-
const computedOffset = typeof rawOffset === 'number' ? {
|
|
550
|
-
mainAxis: rawOffset,
|
|
551
|
-
crossAxis: 0
|
|
552
|
-
} : {
|
|
553
|
-
mainAxis: (_rawOffset$mainAxis = rawOffset.mainAxis) != null ? _rawOffset$mainAxis : 0,
|
|
554
|
-
crossAxis: (_rawOffset$crossAxis = rawOffset.crossAxis) != null ? _rawOffset$crossAxis : 0
|
|
555
|
-
};
|
|
556
|
-
if (checkMainAxis) {
|
|
557
|
-
const len = mainAxis === 'y' ? 'height' : 'width';
|
|
558
|
-
const limitMin = rects.reference[mainAxis] - rects.floating[len] + computedOffset.mainAxis;
|
|
559
|
-
const limitMax = rects.reference[mainAxis] + rects.reference[len] - computedOffset.mainAxis;
|
|
560
|
-
if (mainAxisCoord < limitMin) {
|
|
561
|
-
mainAxisCoord = limitMin;
|
|
562
|
-
} else if (mainAxisCoord > limitMax) {
|
|
563
|
-
mainAxisCoord = limitMax;
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
if (checkCrossAxis) {
|
|
567
|
-
var _middlewareData$offse, _middlewareData$offse2;
|
|
568
|
-
const len = mainAxis === 'y' ? 'width' : 'height';
|
|
569
|
-
const isOriginSide = originSides.has(getSide(placement));
|
|
570
|
-
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);
|
|
571
|
-
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);
|
|
572
|
-
if (crossAxisCoord < limitMin) {
|
|
573
|
-
crossAxisCoord = limitMin;
|
|
574
|
-
} else if (crossAxisCoord > limitMax) {
|
|
575
|
-
crossAxisCoord = limitMax;
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
return {
|
|
579
|
-
[mainAxis]: mainAxisCoord,
|
|
580
|
-
[crossAxis]: crossAxisCoord
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
};
|
|
584
|
-
};
|
|
585
|
-
|
|
586
|
-
// Method syntax keeps callback parameters bivariant, but expressing the
|
|
587
|
-
// explicit `| undefined` required by `exactOptionalPropertyTypes` needs
|
|
588
|
-
// property syntax, which is contravariant under `strictFunctionTypes`.
|
|
589
|
-
// Extracting the function from a method position restores that bivariance so
|
|
590
|
-
// consumers can still assign callbacks with narrower parameter types.
|
|
591
|
-
|
|
592
|
-
/**
|
|
593
|
-
* Provides data that allows you to change the size of the floating element —
|
|
594
|
-
* for instance, prevent it from overflowing the clipping boundary or match the
|
|
595
|
-
* width of the reference element.
|
|
596
|
-
* @see https://floating-ui.com/docs/size
|
|
597
|
-
*/
|
|
598
|
-
const size$2 = function (options) {
|
|
599
|
-
if (options === void 0) {
|
|
600
|
-
options = {};
|
|
601
|
-
}
|
|
602
|
-
return {
|
|
603
|
-
name: 'size',
|
|
604
|
-
options,
|
|
605
|
-
async fn(state) {
|
|
606
|
-
const {
|
|
607
|
-
placement,
|
|
608
|
-
rects,
|
|
609
|
-
platform,
|
|
610
|
-
elements
|
|
611
|
-
} = state;
|
|
612
|
-
const {
|
|
613
|
-
apply = () => {},
|
|
614
|
-
...detectOverflowOptions
|
|
615
|
-
} = evaluate(options, state);
|
|
616
|
-
const overflow = await platform.detectOverflow(state, detectOverflowOptions);
|
|
617
|
-
const side = getSide(placement);
|
|
618
|
-
const alignment = getAlignment(placement);
|
|
619
|
-
const isYAxis = getSideAxis(placement) === 'y';
|
|
620
|
-
const {
|
|
621
|
-
width,
|
|
622
|
-
height
|
|
623
|
-
} = rects.floating;
|
|
624
|
-
let heightSide;
|
|
625
|
-
let widthSide;
|
|
626
|
-
if (side === 'top' || side === 'bottom') {
|
|
627
|
-
heightSide = side;
|
|
628
|
-
widthSide = alignment === ((await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating))) ? 'start' : 'end') ? 'left' : 'right';
|
|
629
|
-
} else {
|
|
630
|
-
widthSide = side;
|
|
631
|
-
heightSide = alignment === 'end' ? 'top' : 'bottom';
|
|
632
|
-
}
|
|
633
|
-
const maximumClippingHeight = height - overflow.top - overflow.bottom;
|
|
634
|
-
const maximumClippingWidth = width - overflow.left - overflow.right;
|
|
635
|
-
const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight);
|
|
636
|
-
const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth);
|
|
637
|
-
const shiftData = state.middlewareData.shift;
|
|
638
|
-
const noShift = !shiftData;
|
|
639
|
-
let availableHeight = overflowAvailableHeight;
|
|
640
|
-
let availableWidth = overflowAvailableWidth;
|
|
641
|
-
if (shiftData != null && shiftData.enabled.x) {
|
|
642
|
-
availableWidth = maximumClippingWidth;
|
|
643
|
-
}
|
|
644
|
-
if (shiftData != null && shiftData.enabled.y) {
|
|
645
|
-
availableHeight = maximumClippingHeight;
|
|
646
|
-
}
|
|
647
|
-
if (noShift && !alignment) {
|
|
648
|
-
if (isYAxis) {
|
|
649
|
-
availableWidth = width - 2 * max(overflow.left, overflow.right);
|
|
650
|
-
} else {
|
|
651
|
-
availableHeight = height - 2 * max(overflow.top, overflow.bottom);
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
await apply({
|
|
655
|
-
...state,
|
|
656
|
-
availableWidth,
|
|
657
|
-
availableHeight
|
|
658
|
-
});
|
|
659
|
-
const nextDimensions = await platform.getDimensions(elements.floating);
|
|
660
|
-
if (width !== nextDimensions.width || height !== nextDimensions.height) {
|
|
661
|
-
return {
|
|
662
|
-
reset: {
|
|
663
|
-
rects: true
|
|
664
|
-
}
|
|
665
|
-
};
|
|
666
|
-
}
|
|
667
|
-
return {};
|
|
668
|
-
}
|
|
669
|
-
};
|
|
670
|
-
};
|
|
671
|
-
|
|
672
|
-
function getCssDimensions(element) {
|
|
673
|
-
const css = getComputedStyle$1(element);
|
|
674
|
-
// In testing environments, the `width` and `height` properties are empty
|
|
675
|
-
// strings for SVG elements, returning NaN. Fallback to `0` in this case.
|
|
676
|
-
let width = parseFloat(css.width) || 0;
|
|
677
|
-
let height = parseFloat(css.height) || 0;
|
|
678
|
-
const hasOffset = isHTMLElement(element);
|
|
679
|
-
const offsetWidth = hasOffset ? element.offsetWidth : width;
|
|
680
|
-
const offsetHeight = hasOffset ? element.offsetHeight : height;
|
|
681
|
-
const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;
|
|
682
|
-
if (shouldFallback) {
|
|
683
|
-
width = offsetWidth;
|
|
684
|
-
height = offsetHeight;
|
|
685
|
-
}
|
|
686
|
-
return {
|
|
687
|
-
width,
|
|
688
|
-
height,
|
|
689
|
-
$: shouldFallback
|
|
690
|
-
};
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
function unwrapElement(element) {
|
|
694
|
-
return !isElement(element) ? element.contextElement : element;
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
function getScale(element) {
|
|
698
|
-
const domElement = unwrapElement(element);
|
|
699
|
-
if (!isHTMLElement(domElement)) {
|
|
700
|
-
return createCoords(1);
|
|
701
|
-
}
|
|
702
|
-
const rect = domElement.getBoundingClientRect();
|
|
703
|
-
const {
|
|
704
|
-
width,
|
|
705
|
-
height,
|
|
706
|
-
$
|
|
707
|
-
} = getCssDimensions(domElement);
|
|
708
|
-
let x = ($ ? round(rect.width) : rect.width) / width;
|
|
709
|
-
let y = ($ ? round(rect.height) : rect.height) / height;
|
|
710
|
-
|
|
711
|
-
// 0, NaN, or Infinity should always fallback to 1.
|
|
712
|
-
|
|
713
|
-
if (!x || !Number.isFinite(x)) {
|
|
714
|
-
x = 1;
|
|
715
|
-
}
|
|
716
|
-
if (!y || !Number.isFinite(y)) {
|
|
717
|
-
y = 1;
|
|
718
|
-
}
|
|
719
|
-
return {
|
|
720
|
-
x,
|
|
721
|
-
y
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
const noOffsets = /*#__PURE__*/createCoords(0);
|
|
726
|
-
function getVisualOffsets(element) {
|
|
727
|
-
const win = getWindow(element);
|
|
728
|
-
if (!isWebKit() || !win.visualViewport) {
|
|
729
|
-
return noOffsets;
|
|
730
|
-
}
|
|
731
|
-
return {
|
|
732
|
-
x: win.visualViewport.offsetLeft,
|
|
733
|
-
y: win.visualViewport.offsetTop
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
|
|
737
|
-
if (isFixed === void 0) {
|
|
738
|
-
isFixed = false;
|
|
739
|
-
}
|
|
740
|
-
return !!floatingOffsetParent && isFixed && floatingOffsetParent === getWindow(element);
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
|
|
744
|
-
if (includeScale === void 0) {
|
|
745
|
-
includeScale = false;
|
|
746
|
-
}
|
|
747
|
-
if (isFixedStrategy === void 0) {
|
|
748
|
-
isFixedStrategy = false;
|
|
749
|
-
}
|
|
750
|
-
const clientRect = element.getBoundingClientRect();
|
|
751
|
-
const domElement = unwrapElement(element);
|
|
752
|
-
let scale = createCoords(1);
|
|
753
|
-
if (includeScale) {
|
|
754
|
-
if (offsetParent) {
|
|
755
|
-
if (isElement(offsetParent)) {
|
|
756
|
-
scale = getScale(offsetParent);
|
|
757
|
-
}
|
|
758
|
-
} else {
|
|
759
|
-
scale = getScale(element);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);
|
|
763
|
-
let x = (clientRect.left + visualOffsets.x) / scale.x;
|
|
764
|
-
let y = (clientRect.top + visualOffsets.y) / scale.y;
|
|
765
|
-
let width = clientRect.width / scale.x;
|
|
766
|
-
let height = clientRect.height / scale.y;
|
|
767
|
-
if (domElement && offsetParent) {
|
|
768
|
-
const win = getWindow(domElement);
|
|
769
|
-
const offsetWin = isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
|
|
770
|
-
let currentWin = win;
|
|
771
|
-
let currentIFrame = getFrameElement(currentWin);
|
|
772
|
-
while (currentIFrame && offsetWin !== currentWin) {
|
|
773
|
-
const iframeScale = getScale(currentIFrame);
|
|
774
|
-
const iframeRect = currentIFrame.getBoundingClientRect();
|
|
775
|
-
const css = getComputedStyle$1(currentIFrame);
|
|
776
|
-
const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
|
|
777
|
-
const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
|
|
778
|
-
x *= iframeScale.x;
|
|
779
|
-
y *= iframeScale.y;
|
|
780
|
-
width *= iframeScale.x;
|
|
781
|
-
height *= iframeScale.y;
|
|
782
|
-
x += left;
|
|
783
|
-
y += top;
|
|
784
|
-
currentWin = getWindow(currentIFrame);
|
|
785
|
-
currentIFrame = getFrameElement(currentWin);
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
return rectToClientRect({
|
|
789
|
-
width,
|
|
790
|
-
height,
|
|
791
|
-
x,
|
|
792
|
-
y
|
|
793
|
-
});
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
// If <html> has a CSS width greater than the viewport, then this will be
|
|
797
|
-
// incorrect for RTL.
|
|
798
|
-
function getWindowScrollBarX(element, rect) {
|
|
799
|
-
const leftScroll = getNodeScroll(element).scrollLeft;
|
|
800
|
-
if (!rect) {
|
|
801
|
-
return getBoundingClientRect(getDocumentElement(element)).left + leftScroll;
|
|
802
|
-
}
|
|
803
|
-
return rect.left + leftScroll;
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
function getHTMLOffset(documentElement, scroll) {
|
|
807
|
-
const htmlRect = documentElement.getBoundingClientRect();
|
|
808
|
-
const x = htmlRect.left + scroll.scrollLeft - getWindowScrollBarX(documentElement, htmlRect);
|
|
809
|
-
const y = htmlRect.top + scroll.scrollTop;
|
|
810
|
-
return {
|
|
811
|
-
x,
|
|
812
|
-
y
|
|
813
|
-
};
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
|
|
817
|
-
let {
|
|
818
|
-
elements,
|
|
819
|
-
rect,
|
|
820
|
-
offsetParent,
|
|
821
|
-
strategy
|
|
822
|
-
} = _ref;
|
|
823
|
-
const isFixed = strategy === 'fixed';
|
|
824
|
-
const documentElement = getDocumentElement(offsetParent);
|
|
825
|
-
const topLayer = elements ? isTopLayer(elements.floating) : false;
|
|
826
|
-
if (offsetParent === documentElement || topLayer && isFixed) {
|
|
827
|
-
return rect;
|
|
828
|
-
}
|
|
829
|
-
let scroll = {
|
|
830
|
-
scrollLeft: 0,
|
|
831
|
-
scrollTop: 0
|
|
832
|
-
};
|
|
833
|
-
let scale = createCoords(1);
|
|
834
|
-
const offsets = createCoords(0);
|
|
835
|
-
const isOffsetParentAnElement = isHTMLElement(offsetParent);
|
|
836
|
-
if (isOffsetParentAnElement || !isFixed) {
|
|
837
|
-
if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
|
|
838
|
-
scroll = getNodeScroll(offsetParent);
|
|
839
|
-
}
|
|
840
|
-
if (isOffsetParentAnElement) {
|
|
841
|
-
const offsetRect = getBoundingClientRect(offsetParent);
|
|
842
|
-
scale = getScale(offsetParent);
|
|
843
|
-
offsets.x = offsetRect.x + offsetParent.clientLeft;
|
|
844
|
-
offsets.y = offsetRect.y + offsetParent.clientTop;
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
|
|
848
|
-
return {
|
|
849
|
-
width: rect.width * scale.x,
|
|
850
|
-
height: rect.height * scale.y,
|
|
851
|
-
x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x,
|
|
852
|
-
y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y
|
|
853
|
-
};
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
function getClientRects(element) {
|
|
857
|
-
return element.getClientRects ? Array.from(element.getClientRects()) : [];
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
// Gets the entire size of the scrollable document area, even extending outside
|
|
861
|
-
// of the `<html>` and `<body>` rect bounds if horizontally scrollable.
|
|
862
|
-
function getDocumentRect(html) {
|
|
863
|
-
const scroll = getNodeScroll(html);
|
|
864
|
-
const body = html.ownerDocument.body;
|
|
865
|
-
const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
|
|
866
|
-
const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
|
|
867
|
-
let x = -scroll.scrollLeft + getWindowScrollBarX(html);
|
|
868
|
-
const y = -scroll.scrollTop;
|
|
869
|
-
if (getComputedStyle$1(body).direction === 'rtl') {
|
|
870
|
-
x += max(html.clientWidth, body.clientWidth) - width;
|
|
871
|
-
}
|
|
872
|
-
return {
|
|
873
|
-
width,
|
|
874
|
-
height,
|
|
875
|
-
x,
|
|
876
|
-
y
|
|
877
|
-
};
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
// Safety check: ensure the scrollbar space is reasonable in case this
|
|
881
|
-
// calculation is affected by unusual styles.
|
|
882
|
-
// Most scrollbars leave 15-18px of space.
|
|
883
|
-
const SCROLLBAR_MAX = 25;
|
|
884
|
-
function getViewportRect(element, strategy, rootBoundary) {
|
|
885
|
-
if (rootBoundary === void 0) {
|
|
886
|
-
rootBoundary = 'viewport';
|
|
887
|
-
}
|
|
888
|
-
const isLayoutViewport = rootBoundary === 'layoutViewport';
|
|
889
|
-
const win = getWindow(element);
|
|
890
|
-
const html = getDocumentElement(element);
|
|
891
|
-
const visualViewport = win.visualViewport;
|
|
892
|
-
let width = html.clientWidth;
|
|
893
|
-
let height = html.clientHeight;
|
|
894
|
-
let x = 0;
|
|
895
|
-
let y = 0;
|
|
896
|
-
if (visualViewport) {
|
|
897
|
-
// Client coordinates are relative to the layout viewport, except in
|
|
898
|
-
// WebKit with an `absolute` strategy, where they are relative to the
|
|
899
|
-
// visual viewport.
|
|
900
|
-
const layoutRelativeClientCoords = !isWebKit() || strategy === 'fixed';
|
|
901
|
-
if (isLayoutViewport) {
|
|
902
|
-
if (!layoutRelativeClientCoords) {
|
|
903
|
-
x = -visualViewport.offsetLeft;
|
|
904
|
-
y = -visualViewport.offsetTop;
|
|
905
|
-
}
|
|
906
|
-
} else {
|
|
907
|
-
width = visualViewport.width;
|
|
908
|
-
height = visualViewport.height;
|
|
909
|
-
if (layoutRelativeClientCoords) {
|
|
910
|
-
x = visualViewport.offsetLeft;
|
|
911
|
-
y = visualViewport.offsetTop;
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
const windowScrollbarX = getWindowScrollBarX(html);
|
|
916
|
-
// `scrollbar-gutter: stable` on the <html> reserves gutter space that shrinks
|
|
917
|
-
// the visual width but isn't reflected in `html.clientWidth`, so subtract it.
|
|
918
|
-
// Only the inline-end (right) gutter can hold the scrollbar; `both-edges` also
|
|
919
|
-
// reserves an empty inline-start gutter that clips nothing, so exclude just
|
|
920
|
-
// the one scrollbar-side gutter — halve the measured (two-gutter) total. A
|
|
921
|
-
// left-side scrollbar (`windowScrollbarX > 0`) is already handled by
|
|
922
|
-
// `getHTMLOffset`/`visualViewport.width`; skip it here.
|
|
923
|
-
if (windowScrollbarX <= 0) {
|
|
924
|
-
const doc = html.ownerDocument;
|
|
925
|
-
const body = doc.body;
|
|
926
|
-
const bodyStyles = getComputedStyle(body);
|
|
927
|
-
const bodyMarginInline = doc.compatMode === 'CSS1Compat' ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0;
|
|
928
|
-
const reservedWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);
|
|
929
|
-
const gutter = getComputedStyle(html).scrollbarGutter === 'stable both-edges' ? reservedWidth / 2 : reservedWidth;
|
|
930
|
-
if (gutter <= SCROLLBAR_MAX) {
|
|
931
|
-
width -= gutter;
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
return {
|
|
935
|
-
width,
|
|
936
|
-
height,
|
|
937
|
-
x,
|
|
938
|
-
y
|
|
939
|
-
};
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
// Returns the inner client rect, subtracting scrollbars if present.
|
|
943
|
-
function getInnerBoundingClientRect(element, strategy) {
|
|
944
|
-
const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
|
|
945
|
-
const top = clientRect.top + element.clientTop;
|
|
946
|
-
const left = clientRect.left + element.clientLeft;
|
|
947
|
-
const scale = getScale(element);
|
|
948
|
-
const width = element.clientWidth * scale.x;
|
|
949
|
-
const height = element.clientHeight * scale.y;
|
|
950
|
-
const x = left * scale.x;
|
|
951
|
-
const y = top * scale.y;
|
|
952
|
-
return {
|
|
953
|
-
width,
|
|
954
|
-
height,
|
|
955
|
-
x,
|
|
956
|
-
y
|
|
957
|
-
};
|
|
958
|
-
}
|
|
959
|
-
function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
|
|
960
|
-
let rect;
|
|
961
|
-
if (clippingAncestor === 'viewport' || clippingAncestor === 'layoutViewport') {
|
|
962
|
-
rect = getViewportRect(element, strategy, clippingAncestor);
|
|
963
|
-
} else if (clippingAncestor === 'document') {
|
|
964
|
-
rect = getDocumentRect(getDocumentElement(element));
|
|
965
|
-
} else if (isElement(clippingAncestor)) {
|
|
966
|
-
rect = getInnerBoundingClientRect(clippingAncestor, strategy);
|
|
967
|
-
} else {
|
|
968
|
-
const visualOffsets = getVisualOffsets(element);
|
|
969
|
-
rect = {
|
|
970
|
-
x: clippingAncestor.x - visualOffsets.x,
|
|
971
|
-
y: clippingAncestor.y - visualOffsets.y,
|
|
972
|
-
width: clippingAncestor.width,
|
|
973
|
-
height: clippingAncestor.height
|
|
974
|
-
};
|
|
975
|
-
}
|
|
976
|
-
return rectToClientRect(rect);
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
// A "clipping ancestor" is an `overflow` element with the characteristic of
|
|
980
|
-
// clipping (or hiding) child elements. This returns all clipping ancestors
|
|
981
|
-
// of the given element up the tree.
|
|
982
|
-
function getClippingElementAncestors(element, cache) {
|
|
983
|
-
const cachedResult = cache.get(element);
|
|
984
|
-
if (cachedResult) {
|
|
985
|
-
return cachedResult;
|
|
986
|
-
}
|
|
987
|
-
let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');
|
|
988
|
-
let lastKeptComputedStyle = null;
|
|
989
|
-
const elementIsFixed = getComputedStyle$1(element).position === 'fixed';
|
|
990
|
-
let currentNode = elementIsFixed ? getParentNode(element) : element;
|
|
991
|
-
|
|
992
|
-
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
|
|
993
|
-
while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
|
|
994
|
-
const computedStyle = getComputedStyle$1(currentNode);
|
|
995
|
-
const currentNodeIsContaining = isContainingBlock(currentNode);
|
|
996
|
-
// Position of the containing block chain below the current node. A fixed
|
|
997
|
-
// element whose containing block hasn't been found yet is a fixed chain.
|
|
998
|
-
const lastPosition = lastKeptComputedStyle ? lastKeptComputedStyle.position : elementIsFixed ? 'fixed' : '';
|
|
999
|
-
|
|
1000
|
-
// A non-containing ancestor does not clip the element when the chain
|
|
1001
|
-
// below it escapes it: a fixed chain escapes all ancestors up to the
|
|
1002
|
-
// next containing block, an absolute chain escapes static ancestors.
|
|
1003
|
-
const shouldDropCurrentNode = !currentNodeIsContaining && (lastPosition === 'fixed' || lastPosition === 'absolute' && computedStyle.position === 'static');
|
|
1004
|
-
if (shouldDropCurrentNode) {
|
|
1005
|
-
// Drop non-containing blocks.
|
|
1006
|
-
result = result.filter(ancestor => ancestor !== currentNode);
|
|
1007
|
-
} else {
|
|
1008
|
-
// The kept node carries the chain position for the next iteration.
|
|
1009
|
-
lastKeptComputedStyle = computedStyle;
|
|
1010
|
-
}
|
|
1011
|
-
currentNode = getParentNode(currentNode);
|
|
1012
|
-
}
|
|
1013
|
-
cache.set(element, result);
|
|
1014
|
-
return result;
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
// Gets the maximum area that the element is visible in due to any number of
|
|
1018
|
-
// clipping ancestors.
|
|
1019
|
-
function getClippingRect(_ref) {
|
|
1020
|
-
let {
|
|
1021
|
-
element,
|
|
1022
|
-
boundary,
|
|
1023
|
-
rootBoundary,
|
|
1024
|
-
strategy
|
|
1025
|
-
} = _ref;
|
|
1026
|
-
const elementClippingAncestors = boundary === 'clippingAncestors' ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary);
|
|
1027
|
-
const clippingAncestors = [...elementClippingAncestors, rootBoundary];
|
|
1028
|
-
const firstRect = getClientRectFromClippingAncestor(element, clippingAncestors[0], strategy);
|
|
1029
|
-
let top = firstRect.top;
|
|
1030
|
-
let right = firstRect.right;
|
|
1031
|
-
let bottom = firstRect.bottom;
|
|
1032
|
-
let left = firstRect.left;
|
|
1033
|
-
for (let i = 1; i < clippingAncestors.length; i++) {
|
|
1034
|
-
const rect = getClientRectFromClippingAncestor(element, clippingAncestors[i], strategy);
|
|
1035
|
-
top = max(rect.top, top);
|
|
1036
|
-
right = min(rect.right, right);
|
|
1037
|
-
bottom = min(rect.bottom, bottom);
|
|
1038
|
-
left = max(rect.left, left);
|
|
1039
|
-
}
|
|
1040
|
-
return {
|
|
1041
|
-
width: right - left,
|
|
1042
|
-
height: bottom - top,
|
|
1043
|
-
x: left,
|
|
1044
|
-
y: top
|
|
1045
|
-
};
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
function getDimensions(element) {
|
|
1049
|
-
const {
|
|
1050
|
-
width,
|
|
1051
|
-
height
|
|
1052
|
-
} = getCssDimensions(element);
|
|
1053
|
-
return {
|
|
1054
|
-
width,
|
|
1055
|
-
height
|
|
1056
|
-
};
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
|
|
1060
|
-
const isOffsetParentAnElement = isHTMLElement(offsetParent);
|
|
1061
|
-
const documentElement = getDocumentElement(offsetParent);
|
|
1062
|
-
const isFixed = strategy === 'fixed';
|
|
1063
|
-
const rect = getBoundingClientRect(element, true, isFixed, offsetParent);
|
|
1064
|
-
let scroll = {
|
|
1065
|
-
scrollLeft: 0,
|
|
1066
|
-
scrollTop: 0
|
|
1067
|
-
};
|
|
1068
|
-
const offsets = createCoords(0);
|
|
1069
|
-
if (isOffsetParentAnElement || !isFixed) {
|
|
1070
|
-
if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
|
|
1071
|
-
scroll = getNodeScroll(offsetParent);
|
|
1072
|
-
}
|
|
1073
|
-
if (isOffsetParentAnElement) {
|
|
1074
|
-
const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
|
|
1075
|
-
offsets.x = offsetRect.x + offsetParent.clientLeft;
|
|
1076
|
-
offsets.y = offsetRect.y + offsetParent.clientTop;
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
// If the <body> scrollbar appears on the left (e.g. RTL systems). Use
|
|
1081
|
-
// Firefox with layout.scrollbar.side = 3 in about:config to test this.
|
|
1082
|
-
if (!isOffsetParentAnElement && documentElement) {
|
|
1083
|
-
offsets.x = getWindowScrollBarX(documentElement);
|
|
1084
|
-
}
|
|
1085
|
-
const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
|
|
1086
|
-
const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;
|
|
1087
|
-
const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y;
|
|
1088
|
-
return {
|
|
1089
|
-
x,
|
|
1090
|
-
y,
|
|
1091
|
-
width: rect.width,
|
|
1092
|
-
height: rect.height
|
|
1093
|
-
};
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
function isStaticPositioned(element) {
|
|
1097
|
-
return getComputedStyle$1(element).position === 'static';
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
function getTrueOffsetParent(element, polyfill) {
|
|
1101
|
-
if (!isHTMLElement(element) || getComputedStyle$1(element).position === 'fixed') {
|
|
1102
|
-
return null;
|
|
1103
|
-
}
|
|
1104
|
-
if (polyfill) {
|
|
1105
|
-
return polyfill(element);
|
|
1106
|
-
}
|
|
1107
|
-
let rawOffsetParent = element.offsetParent;
|
|
1108
|
-
|
|
1109
|
-
// Firefox returns the <html> element as the offsetParent if it's non-static,
|
|
1110
|
-
// while Chrome and Safari return the <body> element. The <body> element must
|
|
1111
|
-
// be used to perform the correct calculations even if the <html> element is
|
|
1112
|
-
// non-static.
|
|
1113
|
-
if (getDocumentElement(element) === rawOffsetParent) {
|
|
1114
|
-
rawOffsetParent = rawOffsetParent.ownerDocument.body;
|
|
1115
|
-
}
|
|
1116
|
-
return rawOffsetParent;
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
// Gets the closest ancestor positioned element. Handles some edge cases,
|
|
1120
|
-
// such as table ancestors and cross browser bugs.
|
|
1121
|
-
function getOffsetParent(element, polyfill) {
|
|
1122
|
-
const win = getWindow(element);
|
|
1123
|
-
if (isTopLayer(element)) {
|
|
1124
|
-
return win;
|
|
1125
|
-
}
|
|
1126
|
-
if (!isHTMLElement(element)) {
|
|
1127
|
-
let svgOffsetParent = getParentNode(element);
|
|
1128
|
-
while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) {
|
|
1129
|
-
if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) {
|
|
1130
|
-
return svgOffsetParent;
|
|
1131
|
-
}
|
|
1132
|
-
svgOffsetParent = getParentNode(svgOffsetParent);
|
|
1133
|
-
}
|
|
1134
|
-
return win;
|
|
1135
|
-
}
|
|
1136
|
-
let offsetParent = getTrueOffsetParent(element, polyfill);
|
|
1137
|
-
while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) {
|
|
1138
|
-
offsetParent = getTrueOffsetParent(offsetParent, polyfill);
|
|
1139
|
-
}
|
|
1140
|
-
if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) {
|
|
1141
|
-
return win;
|
|
1142
|
-
}
|
|
1143
|
-
return offsetParent || getContainingBlock(element) || win;
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
const getElementRects = async function (data) {
|
|
1147
|
-
const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
|
|
1148
|
-
const getDimensionsFn = this.getDimensions;
|
|
1149
|
-
const floatingDimensions = await getDimensionsFn(data.floating);
|
|
1150
|
-
return {
|
|
1151
|
-
reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),
|
|
1152
|
-
floating: {
|
|
1153
|
-
x: 0,
|
|
1154
|
-
y: 0,
|
|
1155
|
-
width: floatingDimensions.width,
|
|
1156
|
-
height: floatingDimensions.height
|
|
1157
|
-
}
|
|
1158
|
-
};
|
|
1159
|
-
};
|
|
1160
|
-
|
|
1161
|
-
function isRTL(element) {
|
|
1162
|
-
return getComputedStyle$1(element).direction === 'rtl';
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
const platform = {
|
|
1166
|
-
convertOffsetParentRelativeRectToViewportRelativeRect,
|
|
1167
|
-
getDocumentElement,
|
|
1168
|
-
getClippingRect,
|
|
1169
|
-
getOffsetParent,
|
|
1170
|
-
getElementRects,
|
|
1171
|
-
getClientRects,
|
|
1172
|
-
getDimensions,
|
|
1173
|
-
getScale,
|
|
1174
|
-
isElement,
|
|
1175
|
-
isRTL
|
|
1176
|
-
};
|
|
1177
|
-
|
|
1178
|
-
function rectsAreEqual(a, b) {
|
|
1179
|
-
return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
// https://samthor.au/2021/observing-dom/
|
|
1183
|
-
function observeMove(element, onMove, ancestorResize) {
|
|
1184
|
-
let io = null;
|
|
1185
|
-
let timeoutId;
|
|
1186
|
-
const root = getDocumentElement(element);
|
|
1187
|
-
function cleanup() {
|
|
1188
|
-
var _io;
|
|
1189
|
-
clearTimeout(timeoutId);
|
|
1190
|
-
(_io = io) == null || _io.disconnect();
|
|
1191
|
-
io = null;
|
|
1192
|
-
}
|
|
1193
|
-
function refresh(skip, threshold) {
|
|
1194
|
-
if (skip === void 0) {
|
|
1195
|
-
skip = false;
|
|
1196
|
-
}
|
|
1197
|
-
if (threshold === void 0) {
|
|
1198
|
-
threshold = 1;
|
|
1199
|
-
}
|
|
1200
|
-
cleanup();
|
|
1201
|
-
const elementRectForRootMargin = element.getBoundingClientRect();
|
|
1202
|
-
const {
|
|
1203
|
-
left,
|
|
1204
|
-
top,
|
|
1205
|
-
width,
|
|
1206
|
-
height
|
|
1207
|
-
} = elementRectForRootMargin;
|
|
1208
|
-
if (!skip) {
|
|
1209
|
-
onMove();
|
|
1210
|
-
}
|
|
1211
|
-
if (!width || !height) {
|
|
1212
|
-
return;
|
|
1213
|
-
}
|
|
1214
|
-
const insetTop = floor(top);
|
|
1215
|
-
const insetRight = floor(root.clientWidth - (left + width));
|
|
1216
|
-
const insetBottom = floor(root.clientHeight - (top + height));
|
|
1217
|
-
const insetLeft = floor(left);
|
|
1218
|
-
const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
|
|
1219
|
-
const options = {
|
|
1220
|
-
rootMargin,
|
|
1221
|
-
threshold: max(0, min(1, threshold)) || 1
|
|
1222
|
-
};
|
|
1223
|
-
let isFirstUpdate = true;
|
|
1224
|
-
function handleObserve(entries) {
|
|
1225
|
-
const ratio = entries[0].intersectionRatio;
|
|
1226
|
-
|
|
1227
|
-
// The entry is a snapshot, so the reference may have moved since the
|
|
1228
|
-
// intersection was computed (under performance constraints, or between
|
|
1229
|
-
// consecutive frames of a multi-frame layout shift). The reported ratio
|
|
1230
|
-
// and the observed area are stale in that case and cannot be trusted to
|
|
1231
|
-
// detect subsequent movement, so refresh regardless of the ratio.
|
|
1232
|
-
if (!rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
|
|
1233
|
-
return refresh();
|
|
1234
|
-
}
|
|
1235
|
-
if (ratio !== threshold) {
|
|
1236
|
-
if (!isFirstUpdate) {
|
|
1237
|
-
return refresh();
|
|
1238
|
-
}
|
|
1239
|
-
if (!ratio) {
|
|
1240
|
-
// If the reference is clipped in place, the ratio is 0. Throttle
|
|
1241
|
-
// the refresh to prevent an infinite loop of updates.
|
|
1242
|
-
timeoutId = setTimeout(() => {
|
|
1243
|
-
refresh(false, 1e-7);
|
|
1244
|
-
}, 1000);
|
|
1245
|
-
} else {
|
|
1246
|
-
refresh(false, ratio);
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
isFirstUpdate = false;
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
// Older browsers don't support a `document` as the root and will throw an
|
|
1253
|
-
// error.
|
|
1254
|
-
try {
|
|
1255
|
-
io = new IntersectionObserver(handleObserve, {
|
|
1256
|
-
...options,
|
|
1257
|
-
// Handle <iframe>s
|
|
1258
|
-
root: root.ownerDocument
|
|
1259
|
-
});
|
|
1260
|
-
} catch (_e) {
|
|
1261
|
-
io = new IntersectionObserver(handleObserve, options);
|
|
1262
|
-
}
|
|
1263
|
-
io.observe(element);
|
|
1264
|
-
}
|
|
1265
|
-
const win = getWindow(element);
|
|
1266
|
-
// The window is a resize ancestor, so when `ancestorResize` is enabled its
|
|
1267
|
-
// listener already runs the update on resize. Here we only need to rebuild
|
|
1268
|
-
// the `IntersectionObserver` for the new root size, skipping a redundant
|
|
1269
|
-
// update. When `ancestorResize` is disabled, this becomes the sole update.
|
|
1270
|
-
const handleResize = () => refresh(ancestorResize);
|
|
1271
|
-
win.addEventListener('resize', handleResize);
|
|
1272
|
-
refresh(true);
|
|
1273
|
-
return () => {
|
|
1274
|
-
win.removeEventListener('resize', handleResize);
|
|
1275
|
-
cleanup();
|
|
1276
|
-
};
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
/**
|
|
1280
|
-
* Automatically updates the position of the floating element when necessary.
|
|
1281
|
-
* Should only be called when the floating element is mounted on the DOM or
|
|
1282
|
-
* visible on the screen.
|
|
1283
|
-
* @returns cleanup function that should be invoked when the floating element is
|
|
1284
|
-
* removed from the DOM or hidden from the screen.
|
|
1285
|
-
* @see https://floating-ui.com/docs/autoUpdate
|
|
1286
|
-
*/
|
|
1287
|
-
function autoUpdate(reference, floating, update, options) {
|
|
1288
|
-
if (options === void 0) {
|
|
1289
|
-
options = {};
|
|
1290
|
-
}
|
|
1291
|
-
const {
|
|
1292
|
-
ancestorScroll = true,
|
|
1293
|
-
ancestorResize = true,
|
|
1294
|
-
elementResize = typeof ResizeObserver === 'function',
|
|
1295
|
-
layoutShift = typeof IntersectionObserver === 'function',
|
|
1296
|
-
animationFrame = false
|
|
1297
|
-
} = options;
|
|
1298
|
-
const referenceEl = unwrapElement(reference);
|
|
1299
|
-
const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...(floating ? getOverflowAncestors(floating) : [])] : [];
|
|
1300
|
-
ancestors.forEach(ancestor => {
|
|
1301
|
-
ancestorScroll && ancestor.addEventListener('scroll', update);
|
|
1302
|
-
ancestorResize && ancestor.addEventListener('resize', update);
|
|
1303
|
-
});
|
|
1304
|
-
const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update, ancestorResize) : null;
|
|
1305
|
-
let reobserveFrame = -1;
|
|
1306
|
-
let resizeObserver = null;
|
|
1307
|
-
if (elementResize) {
|
|
1308
|
-
resizeObserver = new ResizeObserver(_ref => {
|
|
1309
|
-
let [firstEntry] = _ref;
|
|
1310
|
-
if (firstEntry && firstEntry.target === referenceEl && resizeObserver && floating) {
|
|
1311
|
-
// Prevent update loops when using the `size` middleware.
|
|
1312
|
-
// https://github.com/floating-ui/floating-ui/issues/1740
|
|
1313
|
-
resizeObserver.unobserve(floating);
|
|
1314
|
-
cancelAnimationFrame(reobserveFrame);
|
|
1315
|
-
reobserveFrame = requestAnimationFrame(() => {
|
|
1316
|
-
var _resizeObserver;
|
|
1317
|
-
(_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);
|
|
1318
|
-
});
|
|
1319
|
-
}
|
|
1320
|
-
update();
|
|
1321
|
-
});
|
|
1322
|
-
if (referenceEl && !animationFrame) {
|
|
1323
|
-
resizeObserver.observe(referenceEl);
|
|
1324
|
-
}
|
|
1325
|
-
if (floating) {
|
|
1326
|
-
resizeObserver.observe(floating);
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
let frameId;
|
|
1330
|
-
let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
|
|
1331
|
-
if (animationFrame) {
|
|
1332
|
-
frameLoop();
|
|
1333
|
-
}
|
|
1334
|
-
function frameLoop() {
|
|
1335
|
-
const nextRefRect = getBoundingClientRect(reference);
|
|
1336
|
-
if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) {
|
|
1337
|
-
update();
|
|
1338
|
-
}
|
|
1339
|
-
prevRefRect = nextRefRect;
|
|
1340
|
-
frameId = requestAnimationFrame(frameLoop);
|
|
1341
|
-
}
|
|
1342
|
-
update();
|
|
1343
|
-
return () => {
|
|
1344
|
-
var _resizeObserver2;
|
|
1345
|
-
ancestors.forEach(ancestor => {
|
|
1346
|
-
ancestorScroll && ancestor.removeEventListener('scroll', update);
|
|
1347
|
-
ancestorResize && ancestor.removeEventListener('resize', update);
|
|
1348
|
-
});
|
|
1349
|
-
cleanupIo == null || cleanupIo();
|
|
1350
|
-
(_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();
|
|
1351
|
-
resizeObserver = null;
|
|
1352
|
-
if (animationFrame) {
|
|
1353
|
-
cancelAnimationFrame(frameId);
|
|
1354
|
-
}
|
|
1355
|
-
};
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
/**
|
|
1359
|
-
* Modifies the placement by translating the floating element along the
|
|
1360
|
-
* specified axes.
|
|
1361
|
-
* A number (shorthand for `mainAxis` or distance), or an axes configuration
|
|
1362
|
-
* object may be passed.
|
|
1363
|
-
* @see https://floating-ui.com/docs/offset
|
|
1364
|
-
*/
|
|
1365
|
-
const offset$1 = offset$2;
|
|
1366
|
-
|
|
1367
|
-
/**
|
|
1368
|
-
* Optimizes the visibility of the floating element by shifting it in order to
|
|
1369
|
-
* keep it in view when it will overflow the clipping boundary.
|
|
1370
|
-
* @see https://floating-ui.com/docs/shift
|
|
1371
|
-
*/
|
|
1372
|
-
const shift$1 = shift$2;
|
|
1373
|
-
|
|
1374
|
-
/**
|
|
1375
|
-
* Optimizes the visibility of the floating element by flipping the `placement`
|
|
1376
|
-
* in order to keep it in view when the preferred placement(s) will overflow the
|
|
1377
|
-
* clipping boundary. Alternative to `autoPlacement`.
|
|
1378
|
-
* @see https://floating-ui.com/docs/flip
|
|
1379
|
-
*/
|
|
1380
|
-
const flip$1 = flip$2;
|
|
1381
|
-
|
|
1382
|
-
/**
|
|
1383
|
-
* Provides data that allows you to change the size of the floating element —
|
|
1384
|
-
* for instance, prevent it from overflowing the clipping boundary or match the
|
|
1385
|
-
* width of the reference element.
|
|
1386
|
-
* @see https://floating-ui.com/docs/size
|
|
1387
|
-
*/
|
|
1388
|
-
const size$1 = size$2;
|
|
1389
|
-
|
|
1390
|
-
/**
|
|
1391
|
-
* Built-in `limiter` that will stop `shift()` at a certain point.
|
|
1392
|
-
*/
|
|
1393
|
-
const limitShift$1 = limitShift$2;
|
|
1394
|
-
|
|
1395
|
-
/**
|
|
1396
|
-
* Computes the `x` and `y` coordinates that will place the floating element
|
|
1397
|
-
* next to a given reference element.
|
|
1398
|
-
*/
|
|
1399
|
-
const computePosition = (reference, floating, options) => {
|
|
1400
|
-
// This caches the expensive `getClippingElementAncestors` function so that
|
|
1401
|
-
// multiple lifecycle resets re-use the same result. It only lives for a
|
|
1402
|
-
// single call. If other functions become expensive, we can add them as well.
|
|
1403
|
-
const cache = new Map();
|
|
1404
|
-
const mergedOptions = options != null ? options : {};
|
|
1405
|
-
const platformWithCache = {
|
|
1406
|
-
...platform,
|
|
1407
|
-
...mergedOptions.platform,
|
|
1408
|
-
_c: cache
|
|
1409
|
-
};
|
|
1410
|
-
return computePosition$1(reference, floating, {
|
|
1411
|
-
...mergedOptions,
|
|
1412
|
-
platform: platformWithCache
|
|
1413
|
-
});
|
|
1414
|
-
};
|
|
1415
|
-
|
|
1416
|
-
var isClient = typeof document !== 'undefined';
|
|
1417
|
-
|
|
1418
|
-
var noop = function noop() {};
|
|
1419
|
-
var index = isClient ? useLayoutEffect : noop;
|
|
1420
|
-
|
|
1421
|
-
// Fork of `fast-deep-equal` that only does the comparisons we need and compares
|
|
1422
|
-
// functions
|
|
1423
|
-
function deepEqual(a, b) {
|
|
1424
|
-
if (a === b) {
|
|
1425
|
-
return true;
|
|
1426
|
-
}
|
|
1427
|
-
if (typeof a !== typeof b) {
|
|
1428
|
-
return false;
|
|
1429
|
-
}
|
|
1430
|
-
if (typeof a === 'function' && a.toString() === b.toString()) {
|
|
1431
|
-
return true;
|
|
1432
|
-
}
|
|
1433
|
-
let length;
|
|
1434
|
-
let i;
|
|
1435
|
-
let keys;
|
|
1436
|
-
if (a && b && typeof a === 'object') {
|
|
1437
|
-
if (Array.isArray(a)) {
|
|
1438
|
-
length = a.length;
|
|
1439
|
-
if (length !== b.length) return false;
|
|
1440
|
-
for (i = length; i-- !== 0;) {
|
|
1441
|
-
if (!deepEqual(a[i], b[i])) {
|
|
1442
|
-
return false;
|
|
1443
|
-
}
|
|
1444
|
-
}
|
|
1445
|
-
return true;
|
|
1446
|
-
}
|
|
1447
|
-
keys = Object.keys(a);
|
|
1448
|
-
length = keys.length;
|
|
1449
|
-
if (length !== Object.keys(b).length) {
|
|
1450
|
-
return false;
|
|
1451
|
-
}
|
|
1452
|
-
for (i = length; i-- !== 0;) {
|
|
1453
|
-
if (!{}.hasOwnProperty.call(b, keys[i])) {
|
|
1454
|
-
return false;
|
|
1455
|
-
}
|
|
1456
|
-
}
|
|
1457
|
-
for (i = length; i-- !== 0;) {
|
|
1458
|
-
const key = keys[i];
|
|
1459
|
-
if (key === '_owner' && a.$$typeof) {
|
|
1460
|
-
continue;
|
|
1461
|
-
}
|
|
1462
|
-
if (!deepEqual(a[key], b[key])) {
|
|
1463
|
-
return false;
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
return true;
|
|
1467
|
-
}
|
|
1468
|
-
return a !== a && b !== b;
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
function getDPR(element) {
|
|
1472
|
-
if (typeof window === 'undefined') {
|
|
1473
|
-
return 1;
|
|
1474
|
-
}
|
|
1475
|
-
const win = element.ownerDocument.defaultView || window;
|
|
1476
|
-
return win.devicePixelRatio || 1;
|
|
1477
|
-
}
|
|
1478
|
-
|
|
1479
|
-
function roundByDPR(element, value) {
|
|
1480
|
-
const dpr = getDPR(element);
|
|
1481
|
-
return Math.round(value * dpr) / dpr;
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
function useLatestRef(value) {
|
|
1485
|
-
const ref = React.useRef(value);
|
|
1486
|
-
index(() => {
|
|
1487
|
-
ref.current = value;
|
|
1488
|
-
});
|
|
1489
|
-
return ref;
|
|
1490
|
-
}
|
|
1491
|
-
|
|
1492
|
-
/**
|
|
1493
|
-
* Provides data to position a floating element.
|
|
1494
|
-
* @see https://floating-ui.com/docs/useFloating
|
|
1495
|
-
*/
|
|
1496
|
-
function useFloating(options) {
|
|
1497
|
-
if (options === void 0) {
|
|
1498
|
-
options = {};
|
|
1499
|
-
}
|
|
1500
|
-
const {
|
|
1501
|
-
placement = 'bottom',
|
|
1502
|
-
strategy = 'absolute',
|
|
1503
|
-
middleware = [],
|
|
1504
|
-
platform,
|
|
1505
|
-
elements: {
|
|
1506
|
-
reference: externalReference,
|
|
1507
|
-
floating: externalFloating
|
|
1508
|
-
} = {},
|
|
1509
|
-
transform = true,
|
|
1510
|
-
whileElementsMounted,
|
|
1511
|
-
open
|
|
1512
|
-
} = options;
|
|
1513
|
-
const [data, setData] = React.useState({
|
|
1514
|
-
x: 0,
|
|
1515
|
-
y: 0,
|
|
1516
|
-
strategy,
|
|
1517
|
-
placement,
|
|
1518
|
-
middlewareData: {},
|
|
1519
|
-
isPositioned: false
|
|
1520
|
-
});
|
|
1521
|
-
const [latestMiddleware, setLatestMiddleware] = React.useState(middleware);
|
|
1522
|
-
if (!deepEqual(latestMiddleware, middleware)) {
|
|
1523
|
-
setLatestMiddleware(middleware);
|
|
1524
|
-
}
|
|
1525
|
-
const [_reference, _setReference] = React.useState(null);
|
|
1526
|
-
const [_floating, _setFloating] = React.useState(null);
|
|
1527
|
-
const setReference = React.useCallback(node => {
|
|
1528
|
-
if (node !== referenceRef.current) {
|
|
1529
|
-
referenceRef.current = node;
|
|
1530
|
-
_setReference(node);
|
|
1531
|
-
}
|
|
1532
|
-
}, []);
|
|
1533
|
-
const setFloating = React.useCallback(node => {
|
|
1534
|
-
if (node !== floatingRef.current) {
|
|
1535
|
-
floatingRef.current = node;
|
|
1536
|
-
_setFloating(node);
|
|
1537
|
-
}
|
|
1538
|
-
}, []);
|
|
1539
|
-
const referenceEl = externalReference || _reference;
|
|
1540
|
-
const floatingEl = externalFloating || _floating;
|
|
1541
|
-
const referenceRef = React.useRef(null);
|
|
1542
|
-
const floatingRef = React.useRef(null);
|
|
1543
|
-
const dataRef = React.useRef(data);
|
|
1544
|
-
const hasWhileElementsMounted = whileElementsMounted != null;
|
|
1545
|
-
const whileElementsMountedRef = useLatestRef(whileElementsMounted);
|
|
1546
|
-
const platformRef = useLatestRef(platform);
|
|
1547
|
-
const openRef = useLatestRef(open);
|
|
1548
|
-
const update = React.useCallback(() => {
|
|
1549
|
-
if (!referenceRef.current || !floatingRef.current) {
|
|
1550
|
-
return;
|
|
1551
|
-
}
|
|
1552
|
-
const config = {
|
|
1553
|
-
placement,
|
|
1554
|
-
strategy,
|
|
1555
|
-
middleware: latestMiddleware
|
|
1556
|
-
};
|
|
1557
|
-
if (platformRef.current) {
|
|
1558
|
-
config.platform = platformRef.current;
|
|
1559
|
-
}
|
|
1560
|
-
computePosition(referenceRef.current, floatingRef.current, config).then(data => {
|
|
1561
|
-
const fullData = {
|
|
1562
|
-
...data,
|
|
1563
|
-
// The floating element's position may be recomputed while it's closed
|
|
1564
|
-
// but still mounted (such as when transitioning out). To ensure
|
|
1565
|
-
// `isPositioned` will be `false` initially on the next open, avoid
|
|
1566
|
-
// setting it to `true` when `open === false` (must be specified).
|
|
1567
|
-
isPositioned: openRef.current !== false
|
|
1568
|
-
};
|
|
1569
|
-
if (isMountedRef.current && !deepEqual(dataRef.current, fullData)) {
|
|
1570
|
-
dataRef.current = fullData;
|
|
1571
|
-
ReactDOM.flushSync(() => {
|
|
1572
|
-
setData(fullData);
|
|
1573
|
-
});
|
|
1574
|
-
}
|
|
1575
|
-
});
|
|
1576
|
-
}, [latestMiddleware, placement, strategy, platformRef, openRef]);
|
|
1577
|
-
index(() => {
|
|
1578
|
-
if (open === false && dataRef.current.isPositioned) {
|
|
1579
|
-
dataRef.current.isPositioned = false;
|
|
1580
|
-
setData(data => ({
|
|
1581
|
-
...data,
|
|
1582
|
-
isPositioned: false
|
|
1583
|
-
}));
|
|
1584
|
-
}
|
|
1585
|
-
}, [open]);
|
|
1586
|
-
const isMountedRef = React.useRef(false);
|
|
1587
|
-
index(() => {
|
|
1588
|
-
isMountedRef.current = true;
|
|
1589
|
-
return () => {
|
|
1590
|
-
isMountedRef.current = false;
|
|
1591
|
-
};
|
|
1592
|
-
}, []);
|
|
1593
|
-
index(() => {
|
|
1594
|
-
if (referenceEl) referenceRef.current = referenceEl;
|
|
1595
|
-
if (floatingEl) floatingRef.current = floatingEl;
|
|
1596
|
-
if (referenceEl && floatingEl) {
|
|
1597
|
-
if (whileElementsMountedRef.current) {
|
|
1598
|
-
return whileElementsMountedRef.current(referenceEl, floatingEl, update);
|
|
1599
|
-
}
|
|
1600
|
-
update();
|
|
1601
|
-
}
|
|
1602
|
-
}, [referenceEl, floatingEl, update, whileElementsMountedRef, hasWhileElementsMounted]);
|
|
1603
|
-
const refs = React.useMemo(() => ({
|
|
1604
|
-
reference: referenceRef,
|
|
1605
|
-
floating: floatingRef,
|
|
1606
|
-
setReference,
|
|
1607
|
-
setFloating
|
|
1608
|
-
}), [setReference, setFloating]);
|
|
1609
|
-
const elements = React.useMemo(() => ({
|
|
1610
|
-
reference: referenceEl,
|
|
1611
|
-
floating: floatingEl
|
|
1612
|
-
}), [referenceEl, floatingEl]);
|
|
1613
|
-
const floatingStyles = React.useMemo(() => {
|
|
1614
|
-
const initialStyles = {
|
|
1615
|
-
position: strategy,
|
|
1616
|
-
left: 0,
|
|
1617
|
-
top: 0
|
|
1618
|
-
};
|
|
1619
|
-
if (!elements.floating) {
|
|
1620
|
-
return initialStyles;
|
|
1621
|
-
}
|
|
1622
|
-
const x = roundByDPR(elements.floating, data.x);
|
|
1623
|
-
const y = roundByDPR(elements.floating, data.y);
|
|
1624
|
-
if (transform) {
|
|
1625
|
-
return {
|
|
1626
|
-
...initialStyles,
|
|
1627
|
-
transform: "translate(" + x + "px, " + y + "px)",
|
|
1628
|
-
...(getDPR(elements.floating) >= 1.5 && {
|
|
1629
|
-
willChange: 'transform'
|
|
1630
|
-
})
|
|
1631
|
-
};
|
|
1632
|
-
}
|
|
1633
|
-
return {
|
|
1634
|
-
position: strategy,
|
|
1635
|
-
left: x,
|
|
1636
|
-
top: y
|
|
1637
|
-
};
|
|
1638
|
-
}, [strategy, transform, elements.floating, data.x, data.y]);
|
|
1639
|
-
return React.useMemo(() => ({
|
|
1640
|
-
...data,
|
|
1641
|
-
update,
|
|
1642
|
-
refs,
|
|
1643
|
-
elements,
|
|
1644
|
-
floatingStyles
|
|
1645
|
-
}), [data, update, refs, elements, floatingStyles]);
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
/**
|
|
1649
|
-
* Modifies the placement by translating the floating element along the
|
|
1650
|
-
* specified axes.
|
|
1651
|
-
* A number (shorthand for `mainAxis` or distance), or an axes configuration
|
|
1652
|
-
* object may be passed.
|
|
1653
|
-
* @see https://floating-ui.com/docs/offset
|
|
1654
|
-
*/
|
|
1655
|
-
const offset = (options, deps) => {
|
|
1656
|
-
const result = offset$1(options);
|
|
1657
|
-
return {
|
|
1658
|
-
name: result.name,
|
|
1659
|
-
fn: result.fn,
|
|
1660
|
-
options: [options, deps]
|
|
1661
|
-
};
|
|
1662
|
-
};
|
|
1663
|
-
|
|
1664
|
-
/**
|
|
1665
|
-
* Optimizes the visibility of the floating element by shifting it in order to
|
|
1666
|
-
* keep it in view when it will overflow the clipping boundary.
|
|
1667
|
-
* @see https://floating-ui.com/docs/shift
|
|
1668
|
-
*/
|
|
1669
|
-
const shift = (options, deps) => {
|
|
1670
|
-
const result = shift$1(options);
|
|
1671
|
-
return {
|
|
1672
|
-
name: result.name,
|
|
1673
|
-
fn: result.fn,
|
|
1674
|
-
options: [options, deps]
|
|
1675
|
-
};
|
|
1676
|
-
};
|
|
1677
|
-
|
|
1678
|
-
/**
|
|
1679
|
-
* Built-in `limiter` that will stop `shift()` at a certain point.
|
|
1680
|
-
*/
|
|
1681
|
-
const limitShift = (options, deps) => {
|
|
1682
|
-
const result = limitShift$1(options);
|
|
1683
|
-
return {
|
|
1684
|
-
fn: result.fn,
|
|
1685
|
-
options: [options, deps]
|
|
1686
|
-
};
|
|
1687
|
-
};
|
|
1688
|
-
|
|
1689
|
-
/**
|
|
1690
|
-
* Optimizes the visibility of the floating element by flipping the `placement`
|
|
1691
|
-
* in order to keep it in view when the preferred placement(s) will overflow the
|
|
1692
|
-
* clipping boundary. Alternative to `autoPlacement`.
|
|
1693
|
-
* @see https://floating-ui.com/docs/flip
|
|
1694
|
-
*/
|
|
1695
|
-
const flip = (options, deps) => {
|
|
1696
|
-
const result = flip$1(options);
|
|
1697
|
-
return {
|
|
1698
|
-
name: result.name,
|
|
1699
|
-
fn: result.fn,
|
|
1700
|
-
options: [options, deps]
|
|
1701
|
-
};
|
|
1702
|
-
};
|
|
1703
|
-
|
|
1704
|
-
/**
|
|
1705
|
-
* Provides data that allows you to change the size of the floating element —
|
|
1706
|
-
* for instance, prevent it from overflowing the clipping boundary or match the
|
|
1707
|
-
* width of the reference element.
|
|
1708
|
-
* @see https://floating-ui.com/docs/size
|
|
1709
|
-
*/
|
|
1710
|
-
const size = (options, deps) => {
|
|
1711
|
-
const result = size$1(options);
|
|
1712
|
-
return {
|
|
1713
|
-
name: result.name,
|
|
1714
|
-
fn: result.fn,
|
|
1715
|
-
options: [options, deps]
|
|
1716
|
-
};
|
|
1717
|
-
};
|
|
6
|
+
import { u as useFloating$1, h as hide$1, f as flip, d as size, b as autoUpdate, o as offset, s as shift, l as limitShift } from './floating-ui.react-dom-es.js';
|
|
1718
7
|
|
|
1719
8
|
function useFloatingRootContext(options) {
|
|
1720
9
|
const {
|
|
@@ -1763,17 +52,16 @@ function useFloatingRootContext(options) {
|
|
|
1763
52
|
}
|
|
1764
53
|
|
|
1765
54
|
/**
|
|
1766
|
-
*
|
|
1767
|
-
*
|
|
55
|
+
* Provides data to position a floating element and context to add interactions.
|
|
56
|
+
* @see https://floating-ui.com/docs/useFloating
|
|
1768
57
|
*/
|
|
1769
|
-
function
|
|
1770
|
-
return useFloatingWithStore(options, options.rootContext);
|
|
1771
|
-
}
|
|
1772
|
-
function useFloatingWithStore(options, store) {
|
|
58
|
+
function useFloating(options = {}) {
|
|
1773
59
|
const {
|
|
1774
60
|
nodeId,
|
|
1775
61
|
externalTree
|
|
1776
62
|
} = options;
|
|
63
|
+
const internalStore = useFloatingRootContext(options);
|
|
64
|
+
const store = options.rootContext || internalStore;
|
|
1777
65
|
const referenceElement = store.useState('referenceElement');
|
|
1778
66
|
const floatingElement = store.useState('floatingElement');
|
|
1779
67
|
const domReferenceElement = store.useState('domReferenceElement');
|
|
@@ -1789,7 +77,7 @@ function useFloatingWithStore(options, store) {
|
|
|
1789
77
|
floating: floatingElement,
|
|
1790
78
|
domReference: domReferenceElement
|
|
1791
79
|
}), [referenceElement, floatingElement, domReferenceElement]);
|
|
1792
|
-
const position = useFloating({
|
|
80
|
+
const position = useFloating$1({
|
|
1793
81
|
...options,
|
|
1794
82
|
elements: {
|
|
1795
83
|
...storeElements,
|
|
@@ -1879,13 +167,6 @@ function useFloatingWithStore(options, store) {
|
|
|
1879
167
|
}
|
|
1880
168
|
|
|
1881
169
|
const ESCAPE = 'Escape';
|
|
1882
|
-
|
|
1883
|
-
// WebKit fires zero-delta `mousemove`/`pointermove` events when the list scrolls
|
|
1884
|
-
// beneath a stationary pointer, moving the highlight during keyboard navigation.
|
|
1885
|
-
// https://github.com/mui/base-ui/issues/4002
|
|
1886
|
-
function isStationaryWebKitPointer(event) {
|
|
1887
|
-
return webkit && event.movementX === 0 && event.movementY === 0;
|
|
1888
|
-
}
|
|
1889
170
|
function doSwitch(orientation, vertical, horizontal) {
|
|
1890
171
|
switch (orientation) {
|
|
1891
172
|
case 'vertical':
|
|
@@ -2292,9 +573,6 @@ function useListNavigation(context, props) {
|
|
|
2292
573
|
}),
|
|
2293
574
|
// Safari
|
|
2294
575
|
onMouseMove(event) {
|
|
2295
|
-
if (isStationaryWebKitPointer(event)) {
|
|
2296
|
-
return;
|
|
2297
|
-
}
|
|
2298
576
|
forceSyncFocusRef.current = true;
|
|
2299
577
|
forceScrollIntoViewRef.current = false;
|
|
2300
578
|
if (focusItemOnHover) {
|
|
@@ -2358,10 +636,7 @@ function useListNavigation(context, props) {
|
|
|
2358
636
|
}
|
|
2359
637
|
commonOnKeyDown(event);
|
|
2360
638
|
},
|
|
2361
|
-
onPointerMove(
|
|
2362
|
-
if (isStationaryWebKitPointer(event)) {
|
|
2363
|
-
return;
|
|
2364
|
-
}
|
|
639
|
+
onPointerMove() {
|
|
2365
640
|
isPointerModalityRef.current = true;
|
|
2366
641
|
}
|
|
2367
642
|
};
|
|
@@ -2482,19 +757,18 @@ function useTypeahead(context, props) {
|
|
|
2482
757
|
const prevIndexRef = React.useRef(selectedIndex ?? activeIndex ?? -1);
|
|
2483
758
|
const matchIndexRef = React.useRef(null);
|
|
2484
759
|
const onKeyDown = useStableCallback(event => {
|
|
2485
|
-
function
|
|
2486
|
-
|
|
760
|
+
function isVisible(index) {
|
|
761
|
+
const element = elementsRef?.current[index];
|
|
762
|
+
return !element || isElementVisible(element);
|
|
2487
763
|
}
|
|
2488
764
|
function isItemAvailable(index) {
|
|
2489
|
-
|
|
2490
|
-
if (element && !isElementVisible(element) || element?.matches(':disabled')) {
|
|
765
|
+
if (!isVisible(index)) {
|
|
2491
766
|
return false;
|
|
2492
767
|
}
|
|
2493
|
-
// Visibility
|
|
2494
|
-
//
|
|
2495
|
-
//
|
|
2496
|
-
//
|
|
2497
|
-
// item except native disabled elements provided through `elementsRef`.
|
|
768
|
+
// Visibility is handled above; pass an empty element list so `isListIndexDisabled`
|
|
769
|
+
// resolves only the explicit `disabledIndices` (array/predicate) and skips its own
|
|
770
|
+
// visibility/attribute fallbacks. Consumers that don't opt in keep matching every
|
|
771
|
+
// visible item.
|
|
2498
772
|
return disabledIndices == null || !isListIndexDisabled(EMPTY_ARRAY, index, disabledIndices);
|
|
2499
773
|
}
|
|
2500
774
|
function getMatchingIndex(list, string, startIndex = 0) {
|
|
@@ -2602,6 +876,12 @@ function useTypeahead(context, props) {
|
|
|
2602
876
|
stringRef.current = '';
|
|
2603
877
|
}
|
|
2604
878
|
}, [open, selectedIndex, timeout]);
|
|
879
|
+
useIsoLayoutEffect(() => {
|
|
880
|
+
// Sync arrow key navigation but not typeahead navigation.
|
|
881
|
+
if (open && stringRef.current === '') {
|
|
882
|
+
prevIndexRef.current = selectedIndex ?? activeIndex ?? -1;
|
|
883
|
+
}
|
|
884
|
+
}, [open, selectedIndex, activeIndex]);
|
|
2605
885
|
const sharedProps = React.useMemo(() => ({
|
|
2606
886
|
onKeyDown,
|
|
2607
887
|
onBlur
|
|
@@ -2641,12 +921,6 @@ function findItemIndex(itemValues, selectedValue, comparer) {
|
|
|
2641
921
|
return compareItemEquality(itemValue, selectedValue, comparer);
|
|
2642
922
|
});
|
|
2643
923
|
}
|
|
2644
|
-
function findSelectionIndex(itemValues, selectedValue, comparer, multiple) {
|
|
2645
|
-
// Only unwrap in multiple mode: an array can itself be a valid single-select value.
|
|
2646
|
-
const lastValue = multiple && Array.isArray(selectedValue) ? selectedValue[selectedValue.length - 1] : selectedValue;
|
|
2647
|
-
const index = findItemIndex(itemValues, lastValue, comparer);
|
|
2648
|
-
return index === -1 ? null : index;
|
|
2649
|
-
}
|
|
2650
924
|
function removeItem(selectedValues, itemValue, comparer) {
|
|
2651
925
|
return selectedValues.filter(selectedValue => !compareItemEquality(itemValue, selectedValue, comparer));
|
|
2652
926
|
}
|
|
@@ -2769,6 +1043,38 @@ function resolveMultipleLabels(values, items, itemToStringLabel) {
|
|
|
2769
1043
|
}, []);
|
|
2770
1044
|
}
|
|
2771
1045
|
|
|
1046
|
+
let FieldControlDataAttributes = /*#__PURE__*/function (FieldControlDataAttributes) {
|
|
1047
|
+
/**
|
|
1048
|
+
* Present when the field is disabled.
|
|
1049
|
+
*/
|
|
1050
|
+
FieldControlDataAttributes["disabled"] = "data-disabled";
|
|
1051
|
+
/**
|
|
1052
|
+
* Present when the field is in a valid state.
|
|
1053
|
+
*/
|
|
1054
|
+
FieldControlDataAttributes["valid"] = "data-valid";
|
|
1055
|
+
/**
|
|
1056
|
+
* Present when the field is in an invalid state.
|
|
1057
|
+
*/
|
|
1058
|
+
FieldControlDataAttributes["invalid"] = "data-invalid";
|
|
1059
|
+
/**
|
|
1060
|
+
* Present when the field has been touched.
|
|
1061
|
+
*/
|
|
1062
|
+
FieldControlDataAttributes["touched"] = "data-touched";
|
|
1063
|
+
/**
|
|
1064
|
+
* Present when the field's value has changed.
|
|
1065
|
+
*/
|
|
1066
|
+
FieldControlDataAttributes["dirty"] = "data-dirty";
|
|
1067
|
+
/**
|
|
1068
|
+
* Present when the field is filled.
|
|
1069
|
+
*/
|
|
1070
|
+
FieldControlDataAttributes["filled"] = "data-filled";
|
|
1071
|
+
/**
|
|
1072
|
+
* Present when the field control is focused.
|
|
1073
|
+
*/
|
|
1074
|
+
FieldControlDataAttributes["focused"] = "data-focused";
|
|
1075
|
+
return FieldControlDataAttributes;
|
|
1076
|
+
}({});
|
|
1077
|
+
|
|
2772
1078
|
const DEFAULT_VALIDITY_STATE = {
|
|
2773
1079
|
badInput: false,
|
|
2774
1080
|
customError: false,
|
|
@@ -2800,11 +1106,11 @@ const fieldValidityMapping = {
|
|
|
2800
1106
|
}
|
|
2801
1107
|
if (value) {
|
|
2802
1108
|
return {
|
|
2803
|
-
|
|
1109
|
+
[FieldControlDataAttributes.valid]: ''
|
|
2804
1110
|
};
|
|
2805
1111
|
}
|
|
2806
1112
|
return {
|
|
2807
|
-
|
|
1113
|
+
[FieldControlDataAttributes.invalid]: ''
|
|
2808
1114
|
};
|
|
2809
1115
|
}
|
|
2810
1116
|
};
|
|
@@ -2821,22 +1127,29 @@ const DEFAULT_FIELD_ROOT_CONTEXT = {
|
|
|
2821
1127
|
},
|
|
2822
1128
|
setValidityData: NOOP,
|
|
2823
1129
|
disabled: undefined,
|
|
1130
|
+
touched: DEFAULT_FIELD_STATE_ATTRIBUTES.touched,
|
|
2824
1131
|
setTouched: NOOP,
|
|
1132
|
+
dirty: DEFAULT_FIELD_STATE_ATTRIBUTES.dirty,
|
|
2825
1133
|
setDirty: NOOP,
|
|
1134
|
+
filled: DEFAULT_FIELD_STATE_ATTRIBUTES.filled,
|
|
2826
1135
|
setFilled: NOOP,
|
|
1136
|
+
focused: DEFAULT_FIELD_STATE_ATTRIBUTES.focused,
|
|
2827
1137
|
setFocused: NOOP,
|
|
1138
|
+
validate: () => null,
|
|
2828
1139
|
validationMode: 'onSubmit',
|
|
1140
|
+
validationDebounceTime: 0,
|
|
2829
1141
|
shouldValidateOnChange: () => false,
|
|
2830
1142
|
state: DEFAULT_FIELD_ROOT_STATE,
|
|
1143
|
+
markedDirtyRef: {
|
|
1144
|
+
current: false
|
|
1145
|
+
},
|
|
2831
1146
|
registerFieldControl: NOOP,
|
|
2832
1147
|
validation: {
|
|
2833
1148
|
getValidationProps: (_disabled, props = EMPTY_OBJECT) => props,
|
|
2834
1149
|
inputRef: {
|
|
2835
1150
|
current: null
|
|
2836
1151
|
},
|
|
2837
|
-
registeredInputs: new Map(),
|
|
2838
1152
|
registerInput: NOOP,
|
|
2839
|
-
getInputControl: () => null,
|
|
2840
1153
|
commit: async () => {},
|
|
2841
1154
|
change: NOOP
|
|
2842
1155
|
}
|
|
@@ -2855,16 +1168,14 @@ function useRegisterFieldControl(controlRef, id, value, getFormValueOverride, en
|
|
|
2855
1168
|
const {
|
|
2856
1169
|
registerFieldControl
|
|
2857
1170
|
} = useFieldRootContext();
|
|
2858
|
-
const sourceRef =
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
// end of the Map every time its value changes.
|
|
1171
|
+
const sourceRef = React.useRef(null);
|
|
1172
|
+
if (!sourceRef.current) {
|
|
1173
|
+
sourceRef.current = Symbol();
|
|
1174
|
+
}
|
|
2863
1175
|
useIsoLayoutEffect(() => {
|
|
2864
1176
|
const source = sourceRef.current;
|
|
2865
|
-
if (!enabled) {
|
|
2866
|
-
|
|
2867
|
-
return;
|
|
1177
|
+
if (!source || !enabled) {
|
|
1178
|
+
return undefined;
|
|
2868
1179
|
}
|
|
2869
1180
|
const registration = {
|
|
2870
1181
|
controlRef,
|
|
@@ -2874,19 +1185,13 @@ function useRegisterFieldControl(controlRef, id, value, getFormValueOverride, en
|
|
|
2874
1185
|
value
|
|
2875
1186
|
};
|
|
2876
1187
|
registerFieldControl(source, registration);
|
|
2877
|
-
}, [controlRef, enabled, getFormValueOverride, id, name, registerFieldControl, sourceRef, value]);
|
|
2878
|
-
useIsoLayoutEffect(() => {
|
|
2879
|
-
const source = sourceRef.current;
|
|
2880
1188
|
return () => {
|
|
2881
1189
|
registerFieldControl(source, undefined);
|
|
2882
1190
|
};
|
|
2883
|
-
}, [registerFieldControl,
|
|
1191
|
+
}, [controlRef, enabled, getFormValueOverride, id, name, registerFieldControl, value]);
|
|
2884
1192
|
}
|
|
2885
1193
|
|
|
2886
1194
|
const FormContext = /*#__PURE__*/React.createContext({
|
|
2887
|
-
elementRef: {
|
|
2888
|
-
current: null
|
|
2889
|
-
},
|
|
2890
1195
|
formRef: {
|
|
2891
1196
|
current: {
|
|
2892
1197
|
fields: new Map()
|
|
@@ -2934,7 +1239,7 @@ function useLabelableId(params = {}) {
|
|
|
2934
1239
|
} = useLabelableContext();
|
|
2935
1240
|
const defaultId = useBaseUiId(id);
|
|
2936
1241
|
const controlIdForEffect = implicit ? controlId : undefined;
|
|
2937
|
-
const controlSourceRef = useRefWithInit(() => Symbol());
|
|
1242
|
+
const controlSourceRef = useRefWithInit(() => Symbol('labelable-control'));
|
|
2938
1243
|
const hasRegisteredRef = React.useRef(false);
|
|
2939
1244
|
const hadExplicitIdRef = React.useRef(id != null);
|
|
2940
1245
|
const unregisterControlId = useStableCallback(() => {
|
|
@@ -2983,19 +1288,6 @@ function areArraysEqual(array1, array2, itemComparer = (a, b) => a === b) {
|
|
|
2983
1288
|
return array1.length === array2.length && array1.every((value, index) => itemComparer(value, array2[index]));
|
|
2984
1289
|
}
|
|
2985
1290
|
|
|
2986
|
-
// Tolerance around the element bounds so a fast click whose pointer drifts slightly
|
|
2987
|
-
// during press-release isn't mistaken for a drag-off-and-release cancellation.
|
|
2988
|
-
// Matches typical OS/browser drag-initiation thresholds.
|
|
2989
|
-
const BOUNDARY_OFFSET = 5;
|
|
2990
|
-
|
|
2991
|
-
/**
|
|
2992
|
-
* Determines if a mouse event occurred within the bounds of an element
|
|
2993
|
-
* (including its pseudo-elements), with a small tolerance for pointer drift.
|
|
2994
|
-
*/
|
|
2995
|
-
function isMouseWithinBounds(event, element) {
|
|
2996
|
-
const bounds = getPseudoElementBounds(element);
|
|
2997
|
-
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;
|
|
2998
|
-
}
|
|
2999
1291
|
function getPseudoElementBounds(element) {
|
|
3000
1292
|
const elementRect = element.getBoundingClientRect();
|
|
3001
1293
|
const win = getWindow(element);
|
|
@@ -3042,7 +1334,12 @@ function resolveAriaLabelledBy(fieldLabelId, localLabelId) {
|
|
|
3042
1334
|
const CompositeListContext = /*#__PURE__*/React.createContext({
|
|
3043
1335
|
register: () => {},
|
|
3044
1336
|
unregister: () => {},
|
|
3045
|
-
subscribeMapChange: () =>
|
|
1337
|
+
subscribeMapChange: () => {
|
|
1338
|
+
return () => {};
|
|
1339
|
+
},
|
|
1340
|
+
elementsRef: {
|
|
1341
|
+
current: []
|
|
1342
|
+
},
|
|
3046
1343
|
nextIndexRef: {
|
|
3047
1344
|
current: 0
|
|
3048
1345
|
}
|
|
@@ -3055,6 +1352,7 @@ function useCompositeListContext() {
|
|
|
3055
1352
|
/* eslint-disable no-bitwise */
|
|
3056
1353
|
/**
|
|
3057
1354
|
* Provides context for a list of items in a composite component.
|
|
1355
|
+
* @internal
|
|
3058
1356
|
*/
|
|
3059
1357
|
function CompositeList(props) {
|
|
3060
1358
|
const {
|
|
@@ -3064,146 +1362,114 @@ function CompositeList(props) {
|
|
|
3064
1362
|
onMapChange: onMapChangeProp
|
|
3065
1363
|
} = props;
|
|
3066
1364
|
const onMapChange = useStableCallback(onMapChangeProp);
|
|
3067
|
-
const
|
|
1365
|
+
const nextIndexRef = React.useRef(0);
|
|
3068
1366
|
const listeners = useRefWithInit(createListeners).current;
|
|
1367
|
+
|
|
1368
|
+
// We use a stable `map` to avoid O(n^2) re-allocation costs for large lists.
|
|
1369
|
+
// `mapTick` is our re-render trigger mechanism. We also need to update the
|
|
1370
|
+
// elements and label refs, but there's a lot of async work going on and sometimes
|
|
1371
|
+
// the effect that handles `onMapChange` gets called after those refs have been
|
|
1372
|
+
// filled, and we don't want to lose those values by setting their lengths to `0`.
|
|
1373
|
+
// We also need to have them at the proper length because floating-ui uses that
|
|
1374
|
+
// information for list navigation.
|
|
1375
|
+
|
|
3069
1376
|
const map = useRefWithInit(createMap).current;
|
|
3070
|
-
|
|
3071
|
-
const
|
|
3072
|
-
const
|
|
3073
|
-
const
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
// the originating React event is still inside `act()` in tests.
|
|
3078
|
-
const scheduleMapUpdate = useStableCallback(() => {
|
|
3079
|
-
if (isDirtyRef.current) {
|
|
3080
|
-
return;
|
|
3081
|
-
}
|
|
3082
|
-
isDirtyRef.current = true;
|
|
3083
|
-
setMapTick(tick => !tick);
|
|
3084
|
-
});
|
|
3085
|
-
const register = useStableCallback((node, registration) => {
|
|
3086
|
-
map.set(node, registration);
|
|
3087
|
-
scheduleMapUpdate();
|
|
1377
|
+
// `mapTick` uses a counter rather than objects for low precision-loss risk and better memory efficiency
|
|
1378
|
+
const [mapTick, setMapTick] = React.useState(0);
|
|
1379
|
+
const lastTickRef = React.useRef(mapTick);
|
|
1380
|
+
const register = useStableCallback((node, metadata) => {
|
|
1381
|
+
map.set(node, metadata ?? null);
|
|
1382
|
+
lastTickRef.current += 1;
|
|
1383
|
+
setMapTick(lastTickRef.current);
|
|
3088
1384
|
});
|
|
3089
1385
|
const unregister = useStableCallback(node => {
|
|
3090
1386
|
map.delete(node);
|
|
3091
|
-
|
|
1387
|
+
lastTickRef.current += 1;
|
|
1388
|
+
setMapTick(lastTickRef.current);
|
|
3092
1389
|
});
|
|
3093
|
-
const
|
|
3094
|
-
const
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
...
|
|
3102
|
-
index
|
|
1390
|
+
const sortedMap = React.useMemo(() => {
|
|
1391
|
+
const newMap = new Map();
|
|
1392
|
+
// Filter out disconnected elements before sorting to avoid inconsistent
|
|
1393
|
+
// compareDocumentPosition results when elements are detached from the DOM.
|
|
1394
|
+
const sortedNodes = Array.from(map.keys()).filter(node => node.isConnected).sort(sortByDocumentPosition);
|
|
1395
|
+
sortedNodes.forEach((node, index) => {
|
|
1396
|
+
const metadata = map.get(node) ?? {};
|
|
1397
|
+
newMap.set(node, {
|
|
1398
|
+
...metadata,
|
|
1399
|
+
index
|
|
3103
1400
|
});
|
|
3104
|
-
elementsRef.current[item.index] = item.element;
|
|
3105
|
-
if (labelsRef) {
|
|
3106
|
-
labelsRef.current[item.index] = item.registration.label !== undefined ? item.registration.label : item.registration.textRef?.current?.textContent ?? item.element.textContent;
|
|
3107
|
-
}
|
|
3108
1401
|
});
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
mutationObserverRef.current = null;
|
|
3115
|
-
|
|
3116
|
-
// A single item can't reorder.
|
|
3117
|
-
if (typeof MutationObserver !== 'function' || sortedNodes.length < 2) {
|
|
3118
|
-
return;
|
|
1402
|
+
return newMap;
|
|
1403
|
+
}, [map, mapTick]);
|
|
1404
|
+
useIsoLayoutEffect(() => {
|
|
1405
|
+
if (typeof MutationObserver !== 'function' || sortedMap.size === 0) {
|
|
1406
|
+
return undefined;
|
|
3119
1407
|
}
|
|
3120
1408
|
const mutationObserver = new MutationObserver(entries => {
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
1409
|
+
const diff = new Set();
|
|
1410
|
+
const updateDiff = node => diff.has(node) ? diff.delete(node) : diff.add(node);
|
|
1411
|
+
entries.forEach(entry => {
|
|
1412
|
+
entry.removedNodes.forEach(updateDiff);
|
|
1413
|
+
entry.addedNodes.forEach(updateDiff);
|
|
1414
|
+
});
|
|
1415
|
+
if (diff.size === 0) {
|
|
1416
|
+
lastTickRef.current += 1;
|
|
1417
|
+
setMapTick(lastTickRef.current);
|
|
3127
1418
|
}
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
continue;
|
|
3135
|
-
}
|
|
3136
|
-
if (previousConnectedNode && sortByDocumentPosition(previousConnectedNode, node) > 0) {
|
|
3137
|
-
mutationObserver.disconnect();
|
|
3138
|
-
scheduleMapUpdate();
|
|
3139
|
-
return;
|
|
3140
|
-
}
|
|
3141
|
-
previousConnectedNode = node;
|
|
1419
|
+
});
|
|
1420
|
+
sortedMap.forEach((_, node) => {
|
|
1421
|
+
if (node.parentElement) {
|
|
1422
|
+
mutationObserver.observe(node.parentElement, {
|
|
1423
|
+
childList: true
|
|
1424
|
+
});
|
|
3142
1425
|
}
|
|
3143
1426
|
});
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
const
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
roots.add(root);
|
|
1427
|
+
return () => {
|
|
1428
|
+
mutationObserver.disconnect();
|
|
1429
|
+
};
|
|
1430
|
+
}, [sortedMap]);
|
|
1431
|
+
useIsoLayoutEffect(() => {
|
|
1432
|
+
const shouldUpdateLengths = lastTickRef.current === mapTick;
|
|
1433
|
+
if (shouldUpdateLengths) {
|
|
1434
|
+
if (elementsRef.current.length !== sortedMap.size) {
|
|
1435
|
+
elementsRef.current.length = sortedMap.size;
|
|
3154
1436
|
}
|
|
1437
|
+
if (labelsRef && labelsRef.current.length !== sortedMap.size) {
|
|
1438
|
+
labelsRef.current.length = sortedMap.size;
|
|
1439
|
+
}
|
|
1440
|
+
nextIndexRef.current = sortedMap.size;
|
|
3155
1441
|
}
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
}));
|
|
3159
|
-
}
|
|
3160
|
-
const flush = useStableCallback(() => {
|
|
3161
|
-
const [items, automaticNodes] = getCompositeListSnapshot(map);
|
|
3162
|
-
const nextMap = syncRefs(items);
|
|
3163
|
-
observe(automaticNodes);
|
|
3164
|
-
itemsRef.current = items;
|
|
3165
|
-
isDirtyRef.current = false;
|
|
3166
|
-
listeners.forEach(listener => listener(nextMap));
|
|
3167
|
-
onMapChange(nextMap);
|
|
3168
|
-
});
|
|
1442
|
+
onMapChange(sortedMap);
|
|
1443
|
+
}, [onMapChange, sortedMap, elementsRef, labelsRef, mapTick]);
|
|
3169
1444
|
useIsoLayoutEffect(() => {
|
|
3170
|
-
// Re-copy the last committed snapshot when the ref objects change or Strict Mode replays
|
|
3171
|
-
// effects without reattaching callback refs.
|
|
3172
|
-
if (!isDirtyRef.current) {
|
|
3173
|
-
syncRefs(itemsRef.current);
|
|
3174
|
-
}
|
|
3175
1445
|
return () => {
|
|
3176
1446
|
elementsRef.current = [];
|
|
3177
|
-
if (labelsRef) {
|
|
3178
|
-
labelsRef.current = [];
|
|
3179
|
-
}
|
|
3180
1447
|
};
|
|
3181
|
-
}, [elementsRef
|
|
3182
|
-
useIsoLayoutEffect(() => {
|
|
3183
|
-
if (isDirtyRef.current) {
|
|
3184
|
-
flush();
|
|
3185
|
-
}
|
|
3186
|
-
});
|
|
1448
|
+
}, [elementsRef]);
|
|
3187
1449
|
useIsoLayoutEffect(() => {
|
|
3188
1450
|
return () => {
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
isDirtyRef.current = true;
|
|
1451
|
+
if (labelsRef) {
|
|
1452
|
+
labelsRef.current = [];
|
|
1453
|
+
}
|
|
3193
1454
|
};
|
|
3194
|
-
}, []);
|
|
1455
|
+
}, [labelsRef]);
|
|
3195
1456
|
const subscribeMapChange = useStableCallback(fn => {
|
|
3196
1457
|
listeners.add(fn);
|
|
3197
1458
|
return () => {
|
|
3198
1459
|
listeners.delete(fn);
|
|
3199
1460
|
};
|
|
3200
1461
|
});
|
|
1462
|
+
useIsoLayoutEffect(() => {
|
|
1463
|
+
listeners.forEach(l => l(sortedMap));
|
|
1464
|
+
}, [listeners, sortedMap]);
|
|
3201
1465
|
const contextValue = React.useMemo(() => ({
|
|
3202
1466
|
register,
|
|
3203
1467
|
unregister,
|
|
3204
1468
|
subscribeMapChange,
|
|
1469
|
+
elementsRef,
|
|
1470
|
+
labelsRef,
|
|
3205
1471
|
nextIndexRef
|
|
3206
|
-
}), [register, unregister, subscribeMapChange, nextIndexRef]);
|
|
1472
|
+
}), [register, unregister, subscribeMapChange, elementsRef, labelsRef, nextIndexRef]);
|
|
3207
1473
|
return /*#__PURE__*/jsx(CompositeListContext.Provider, {
|
|
3208
1474
|
value: contextValue,
|
|
3209
1475
|
children: children
|
|
@@ -3215,66 +1481,15 @@ function createMap() {
|
|
|
3215
1481
|
function createListeners() {
|
|
3216
1482
|
return new Set();
|
|
3217
1483
|
}
|
|
3218
|
-
function
|
|
3219
|
-
const
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
map.forEach((registration, node) => {
|
|
3223
|
-
if (!node.isConnected) {
|
|
3224
|
-
return;
|
|
3225
|
-
}
|
|
3226
|
-
const index = registration.index;
|
|
3227
|
-
const item = {
|
|
3228
|
-
index: index ?? -1,
|
|
3229
|
-
element: node,
|
|
3230
|
-
registration
|
|
3231
|
-
};
|
|
3232
|
-
if (index === null) {
|
|
3233
|
-
automaticItems.push(item);
|
|
3234
|
-
} else if (index >= 0) {
|
|
3235
|
-
reservedIndices.add(index);
|
|
3236
|
-
items.push(item);
|
|
3237
|
-
}
|
|
3238
|
-
});
|
|
3239
|
-
let nextAutomaticIndex = 0;
|
|
3240
|
-
automaticItems.sort((a, b) => sortByDocumentPosition(a.element, b.element));
|
|
3241
|
-
automaticItems.forEach(item => {
|
|
3242
|
-
while (reservedIndices.has(nextAutomaticIndex)) {
|
|
3243
|
-
nextAutomaticIndex += 1;
|
|
3244
|
-
}
|
|
3245
|
-
item.index = nextAutomaticIndex;
|
|
3246
|
-
items.push(item);
|
|
3247
|
-
nextAutomaticIndex += 1;
|
|
3248
|
-
});
|
|
3249
|
-
if (reservedIndices.size > 0) {
|
|
3250
|
-
items.sort((a, b) => a.index - b.index);
|
|
3251
|
-
}
|
|
3252
|
-
return [items, automaticItems.map(item => item.element)];
|
|
3253
|
-
}
|
|
3254
|
-
function getCommonAncestor(firstNode, lastNode) {
|
|
3255
|
-
let ancestor = firstNode.parentElement;
|
|
3256
|
-
|
|
3257
|
-
// The `parentElement` walk cannot cross shadow boundaries, so the native
|
|
3258
|
-
// `contains` is sufficient here.
|
|
3259
|
-
while (ancestor && !ancestor.contains(lastNode)) {
|
|
3260
|
-
ancestor = ancestor.parentElement;
|
|
1484
|
+
function sortByDocumentPosition(a, b) {
|
|
1485
|
+
const position = a.compareDocumentPosition(b);
|
|
1486
|
+
if (position & Node.DOCUMENT_POSITION_FOLLOWING || position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
|
|
1487
|
+
return -1;
|
|
3261
1488
|
}
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
function hasMovedNode(entries) {
|
|
3265
|
-
for (const entry of entries) {
|
|
3266
|
-
for (let i = 0; i < entry.removedNodes.length; i += 1) {
|
|
3267
|
-
if (entry.removedNodes[i].isConnected) {
|
|
3268
|
-
return true;
|
|
3269
|
-
}
|
|
3270
|
-
}
|
|
1489
|
+
if (position & Node.DOCUMENT_POSITION_PRECEDING || position & Node.DOCUMENT_POSITION_CONTAINS) {
|
|
1490
|
+
return 1;
|
|
3271
1491
|
}
|
|
3272
|
-
return
|
|
3273
|
-
}
|
|
3274
|
-
function sortByDocumentPosition(a, b) {
|
|
3275
|
-
// `DOCUMENT_POSITION_CONTAINED_BY` is always reported alongside `FOLLOWING`, and `CONTAINS`
|
|
3276
|
-
// alongside `PRECEDING`, so testing `FOLLOWING` alone orders siblings and nested items alike.
|
|
3277
|
-
return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
|
|
1492
|
+
return 0;
|
|
3278
1493
|
}
|
|
3279
1494
|
|
|
3280
1495
|
/**
|
|
@@ -3371,6 +1586,7 @@ const arrow = (options, deps) => ({
|
|
|
3371
1586
|
options: [options, deps]
|
|
3372
1587
|
});
|
|
3373
1588
|
|
|
1589
|
+
const nativeHideFn = hide$1().fn;
|
|
3374
1590
|
const hide = {
|
|
3375
1591
|
name: 'hide',
|
|
3376
1592
|
async fn(state) {
|
|
@@ -3381,15 +1597,10 @@ const hide = {
|
|
|
3381
1597
|
y
|
|
3382
1598
|
} = state.rects.reference;
|
|
3383
1599
|
const anchorHidden = width === 0 && height === 0 && x === 0 && y === 0;
|
|
3384
|
-
|
|
3385
|
-
// `detectOverflow` into the middleware platform before invoking middleware.
|
|
3386
|
-
const overflow = await state.platform.detectOverflow(state, {
|
|
3387
|
-
elementContext: 'reference'
|
|
3388
|
-
});
|
|
3389
|
-
const referenceHidden = overflow.top - height >= 0 || overflow.right - width >= 0 || overflow.bottom - height >= 0 || overflow.left - width >= 0;
|
|
1600
|
+
const nativeHideResult = await nativeHideFn(state);
|
|
3390
1601
|
return {
|
|
3391
1602
|
data: {
|
|
3392
|
-
referenceHidden: referenceHidden || anchorHidden
|
|
1603
|
+
referenceHidden: nativeHideResult.data?.referenceHidden || anchorHidden
|
|
3393
1604
|
}
|
|
3394
1605
|
};
|
|
3395
1606
|
}
|
|
@@ -3399,13 +1610,75 @@ const DEFAULT_SIDES = {
|
|
|
3399
1610
|
sideX: 'left',
|
|
3400
1611
|
sideY: 'top'
|
|
3401
1612
|
};
|
|
1613
|
+
const adaptiveOrigin = {
|
|
1614
|
+
name: 'adaptiveOrigin',
|
|
1615
|
+
async fn(state) {
|
|
1616
|
+
const {
|
|
1617
|
+
x: rawX,
|
|
1618
|
+
y: rawY,
|
|
1619
|
+
rects: {
|
|
1620
|
+
floating: floatRect
|
|
1621
|
+
},
|
|
1622
|
+
elements: {
|
|
1623
|
+
floating
|
|
1624
|
+
},
|
|
1625
|
+
platform,
|
|
1626
|
+
strategy,
|
|
1627
|
+
placement
|
|
1628
|
+
} = state;
|
|
1629
|
+
const win = getWindow(floating);
|
|
1630
|
+
const styles = win.getComputedStyle(floating);
|
|
1631
|
+
const hasTransition = styles.transitionDuration !== '0s' && styles.transitionDuration !== '';
|
|
1632
|
+
if (!hasTransition) {
|
|
1633
|
+
return {
|
|
1634
|
+
x: rawX,
|
|
1635
|
+
y: rawY,
|
|
1636
|
+
data: DEFAULT_SIDES
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1639
|
+
const offsetParent = await platform.getOffsetParent?.(floating);
|
|
1640
|
+
let offsetDimensions = {
|
|
1641
|
+
width: 0,
|
|
1642
|
+
height: 0
|
|
1643
|
+
};
|
|
3402
1644
|
|
|
3403
|
-
//
|
|
3404
|
-
|
|
3405
|
-
|
|
1645
|
+
// For fixed strategy, prefer visualViewport if available
|
|
1646
|
+
if (strategy === 'fixed' && win?.visualViewport) {
|
|
1647
|
+
offsetDimensions = {
|
|
1648
|
+
width: win.visualViewport.width,
|
|
1649
|
+
height: win.visualViewport.height
|
|
1650
|
+
};
|
|
1651
|
+
} else if (offsetParent === win) {
|
|
1652
|
+
const doc = ownerDocument(floating);
|
|
1653
|
+
offsetDimensions = {
|
|
1654
|
+
width: doc.documentElement.clientWidth,
|
|
1655
|
+
height: doc.documentElement.clientHeight
|
|
1656
|
+
};
|
|
1657
|
+
} else if (await platform.isElement?.(offsetParent)) {
|
|
1658
|
+
offsetDimensions = await platform.getDimensions(offsetParent);
|
|
1659
|
+
}
|
|
1660
|
+
const currentSide = getSide(placement);
|
|
1661
|
+
let x = rawX;
|
|
1662
|
+
let y = rawY;
|
|
1663
|
+
if (currentSide === 'left') {
|
|
1664
|
+
x = offsetDimensions.width - (rawX + floatRect.width);
|
|
1665
|
+
}
|
|
1666
|
+
if (currentSide === 'top') {
|
|
1667
|
+
y = offsetDimensions.height - (rawY + floatRect.height);
|
|
1668
|
+
}
|
|
1669
|
+
const sideX = currentSide === 'left' ? 'right' : DEFAULT_SIDES.sideX;
|
|
1670
|
+
const sideY = currentSide === 'top' ? 'bottom' : DEFAULT_SIDES.sideY;
|
|
1671
|
+
return {
|
|
1672
|
+
x,
|
|
1673
|
+
y,
|
|
1674
|
+
data: {
|
|
1675
|
+
sideX,
|
|
1676
|
+
sideY
|
|
1677
|
+
}
|
|
1678
|
+
};
|
|
1679
|
+
}
|
|
1680
|
+
};
|
|
3406
1681
|
|
|
3407
|
-
const AVAILABLE_WIDTH_VAR = '--available-width';
|
|
3408
|
-
const AVAILABLE_HEIGHT_VAR = '--available-height';
|
|
3409
1682
|
function getLogicalSide(sideParam, renderedSide, isRtl) {
|
|
3410
1683
|
const isLogicalSideParam = sideParam === 'inline-start' || sideParam === 'inline-end';
|
|
3411
1684
|
const logicalRight = isRtl ? 'inline-start' : 'inline-end';
|
|
@@ -3441,9 +1714,6 @@ function getOffsetData(state, sideParam, isRtl) {
|
|
|
3441
1714
|
* `useFloating` hook.
|
|
3442
1715
|
*/
|
|
3443
1716
|
function useAnchorPositioning(params) {
|
|
3444
|
-
return useAnchorPositioningWithHook(params, useBaseUIFloating);
|
|
3445
|
-
}
|
|
3446
|
-
function useAnchorPositioningWithHook(params, useFloatingHook) {
|
|
3447
1717
|
const {
|
|
3448
1718
|
// Public parameters
|
|
3449
1719
|
anchor,
|
|
@@ -3463,7 +1733,7 @@ function useAnchorPositioningWithHook(params, useFloatingHook) {
|
|
|
3463
1733
|
floatingRootContext,
|
|
3464
1734
|
mounted,
|
|
3465
1735
|
collisionAvoidance,
|
|
3466
|
-
|
|
1736
|
+
shiftCrossAxis = false,
|
|
3467
1737
|
nodeId,
|
|
3468
1738
|
adaptiveOrigin,
|
|
3469
1739
|
lazyFlip = false,
|
|
@@ -3476,8 +1746,6 @@ function useAnchorPositioningWithHook(params, useFloatingHook) {
|
|
|
3476
1746
|
const collisionAvoidanceSide = collisionAvoidance.side || 'flip';
|
|
3477
1747
|
const collisionAvoidanceAlign = collisionAvoidance.align || 'flip';
|
|
3478
1748
|
const collisionAvoidanceFallbackAxisSide = collisionAvoidance.fallbackAxisSide || 'end';
|
|
3479
|
-
const shiftCrossAxis = shift$1?.crossAxis ?? false;
|
|
3480
|
-
const shiftRootBoundary = shift$1?.rootBoundary;
|
|
3481
1749
|
const anchorFn = typeof anchor === 'function' ? anchor : undefined;
|
|
3482
1750
|
const anchorFnCallback = useStableCallback(anchorFn);
|
|
3483
1751
|
const anchorDep = anchorFn ? anchorFnCallback : anchor;
|
|
@@ -3495,32 +1763,30 @@ function useAnchorPositioningWithHook(params, useFloatingHook) {
|
|
|
3495
1763
|
}[sideParam];
|
|
3496
1764
|
const placement = align === 'center' ? side : `${side}-${align}`;
|
|
3497
1765
|
let collisionPadding = collisionPaddingParam;
|
|
3498
|
-
if (typeof collisionPadding === 'number') {
|
|
3499
|
-
collisionPadding = {
|
|
3500
|
-
top: collisionPadding,
|
|
3501
|
-
right: collisionPadding,
|
|
3502
|
-
bottom: collisionPadding,
|
|
3503
|
-
left: collisionPadding
|
|
3504
|
-
};
|
|
3505
|
-
} else if (collisionPadding) {
|
|
3506
|
-
collisionPadding = {
|
|
3507
|
-
top: collisionPadding.top || 0,
|
|
3508
|
-
right: collisionPadding.right || 0,
|
|
3509
|
-
bottom: collisionPadding.bottom || 0,
|
|
3510
|
-
left: collisionPadding.left || 0
|
|
3511
|
-
};
|
|
3512
|
-
}
|
|
3513
1766
|
|
|
3514
1767
|
// Create a bias to the preferred side.
|
|
3515
1768
|
// On iOS, when the mobile software keyboard opens, the input is exactly centered
|
|
3516
1769
|
// in the viewport, but this can cause it to flip to the top undesirably.
|
|
3517
|
-
// The bias is only applied to `flip()` so it doesn't shift the resting position
|
|
3518
|
-
// computed by `shift()` and `size()` away from the requested `collisionPadding`.
|
|
3519
1770
|
const bias = 1;
|
|
3520
1771
|
const biasTop = sideParam === 'bottom' ? bias : 0;
|
|
3521
1772
|
const biasBottom = sideParam === 'top' ? bias : 0;
|
|
3522
1773
|
const biasLeft = sideParam === 'right' ? bias : 0;
|
|
3523
1774
|
const biasRight = sideParam === 'left' ? bias : 0;
|
|
1775
|
+
if (typeof collisionPadding === 'number') {
|
|
1776
|
+
collisionPadding = {
|
|
1777
|
+
top: collisionPadding + biasTop,
|
|
1778
|
+
right: collisionPadding + biasRight,
|
|
1779
|
+
bottom: collisionPadding + biasBottom,
|
|
1780
|
+
left: collisionPadding + biasLeft
|
|
1781
|
+
};
|
|
1782
|
+
} else if (collisionPadding) {
|
|
1783
|
+
collisionPadding = {
|
|
1784
|
+
top: (collisionPadding.top || 0) + biasTop,
|
|
1785
|
+
right: (collisionPadding.right || 0) + biasRight,
|
|
1786
|
+
bottom: (collisionPadding.bottom || 0) + biasBottom,
|
|
1787
|
+
left: (collisionPadding.left || 0) + biasLeft
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
3524
1790
|
const commonCollisionProps = {
|
|
3525
1791
|
boundary: collisionBoundary === 'clipping-ancestors' ? 'clippingAncestors' : collisionBoundary,
|
|
3526
1792
|
padding: collisionPadding
|
|
@@ -3557,37 +1823,46 @@ function useAnchorPositioningWithHook(params, useFloatingHook) {
|
|
|
3557
1823
|
// Ensure the popup flips if it's been limited by its --available-height and it resizes.
|
|
3558
1824
|
// Since the size() padding is smaller than the flip() padding, flip() will take precedence.
|
|
3559
1825
|
padding: {
|
|
3560
|
-
top: collisionPadding.top + bias
|
|
3561
|
-
right: collisionPadding.right + bias
|
|
3562
|
-
bottom: collisionPadding.bottom + bias
|
|
3563
|
-
left: collisionPadding.left + bias
|
|
1826
|
+
top: collisionPadding.top + bias,
|
|
1827
|
+
right: collisionPadding.right + bias,
|
|
1828
|
+
bottom: collisionPadding.bottom + bias,
|
|
1829
|
+
left: collisionPadding.left + bias
|
|
3564
1830
|
},
|
|
3565
1831
|
mainAxis: !shiftCrossAxis && collisionAvoidanceSide === 'flip',
|
|
3566
1832
|
crossAxis: collisionAvoidanceAlign === 'flip' ? 'alignment' : false,
|
|
3567
1833
|
fallbackAxisSideDirection: collisionAvoidanceFallbackAxisSide
|
|
3568
1834
|
});
|
|
3569
|
-
const shiftMiddleware = shiftDisabled ? null : shift({
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
1835
|
+
const shiftMiddleware = shiftDisabled ? null : shift(data => {
|
|
1836
|
+
const html = ownerDocument(data.elements.floating).documentElement;
|
|
1837
|
+
return {
|
|
1838
|
+
...commonCollisionProps,
|
|
1839
|
+
// Use the Layout Viewport to avoid shifting around when pinch-zooming
|
|
1840
|
+
// for context menus.
|
|
1841
|
+
rootBoundary: shiftCrossAxis ? {
|
|
1842
|
+
x: 0,
|
|
1843
|
+
y: 0,
|
|
1844
|
+
width: html.clientWidth,
|
|
1845
|
+
height: html.clientHeight
|
|
1846
|
+
} : undefined,
|
|
1847
|
+
mainAxis: collisionAvoidanceAlign !== 'none',
|
|
1848
|
+
crossAxis: crossAxisShiftEnabled,
|
|
1849
|
+
limiter: sticky || shiftCrossAxis ? undefined : limitShift(limitData => {
|
|
1850
|
+
if (!arrowRef.current) {
|
|
1851
|
+
return {};
|
|
1852
|
+
}
|
|
1853
|
+
const {
|
|
1854
|
+
width,
|
|
1855
|
+
height
|
|
1856
|
+
} = arrowRef.current.getBoundingClientRect();
|
|
1857
|
+
const sideAxis = getSideAxis(getSide(limitData.placement));
|
|
1858
|
+
const arrowSize = sideAxis === 'y' ? width : height;
|
|
1859
|
+
const offsetAmount = sideAxis === 'y' ? collisionPadding.left + collisionPadding.right : collisionPadding.top + collisionPadding.bottom;
|
|
1860
|
+
return {
|
|
1861
|
+
offset: arrowSize / 2 + offsetAmount / 2
|
|
1862
|
+
};
|
|
1863
|
+
})
|
|
1864
|
+
};
|
|
1865
|
+
}, [commonCollisionProps, sticky, shiftCrossAxis, collisionPadding, collisionAvoidanceAlign]);
|
|
3591
1866
|
|
|
3592
1867
|
// https://floating-ui.com/docs/flip#combining-with-shift
|
|
3593
1868
|
if (collisionAvoidanceSide === 'shift' || collisionAvoidanceAlign === 'shift' || align === 'center') {
|
|
@@ -3609,8 +1884,8 @@ function useAnchorPositioningWithHook(params, useFloatingHook) {
|
|
|
3609
1884
|
return;
|
|
3610
1885
|
}
|
|
3611
1886
|
const floatingStyle = floating.style;
|
|
3612
|
-
floatingStyle.setProperty(
|
|
3613
|
-
floatingStyle.setProperty(
|
|
1887
|
+
floatingStyle.setProperty('--available-width', `${availableWidth}px`);
|
|
1888
|
+
floatingStyle.setProperty('--available-height', `${availableHeight}px`);
|
|
3614
1889
|
|
|
3615
1890
|
// Snap anchor dimensions to device pixels to ensure the popup's visual width matches the anchor's one.
|
|
3616
1891
|
const dpr = getWindow(floating).devicePixelRatio || 1;
|
|
@@ -3692,7 +1967,7 @@ function useAnchorPositioningWithHook(params, useFloatingHook) {
|
|
|
3692
1967
|
context,
|
|
3693
1968
|
isPositioned,
|
|
3694
1969
|
floatingStyles: originalFloatingStyles
|
|
3695
|
-
} =
|
|
1970
|
+
} = useFloating({
|
|
3696
1971
|
rootContext: floatingRootContext,
|
|
3697
1972
|
open: keepMounted ? mounted : undefined,
|
|
3698
1973
|
placement,
|
|
@@ -3711,41 +1986,14 @@ function useAnchorPositioningWithHook(params, useFloatingHook) {
|
|
|
3711
1986
|
// This ensures the popup is inside the viewport initially before it gets positioned.
|
|
3712
1987
|
const resolvedPosition = isPositioned ? positionMethod : 'fixed';
|
|
3713
1988
|
const floatingStyles = React.useMemo(() => {
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
top: 0,
|
|
3723
|
-
left: 0
|
|
3724
|
-
};
|
|
3725
|
-
} else if (adaptiveOrigin) {
|
|
3726
|
-
base = {
|
|
3727
|
-
position: resolvedPosition,
|
|
3728
|
-
[sideX]: x,
|
|
3729
|
-
[sideY]: y
|
|
3730
|
-
};
|
|
3731
|
-
} else {
|
|
3732
|
-
base = {
|
|
3733
|
-
...originalFloatingStyles,
|
|
3734
|
-
position: resolvedPosition
|
|
3735
|
-
};
|
|
3736
|
-
}
|
|
3737
|
-
|
|
3738
|
-
// Seed the available size vars so consumer `max-height: min(x, var(--available-height))` rules
|
|
3739
|
-
// resolve to a valid length on the first positioning pass, before `size()` writes the real
|
|
3740
|
-
// values. Without a fallback the unresolved `var()` invalidates the whole declaration, so the
|
|
3741
|
-
// popup is measured unconstrained while `flip()` picks its side, against the full content
|
|
3742
|
-
// height rather than the capped one. Seeded unconditionally (not only while `!isPositioned`):
|
|
3743
|
-
// the keys must stay present with a constant value so React's per-property style diff never
|
|
3744
|
-
// rewrites them after mount, preserving the px values `size()` sets imperatively. Moving them
|
|
3745
|
-
// into the `!isPositioned` branch makes React remove them once positioned, wiping `size()`'s
|
|
3746
|
-
// values and leaving the popup unconstrained.
|
|
3747
|
-
base[AVAILABLE_WIDTH_VAR] = '100vw';
|
|
3748
|
-
base[AVAILABLE_HEIGHT_VAR] = '100vh';
|
|
1989
|
+
const base = adaptiveOrigin ? {
|
|
1990
|
+
position: resolvedPosition,
|
|
1991
|
+
[sideX]: x,
|
|
1992
|
+
[sideY]: y
|
|
1993
|
+
} : {
|
|
1994
|
+
position: resolvedPosition,
|
|
1995
|
+
...originalFloatingStyles
|
|
1996
|
+
};
|
|
3749
1997
|
if (!isPositioned) {
|
|
3750
1998
|
base.opacity = 0;
|
|
3751
1999
|
}
|
|
@@ -3796,10 +2044,10 @@ function useAnchorPositioningWithHook(params, useFloatingHook) {
|
|
|
3796
2044
|
// and flips back lazily, not eagerly. Ideal for filtered lists that change
|
|
3797
2045
|
// the size of the popup dynamically to avoid unwanted flipping when typing.
|
|
3798
2046
|
useIsoLayoutEffect(() => {
|
|
3799
|
-
if (lazyFlip && mounted && isPositioned
|
|
2047
|
+
if (lazyFlip && mounted && isPositioned) {
|
|
3800
2048
|
setMountSide(renderedSide);
|
|
3801
2049
|
}
|
|
3802
|
-
}, [lazyFlip, mounted, isPositioned, renderedSide
|
|
2050
|
+
}, [lazyFlip, mounted, isPositioned, renderedSide]);
|
|
3803
2051
|
const arrowStyles = React.useMemo(() => ({
|
|
3804
2052
|
position: 'absolute',
|
|
3805
2053
|
top: middlewareData.arrow?.y,
|
|
@@ -3884,57 +2132,64 @@ function useAnchoredPopupScrollLock(enabled, touchOpen, positionerElement, refer
|
|
|
3884
2132
|
useScrollLock(enabled && (!touchOpen || touchOpenShouldLockScroll), referenceElement);
|
|
3885
2133
|
}
|
|
3886
2134
|
|
|
2135
|
+
let IndexGuessBehavior = /*#__PURE__*/function (IndexGuessBehavior) {
|
|
2136
|
+
IndexGuessBehavior[IndexGuessBehavior["None"] = 0] = "None";
|
|
2137
|
+
IndexGuessBehavior[IndexGuessBehavior["GuessFromOrder"] = 1] = "GuessFromOrder";
|
|
2138
|
+
return IndexGuessBehavior;
|
|
2139
|
+
}({});
|
|
2140
|
+
|
|
3887
2141
|
/**
|
|
3888
2142
|
* Used to register a list item and its index (DOM position) in the `CompositeList`.
|
|
3889
2143
|
*/
|
|
3890
2144
|
function useCompositeListItem(params = {}) {
|
|
3891
2145
|
const {
|
|
3892
|
-
guess,
|
|
3893
2146
|
label,
|
|
3894
2147
|
metadata,
|
|
3895
2148
|
textRef,
|
|
2149
|
+
indexGuessBehavior,
|
|
3896
2150
|
index: externalIndex
|
|
3897
2151
|
} = params;
|
|
3898
2152
|
const {
|
|
3899
2153
|
register,
|
|
3900
2154
|
unregister,
|
|
3901
2155
|
subscribeMapChange,
|
|
2156
|
+
elementsRef,
|
|
2157
|
+
labelsRef,
|
|
3902
2158
|
nextIndexRef
|
|
3903
2159
|
} = useCompositeListContext();
|
|
3904
|
-
|
|
3905
|
-
// Guess the index from the render order. This avoids a re-render after mount for
|
|
3906
|
-
// flat lists rendered in DOM order; when the guess is wrong (grouped or out-of-order
|
|
3907
|
-
// rendering), the commit flush corrects it before paint.
|
|
3908
2160
|
const indexRef = React.useRef(-1);
|
|
3909
|
-
const [
|
|
2161
|
+
const [index, setIndex] = React.useState(externalIndex ?? (indexGuessBehavior === IndexGuessBehavior.GuessFromOrder ? () => {
|
|
3910
2162
|
if (indexRef.current === -1) {
|
|
3911
2163
|
const newIndex = nextIndexRef.current;
|
|
3912
2164
|
nextIndexRef.current += 1;
|
|
3913
2165
|
indexRef.current = newIndex;
|
|
3914
2166
|
}
|
|
3915
2167
|
return indexRef.current;
|
|
3916
|
-
} : -1);
|
|
3917
|
-
const index = externalIndex ?? internalIndex;
|
|
2168
|
+
} : -1));
|
|
3918
2169
|
const componentRef = React.useRef(null);
|
|
3919
|
-
|
|
3920
|
-
// Deliberately identity-sensitive: nested items sharing one DOM node rely on ref attachment
|
|
3921
|
-
// order to decide which registration wins, and republishing from an effect instead would let
|
|
3922
|
-
// an inner item's later update silently take ownership from the outer one.
|
|
3923
2170
|
const ref = React.useCallback(node => {
|
|
3924
|
-
const previousNode = componentRef.current;
|
|
3925
|
-
if (previousNode) {
|
|
3926
|
-
unregister(previousNode);
|
|
3927
|
-
}
|
|
3928
2171
|
componentRef.current = node;
|
|
2172
|
+
if (index !== -1 && node !== null) {
|
|
2173
|
+
elementsRef.current[index] = node;
|
|
2174
|
+
if (labelsRef) {
|
|
2175
|
+
const isLabelDefined = label !== undefined;
|
|
2176
|
+
labelsRef.current[index] = isLabelDefined ? label : textRef?.current?.textContent ?? node.textContent;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
}, [index, elementsRef, labelsRef, label, textRef]);
|
|
2180
|
+
useIsoLayoutEffect(() => {
|
|
2181
|
+
if (externalIndex != null) {
|
|
2182
|
+
return undefined;
|
|
2183
|
+
}
|
|
2184
|
+
const node = componentRef.current;
|
|
3929
2185
|
if (node) {
|
|
3930
|
-
register(node,
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
textRef
|
|
3935
|
-
});
|
|
2186
|
+
register(node, metadata);
|
|
2187
|
+
return () => {
|
|
2188
|
+
unregister(node);
|
|
2189
|
+
};
|
|
3936
2190
|
}
|
|
3937
|
-
|
|
2191
|
+
return undefined;
|
|
2192
|
+
}, [externalIndex, register, unregister, metadata]);
|
|
3938
2193
|
useIsoLayoutEffect(() => {
|
|
3939
2194
|
if (externalIndex != null) {
|
|
3940
2195
|
return undefined;
|
|
@@ -3942,14 +2197,14 @@ function useCompositeListItem(params = {}) {
|
|
|
3942
2197
|
return subscribeMapChange(map => {
|
|
3943
2198
|
const i = componentRef.current ? map.get(componentRef.current)?.index : null;
|
|
3944
2199
|
if (i != null) {
|
|
3945
|
-
|
|
2200
|
+
setIndex(i);
|
|
3946
2201
|
}
|
|
3947
2202
|
});
|
|
3948
|
-
}, [externalIndex, subscribeMapChange]);
|
|
2203
|
+
}, [externalIndex, subscribeMapChange, setIndex]);
|
|
3949
2204
|
return {
|
|
3950
2205
|
ref,
|
|
3951
2206
|
index
|
|
3952
2207
|
};
|
|
3953
2208
|
}
|
|
3954
2209
|
|
|
3955
|
-
export {
|
|
2210
|
+
export { removeItem as A, adaptiveOrigin as B, CompositeList as C, DEFAULT_VALIDITY_STATE as D, isGroupedItems as E, FieldRootContext as F, DEFAULT_FIELD_ROOT_CONTEXT as G, DEFAULT_FIELD_STATE_ATTRIBUTES as H, IndexGuessBehavior as I, getDefaultLabelId as J, LabelableContext as L, useFormContext as a, useFieldRootContext as b, useLabelableId as c, useRegisterFieldControl as d, compareItemEquality as e, fieldValidityMapping as f, findItemIndex as g, hasNullItemLabel as h, useFloatingRootContext as i, useListNavigation as j, useTypeahead as k, defaultItemEquality as l, stringifyAsLabel as m, areArraysEqual as n, getPseudoElementBounds as o, resolveMultipleLabels as p, resolveSelectedLabel as q, resolveAriaLabelledBy as r, stringifyAsValue as s, useAnchoredPopupScrollLock as t, useLabelableContext as u, useAnchorPositioning as v, usePositioner as w, selectedValueIncludes as x, getDisabledMountTransitionStyles as y, useCompositeListItem as z };
|