@jobber/components 9.5.3 → 9.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Combobox.d.ts +1 -0
- package/Combobox.js +17 -0
- package/dist/Autocomplete/index.cjs +0 -2
- package/dist/Autocomplete/index.mjs +0 -2
- package/dist/Autocomplete-cjs.js +4 -5
- package/dist/Autocomplete-es.js +1 -2
- package/dist/Card/index.cjs +2 -2
- package/dist/Card/index.mjs +2 -2
- package/dist/Chip/index.cjs +0 -2
- package/dist/Chip/index.mjs +0 -2
- package/dist/Chips/InternalChipDismissible/hooks/index.cjs +0 -2
- package/dist/Chips/InternalChipDismissible/hooks/index.mjs +0 -2
- package/dist/Chips/InternalChipDismissible/index.cjs +0 -2
- package/dist/Chips/InternalChipDismissible/index.mjs +0 -2
- package/dist/Chips/index.cjs +0 -2
- package/dist/Chips/index.mjs +0 -2
- package/dist/Combobox/Combobox.contentSlots.d.ts +5 -0
- package/dist/Combobox/Combobox.context.d.ts +34 -0
- package/dist/Combobox/Combobox.d.ts +69 -0
- package/dist/Combobox/Combobox.footer.d.ts +7 -0
- package/dist/Combobox/Combobox.items.d.ts +25 -0
- package/dist/Combobox/Combobox.responsive.d.ts +54 -0
- package/dist/Combobox/Combobox.selectAll.d.ts +4 -0
- package/dist/Combobox/Combobox.slotFactory.d.ts +7 -0
- package/dist/Combobox/Combobox.testUtils.d.ts +12 -0
- package/dist/Combobox/Combobox.types.d.ts +166 -0
- package/dist/Combobox/index.cjs +35 -0
- package/dist/Combobox/index.d.ts +2 -0
- package/dist/Combobox/index.mjs +29 -0
- package/dist/Combobox-cjs.js +675 -0
- package/dist/Combobox-es.js +673 -0
- package/dist/ComboboxPrimitive-cjs.js +88 -47
- package/dist/ComboboxPrimitive-es.js +39 -23
- package/dist/{ComboboxChipRemove-cjs.js → ComboboxSeparator-cjs.js} +501 -455
- package/dist/{ComboboxChipRemove-es.js → ComboboxSeparator-es.js} +500 -456
- package/dist/ConfirmationModal/index.cjs +0 -2
- package/dist/ConfirmationModal/index.mjs +0 -2
- package/dist/ContentBlock/index.cjs +1 -0
- package/dist/ContentBlock/index.mjs +1 -0
- package/dist/ContentBlock-cjs.js +2 -18
- package/dist/ContentBlock-es.js +1 -17
- package/dist/DataDump/index.cjs +2 -2
- package/dist/DataDump/index.mjs +2 -2
- package/dist/DataList/components/DataListActions/index.cjs +0 -2
- package/dist/DataList/components/DataListActions/index.mjs +0 -2
- package/dist/DataList/components/DataListBulkActions/index.cjs +0 -2
- package/dist/DataList/components/DataListBulkActions/index.mjs +0 -2
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +0 -2
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +0 -2
- package/dist/DataList/components/DataListFilters/index.cjs +0 -2
- package/dist/DataList/components/DataListFilters/index.mjs +0 -2
- package/dist/DataList/components/DataListHeader/index.cjs +0 -2
- package/dist/DataList/components/DataListHeader/index.mjs +0 -2
- package/dist/DataList/components/DataListItem/index.cjs +0 -2
- package/dist/DataList/components/DataListItem/index.mjs +0 -2
- package/dist/DataList/components/DataListItemActions/index.cjs +0 -2
- package/dist/DataList/components/DataListItemActions/index.mjs +0 -2
- package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +0 -2
- package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +0 -2
- package/dist/DataList/components/DataListItems/index.cjs +0 -2
- package/dist/DataList/components/DataListItems/index.mjs +0 -2
- package/dist/DataList/components/DataListLayout/index.cjs +0 -2
- package/dist/DataList/components/DataListLayout/index.mjs +0 -2
- package/dist/DataList/components/DataListLayoutActions/index.cjs +0 -2
- package/dist/DataList/components/DataListLayoutActions/index.mjs +0 -2
- package/dist/DataList/index.cjs +0 -2
- package/dist/DataList/index.mjs +0 -2
- package/dist/DatePicker/index.cjs +0 -2
- package/dist/DatePicker/index.mjs +0 -2
- package/dist/DatePicker-cjs.js +4 -5
- package/dist/DatePicker-es.js +1 -2
- package/dist/Dialog/index.cjs +2 -2
- package/dist/Dialog/index.mjs +2 -2
- package/dist/DrawerDescription-cjs.js +268 -99
- package/dist/DrawerDescription-es.js +270 -103
- package/dist/DrawerTitle-cjs.js +2 -6
- package/dist/DrawerTitle-es.js +3 -7
- package/dist/FieldDescription-cjs.js +184 -181
- package/dist/FieldDescription-es.js +187 -184
- package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +0 -2
- package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +0 -2
- package/dist/FilterPicker/components/FilterPickerContent/index.cjs +0 -2
- package/dist/FilterPicker/components/FilterPickerContent/index.mjs +0 -2
- package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +0 -2
- package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +0 -2
- package/dist/FilterPicker/index.cjs +0 -2
- package/dist/FilterPicker/index.mjs +0 -2
- package/dist/FilterPickerContent-cjs.js +4 -5
- package/dist/FilterPickerContent-es.js +1 -2
- package/dist/FormatFile/index.cjs +0 -2
- package/dist/FormatFile/index.mjs +0 -2
- package/dist/Gallery/index.cjs +0 -2
- package/dist/Gallery/index.mjs +0 -2
- package/dist/InputDate/index.cjs +0 -2
- package/dist/InputDate/index.mjs +0 -2
- package/dist/InputNumber/index.cjs +2 -2
- package/dist/InputNumber/index.mjs +2 -2
- package/dist/InputNumber/types.d.ts +5 -0
- package/dist/InputNumber-cjs.js +2 -2
- package/dist/InputNumber-es.js +2 -2
- package/dist/LightBox/index.cjs +0 -2
- package/dist/LightBox/index.mjs +0 -2
- package/dist/Menu/index.cjs +2 -2
- package/dist/Menu/index.mjs +2 -2
- package/dist/Menu-cjs.js +4 -5
- package/dist/Menu-es.js +1 -2
- package/dist/MenuSubmenuTrigger-cjs.js +206 -164
- package/dist/MenuSubmenuTrigger-es.js +194 -152
- package/dist/Modal/index.cjs +0 -2
- package/dist/Modal/index.mjs +1 -3
- package/dist/NumberFieldInput-cjs.js +187 -308
- package/dist/NumberFieldInput-es.js +187 -308
- package/dist/Page/index.cjs +2 -2
- package/dist/Page/index.mjs +2 -2
- package/dist/Popover/index.cjs +0 -2
- package/dist/Popover/index.mjs +0 -2
- package/dist/Popover-cjs.js +7 -8
- package/dist/Popover-es.js +1 -2
- package/dist/ScrollAreaViewport-cjs.js +747 -1093
- package/dist/ScrollAreaViewport-es.js +734 -1081
- package/dist/Select/index.cjs +2 -2
- package/dist/Select/index.mjs +2 -2
- package/dist/SelectGroupLabel-cjs.js +207 -306
- package/dist/SelectGroupLabel-es.js +203 -302
- package/dist/SelectPrimitive-cjs.js +11 -17
- package/dist/SelectPrimitive-es.js +1 -7
- package/dist/Tooltip/index.cjs +0 -2
- package/dist/Tooltip/index.mjs +0 -2
- package/dist/Tooltip-cjs.js +6 -7
- package/dist/Tooltip-es.js +1 -2
- package/dist/buttonRenderAdapter-cjs.js +2 -1
- package/dist/buttonRenderAdapter-es.js +2 -1
- package/dist/dialogReturnFocus-cjs.js +1 -1
- package/dist/dialogReturnFocus-es.js +2 -2
- package/dist/docs/InputNumber/InputNumber.md +2 -2
- package/dist/docs/SelectPrimitive/SelectPrimitive.md +1 -1
- package/dist/floating-ui.react-cjs.js +2557 -185
- package/dist/floating-ui.react-es.js +2512 -149
- package/dist/getMappedBreakpointWidth-cjs.js +21 -0
- package/dist/getMappedBreakpointWidth-es.js +18 -0
- package/dist/index.cjs +15 -10
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +14 -10
- package/dist/mergeClassName-cjs.js +12 -0
- package/dist/mergeClassName-es.js +10 -0
- package/dist/primitives/BottomSheet/index.cjs +1 -1
- package/dist/primitives/BottomSheet/index.mjs +1 -1
- package/dist/primitives/ComboboxPrimitive/ComboboxPrimitive.d.ts +2 -2
- package/dist/primitives/ComboboxPrimitive/index.cjs +4 -5
- package/dist/primitives/ComboboxPrimitive/index.mjs +4 -5
- package/dist/primitives/SelectPrimitive/index.cjs +1 -2
- package/dist/primitives/SelectPrimitive/index.mjs +1 -2
- package/dist/primitives/index.cjs +3 -3
- package/dist/primitives/index.mjs +3 -3
- package/dist/scrollEdges-cjs.js +1 -11
- package/dist/scrollEdges-es.js +1 -11
- package/dist/scrollable-cjs.js +58 -0
- package/dist/scrollable-es.js +54 -0
- package/dist/styles.css +759 -42
- package/dist/unstyledPrimitives/index.cjs +720 -478
- package/dist/unstyledPrimitives/index.mjs +663 -421
- package/dist/useCompositeListItem-cjs.js +2108 -361
- package/dist/useCompositeListItem-es.js +2076 -331
- package/dist/useLabel-cjs.js +2 -3
- package/dist/useLabel-es.js +2 -3
- package/dist/useRenderElement-cjs.js +9 -7
- package/dist/useRenderElement-es.js +9 -7
- package/dist/useScrollLock-cjs.js +819 -344
- package/dist/useScrollLock-es.js +732 -296
- package/dist/useScrollToActive-cjs.js +4 -5
- package/dist/useScrollToActive-es.js +1 -2
- package/dist/utils/meta/meta.json +43 -1
- package/package.json +8 -3
- package/dist/floating-ui.react-dom-cjs.js +0 -2103
- package/dist/floating-ui.react-dom-es.js +0 -2072
- package/dist/floating-ui.utils-cjs.js +0 -342
- package/dist/floating-ui.utils-es.js +0 -300
|
@@ -1,9 +1,1720 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { useLayoutEffect } from 'react';
|
|
3
|
+
import { ae as evaluate, af as getSide, ag as getSideAxis, ah as getOppositePlacement, ai as getExpandedPlacements, aj as getOppositeAxisPlacements, ak as getAlignmentSides, al as getAlignment, am as min, an as max, ao as getAlignmentAxis, ap as getPaddingObject, aa as rectToClientRect, aq as getOppositeAxis, ar as clamp, as as getAxisLength, at as getDocumentElement, au as isElement, i as isHTMLElement, av as createCoords, aw as round, ax as isTopLayer, ay as getNodeName, az as isOverflowElement, aA as getNodeScroll, I as getWindow, b as getParentNode, a as isLastTraversableNode, aB as isTableElement, aC as isContainingBlock, aD as getContainingBlock, g as getComputedStyle$1, aE as getOverflowAncestors, aF as getFrameElement, aG as isWebKit, aH as floor, aI as useId, aJ as useFloatingParentNodeId, aK as FloatingRootStore, aL as PopupTriggerMap, c as useIsoLayoutEffect, aM as useFloatingTree, $ as getFloatingFocusElement, aN as isTypeableCombobox, w as useValueAsRef, d as useStableCallback, a8 as useAnimationFrame, aO as isIndexOutOfListBounds, aP as getMinListIndex, aQ as getMaxListIndex, D as activeElement, o as ownerDocument, a0 as contains, aR as stopEvent, h as createChangeEventDetails, aS as listNavigation, aT as findNonDisabledListIndex, e as getTarget, Y as focusOut, a9 as webkit, aU as enqueueFocus, ac as isVirtualClick, aV as isVirtualPointerEvent, aW as ARROW_UP, aX as ARROW_DOWN, aY as ARROW_LEFT, aZ as ARROW_RIGHT, q as useTimeout, a_ as isElementVisible, a$ as isListIndexDisabled, u as useBaseUiId, b0 as jsdom, a7 as useDirection, b1 as DISABLED_TRANSITIONS_STYLE, a6 as popupStateMapping, b2 as useScrollLock } from './useScrollLock-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
|
|
6
|
+
import * as ReactDOM from 'react-dom';
|
|
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
|
+
};
|
|
7
1718
|
|
|
8
1719
|
function useFloatingRootContext(options) {
|
|
9
1720
|
const {
|
|
@@ -52,16 +1763,17 @@ function useFloatingRootContext(options) {
|
|
|
52
1763
|
}
|
|
53
1764
|
|
|
54
1765
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
1766
|
+
* Base UI's private `useFloating` path. The caller must supply the root store, so this skips the
|
|
1767
|
+
* internal root-context hook used by the public Floating UI-compatible API.
|
|
57
1768
|
*/
|
|
58
|
-
function
|
|
1769
|
+
function useBaseUIFloating(options) {
|
|
1770
|
+
return useFloatingWithStore(options, options.rootContext);
|
|
1771
|
+
}
|
|
1772
|
+
function useFloatingWithStore(options, store) {
|
|
59
1773
|
const {
|
|
60
1774
|
nodeId,
|
|
61
1775
|
externalTree
|
|
62
1776
|
} = options;
|
|
63
|
-
const internalStore = useFloatingRootContext(options);
|
|
64
|
-
const store = options.rootContext || internalStore;
|
|
65
1777
|
const referenceElement = store.useState('referenceElement');
|
|
66
1778
|
const floatingElement = store.useState('floatingElement');
|
|
67
1779
|
const domReferenceElement = store.useState('domReferenceElement');
|
|
@@ -77,7 +1789,7 @@ function useFloating(options = {}) {
|
|
|
77
1789
|
floating: floatingElement,
|
|
78
1790
|
domReference: domReferenceElement
|
|
79
1791
|
}), [referenceElement, floatingElement, domReferenceElement]);
|
|
80
|
-
const position = useFloating
|
|
1792
|
+
const position = useFloating({
|
|
81
1793
|
...options,
|
|
82
1794
|
elements: {
|
|
83
1795
|
...storeElements,
|
|
@@ -167,6 +1879,13 @@ function useFloating(options = {}) {
|
|
|
167
1879
|
}
|
|
168
1880
|
|
|
169
1881
|
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
|
+
}
|
|
170
1889
|
function doSwitch(orientation, vertical, horizontal) {
|
|
171
1890
|
switch (orientation) {
|
|
172
1891
|
case 'vertical':
|
|
@@ -573,6 +2292,9 @@ function useListNavigation(context, props) {
|
|
|
573
2292
|
}),
|
|
574
2293
|
// Safari
|
|
575
2294
|
onMouseMove(event) {
|
|
2295
|
+
if (isStationaryWebKitPointer(event)) {
|
|
2296
|
+
return;
|
|
2297
|
+
}
|
|
576
2298
|
forceSyncFocusRef.current = true;
|
|
577
2299
|
forceScrollIntoViewRef.current = false;
|
|
578
2300
|
if (focusItemOnHover) {
|
|
@@ -636,7 +2358,10 @@ function useListNavigation(context, props) {
|
|
|
636
2358
|
}
|
|
637
2359
|
commonOnKeyDown(event);
|
|
638
2360
|
},
|
|
639
|
-
onPointerMove() {
|
|
2361
|
+
onPointerMove(event) {
|
|
2362
|
+
if (isStationaryWebKitPointer(event)) {
|
|
2363
|
+
return;
|
|
2364
|
+
}
|
|
640
2365
|
isPointerModalityRef.current = true;
|
|
641
2366
|
}
|
|
642
2367
|
};
|
|
@@ -757,18 +2482,19 @@ function useTypeahead(context, props) {
|
|
|
757
2482
|
const prevIndexRef = React.useRef(selectedIndex ?? activeIndex ?? -1);
|
|
758
2483
|
const matchIndexRef = React.useRef(null);
|
|
759
2484
|
const onKeyDown = useStableCallback(event => {
|
|
760
|
-
function
|
|
761
|
-
|
|
762
|
-
return !element || isElementVisible(element);
|
|
2485
|
+
function getElement(index) {
|
|
2486
|
+
return elementsRef?.current[index];
|
|
763
2487
|
}
|
|
764
2488
|
function isItemAvailable(index) {
|
|
765
|
-
|
|
2489
|
+
const element = getElement(index);
|
|
2490
|
+
if (element && !isElementVisible(element) || element?.matches(':disabled')) {
|
|
766
2491
|
return false;
|
|
767
2492
|
}
|
|
768
|
-
// Visibility
|
|
769
|
-
//
|
|
770
|
-
//
|
|
771
|
-
// visible
|
|
2493
|
+
// Visibility and native disabled state are handled above; pass an empty
|
|
2494
|
+
// element list so `isListIndexDisabled` resolves only the explicit
|
|
2495
|
+
// `disabledIndices` (array/predicate) and skips its own fallbacks.
|
|
2496
|
+
// Consumers that don't pass `disabledIndices` keep matching every visible
|
|
2497
|
+
// item except native disabled elements provided through `elementsRef`.
|
|
772
2498
|
return disabledIndices == null || !isListIndexDisabled(EMPTY_ARRAY, index, disabledIndices);
|
|
773
2499
|
}
|
|
774
2500
|
function getMatchingIndex(list, string, startIndex = 0) {
|
|
@@ -876,12 +2602,6 @@ function useTypeahead(context, props) {
|
|
|
876
2602
|
stringRef.current = '';
|
|
877
2603
|
}
|
|
878
2604
|
}, [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]);
|
|
885
2605
|
const sharedProps = React.useMemo(() => ({
|
|
886
2606
|
onKeyDown,
|
|
887
2607
|
onBlur
|
|
@@ -921,6 +2641,12 @@ function findItemIndex(itemValues, selectedValue, comparer) {
|
|
|
921
2641
|
return compareItemEquality(itemValue, selectedValue, comparer);
|
|
922
2642
|
});
|
|
923
2643
|
}
|
|
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
|
+
}
|
|
924
2650
|
function removeItem(selectedValues, itemValue, comparer) {
|
|
925
2651
|
return selectedValues.filter(selectedValue => !compareItemEquality(itemValue, selectedValue, comparer));
|
|
926
2652
|
}
|
|
@@ -1043,38 +2769,6 @@ function resolveMultipleLabels(values, items, itemToStringLabel) {
|
|
|
1043
2769
|
}, []);
|
|
1044
2770
|
}
|
|
1045
2771
|
|
|
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
|
-
|
|
1078
2772
|
const DEFAULT_VALIDITY_STATE = {
|
|
1079
2773
|
badInput: false,
|
|
1080
2774
|
customError: false,
|
|
@@ -1106,11 +2800,11 @@ const fieldValidityMapping = {
|
|
|
1106
2800
|
}
|
|
1107
2801
|
if (value) {
|
|
1108
2802
|
return {
|
|
1109
|
-
|
|
2803
|
+
'data-valid': ''
|
|
1110
2804
|
};
|
|
1111
2805
|
}
|
|
1112
2806
|
return {
|
|
1113
|
-
|
|
2807
|
+
'data-invalid': ''
|
|
1114
2808
|
};
|
|
1115
2809
|
}
|
|
1116
2810
|
};
|
|
@@ -1127,29 +2821,22 @@ const DEFAULT_FIELD_ROOT_CONTEXT = {
|
|
|
1127
2821
|
},
|
|
1128
2822
|
setValidityData: NOOP,
|
|
1129
2823
|
disabled: undefined,
|
|
1130
|
-
touched: DEFAULT_FIELD_STATE_ATTRIBUTES.touched,
|
|
1131
2824
|
setTouched: NOOP,
|
|
1132
|
-
dirty: DEFAULT_FIELD_STATE_ATTRIBUTES.dirty,
|
|
1133
2825
|
setDirty: NOOP,
|
|
1134
|
-
filled: DEFAULT_FIELD_STATE_ATTRIBUTES.filled,
|
|
1135
2826
|
setFilled: NOOP,
|
|
1136
|
-
focused: DEFAULT_FIELD_STATE_ATTRIBUTES.focused,
|
|
1137
2827
|
setFocused: NOOP,
|
|
1138
|
-
validate: () => null,
|
|
1139
2828
|
validationMode: 'onSubmit',
|
|
1140
|
-
validationDebounceTime: 0,
|
|
1141
2829
|
shouldValidateOnChange: () => false,
|
|
1142
2830
|
state: DEFAULT_FIELD_ROOT_STATE,
|
|
1143
|
-
markedDirtyRef: {
|
|
1144
|
-
current: false
|
|
1145
|
-
},
|
|
1146
2831
|
registerFieldControl: NOOP,
|
|
1147
2832
|
validation: {
|
|
1148
2833
|
getValidationProps: (_disabled, props = EMPTY_OBJECT) => props,
|
|
1149
2834
|
inputRef: {
|
|
1150
2835
|
current: null
|
|
1151
2836
|
},
|
|
2837
|
+
registeredInputs: new Map(),
|
|
1152
2838
|
registerInput: NOOP,
|
|
2839
|
+
getInputControl: () => null,
|
|
1153
2840
|
commit: async () => {},
|
|
1154
2841
|
change: NOOP
|
|
1155
2842
|
}
|
|
@@ -1168,14 +2855,16 @@ function useRegisterFieldControl(controlRef, id, value, getFormValueOverride, en
|
|
|
1168
2855
|
const {
|
|
1169
2856
|
registerFieldControl
|
|
1170
2857
|
} = useFieldRootContext();
|
|
1171
|
-
const sourceRef =
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
2858
|
+
const sourceRef = useRefWithInit(() => Symbol());
|
|
2859
|
+
|
|
2860
|
+
// Re-register without unregistering first: re-registration with the same id updates the
|
|
2861
|
+
// form's fields Map entry in place, while a delete + re-add would move the field to the
|
|
2862
|
+
// end of the Map every time its value changes.
|
|
1175
2863
|
useIsoLayoutEffect(() => {
|
|
1176
2864
|
const source = sourceRef.current;
|
|
1177
|
-
if (!
|
|
1178
|
-
|
|
2865
|
+
if (!enabled) {
|
|
2866
|
+
registerFieldControl(source, undefined);
|
|
2867
|
+
return;
|
|
1179
2868
|
}
|
|
1180
2869
|
const registration = {
|
|
1181
2870
|
controlRef,
|
|
@@ -1185,13 +2874,19 @@ function useRegisterFieldControl(controlRef, id, value, getFormValueOverride, en
|
|
|
1185
2874
|
value
|
|
1186
2875
|
};
|
|
1187
2876
|
registerFieldControl(source, registration);
|
|
2877
|
+
}, [controlRef, enabled, getFormValueOverride, id, name, registerFieldControl, sourceRef, value]);
|
|
2878
|
+
useIsoLayoutEffect(() => {
|
|
2879
|
+
const source = sourceRef.current;
|
|
1188
2880
|
return () => {
|
|
1189
2881
|
registerFieldControl(source, undefined);
|
|
1190
2882
|
};
|
|
1191
|
-
}, [
|
|
2883
|
+
}, [registerFieldControl, sourceRef]);
|
|
1192
2884
|
}
|
|
1193
2885
|
|
|
1194
2886
|
const FormContext = /*#__PURE__*/React.createContext({
|
|
2887
|
+
elementRef: {
|
|
2888
|
+
current: null
|
|
2889
|
+
},
|
|
1195
2890
|
formRef: {
|
|
1196
2891
|
current: {
|
|
1197
2892
|
fields: new Map()
|
|
@@ -1239,7 +2934,7 @@ function useLabelableId(params = {}) {
|
|
|
1239
2934
|
} = useLabelableContext();
|
|
1240
2935
|
const defaultId = useBaseUiId(id);
|
|
1241
2936
|
const controlIdForEffect = implicit ? controlId : undefined;
|
|
1242
|
-
const controlSourceRef = useRefWithInit(() => Symbol(
|
|
2937
|
+
const controlSourceRef = useRefWithInit(() => Symbol());
|
|
1243
2938
|
const hasRegisteredRef = React.useRef(false);
|
|
1244
2939
|
const hadExplicitIdRef = React.useRef(id != null);
|
|
1245
2940
|
const unregisterControlId = useStableCallback(() => {
|
|
@@ -1288,6 +2983,19 @@ function areArraysEqual(array1, array2, itemComparer = (a, b) => a === b) {
|
|
|
1288
2983
|
return array1.length === array2.length && array1.every((value, index) => itemComparer(value, array2[index]));
|
|
1289
2984
|
}
|
|
1290
2985
|
|
|
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
|
+
}
|
|
1291
2999
|
function getPseudoElementBounds(element) {
|
|
1292
3000
|
const elementRect = element.getBoundingClientRect();
|
|
1293
3001
|
const win = getWindow(element);
|
|
@@ -1334,12 +3042,7 @@ function resolveAriaLabelledBy(fieldLabelId, localLabelId) {
|
|
|
1334
3042
|
const CompositeListContext = /*#__PURE__*/React.createContext({
|
|
1335
3043
|
register: () => {},
|
|
1336
3044
|
unregister: () => {},
|
|
1337
|
-
subscribeMapChange: () => {
|
|
1338
|
-
return () => {};
|
|
1339
|
-
},
|
|
1340
|
-
elementsRef: {
|
|
1341
|
-
current: []
|
|
1342
|
-
},
|
|
3045
|
+
subscribeMapChange: () => () => {},
|
|
1343
3046
|
nextIndexRef: {
|
|
1344
3047
|
current: 0
|
|
1345
3048
|
}
|
|
@@ -1352,7 +3055,6 @@ function useCompositeListContext() {
|
|
|
1352
3055
|
/* eslint-disable no-bitwise */
|
|
1353
3056
|
/**
|
|
1354
3057
|
* Provides context for a list of items in a composite component.
|
|
1355
|
-
* @internal
|
|
1356
3058
|
*/
|
|
1357
3059
|
function CompositeList(props) {
|
|
1358
3060
|
const {
|
|
@@ -1362,114 +3064,146 @@ function CompositeList(props) {
|
|
|
1362
3064
|
onMapChange: onMapChangeProp
|
|
1363
3065
|
} = props;
|
|
1364
3066
|
const onMapChange = useStableCallback(onMapChangeProp);
|
|
1365
|
-
const
|
|
3067
|
+
const [, setMapTick] = React.useState(false);
|
|
1366
3068
|
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
|
-
|
|
1376
3069
|
const map = useRefWithInit(createMap).current;
|
|
1377
|
-
|
|
1378
|
-
const
|
|
1379
|
-
const
|
|
1380
|
-
const
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
3070
|
+
const nextIndexRef = React.useRef(0);
|
|
3071
|
+
const isDirtyRef = React.useRef(true);
|
|
3072
|
+
const itemsRef = React.useRef([]);
|
|
3073
|
+
const mutationObserverRef = React.useRef(null);
|
|
3074
|
+
|
|
3075
|
+
// Item effects can run without their parent rendering. Schedule one synchronous
|
|
3076
|
+
// parent update for the whole commit so refs are rebuilt before paint and while
|
|
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();
|
|
1384
3088
|
});
|
|
1385
3089
|
const unregister = useStableCallback(node => {
|
|
1386
3090
|
map.delete(node);
|
|
1387
|
-
|
|
1388
|
-
setMapTick(lastTickRef.current);
|
|
3091
|
+
scheduleMapUpdate();
|
|
1389
3092
|
});
|
|
1390
|
-
const
|
|
1391
|
-
const
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
...metadata,
|
|
1399
|
-
index
|
|
3093
|
+
const syncRefs = useStableCallback(items => {
|
|
3094
|
+
const nextMap = new Map();
|
|
3095
|
+
elementsRef.current.length = 0;
|
|
3096
|
+
if (labelsRef) {
|
|
3097
|
+
labelsRef.current.length = 0;
|
|
3098
|
+
}
|
|
3099
|
+
items.forEach(item => {
|
|
3100
|
+
nextMap.set(item.element, {
|
|
3101
|
+
...(item.registration.metadata ?? {}),
|
|
3102
|
+
index: item.index
|
|
1400
3103
|
});
|
|
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
|
+
}
|
|
1401
3108
|
});
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
3109
|
+
nextIndexRef.current = elementsRef.current.length;
|
|
3110
|
+
return nextMap;
|
|
3111
|
+
});
|
|
3112
|
+
function observe(sortedNodes) {
|
|
3113
|
+
mutationObserverRef.current?.disconnect();
|
|
3114
|
+
mutationObserverRef.current = null;
|
|
3115
|
+
|
|
3116
|
+
// A single item can't reorder.
|
|
3117
|
+
if (typeof MutationObserver !== 'function' || sortedNodes.length < 2) {
|
|
3118
|
+
return;
|
|
1407
3119
|
}
|
|
1408
3120
|
const mutationObserver = new MutationObserver(entries => {
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
if (diff.size === 0) {
|
|
1416
|
-
lastTickRef.current += 1;
|
|
1417
|
-
setMapTick(lastTickRef.current);
|
|
3121
|
+
// Only verify the order after a move: a node that was removed and later
|
|
3122
|
+
// re-added within the same batch. Additions and removals alone can't
|
|
3123
|
+
// change the relative order of the remaining items, and items that mount
|
|
3124
|
+
// or unmount re-sort through `register`/`unregister`.
|
|
3125
|
+
if (!hasMovedNode(entries)) {
|
|
3126
|
+
return;
|
|
1418
3127
|
}
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
3128
|
+
let previousConnectedNode = null;
|
|
3129
|
+
|
|
3130
|
+
// If any connected node now appears before the previous connected node,
|
|
3131
|
+
// wrappers/items moved and the index map needs to be rebuilt.
|
|
3132
|
+
for (const node of sortedNodes) {
|
|
3133
|
+
if (!node.isConnected) {
|
|
3134
|
+
continue;
|
|
3135
|
+
}
|
|
3136
|
+
if (previousConnectedNode && sortByDocumentPosition(previousConnectedNode, node) > 0) {
|
|
3137
|
+
mutationObserver.disconnect();
|
|
3138
|
+
scheduleMapUpdate();
|
|
3139
|
+
return;
|
|
3140
|
+
}
|
|
3141
|
+
previousConnectedNode = node;
|
|
1425
3142
|
}
|
|
1426
3143
|
});
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
const
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
3144
|
+
mutationObserverRef.current = mutationObserver;
|
|
3145
|
+
|
|
3146
|
+
// A reorder that changes item indexes must invert at least one adjacent pair
|
|
3147
|
+
// from the previous sorted order. Observing each pair's common parent catches
|
|
3148
|
+
// both direct item moves and ancestor wrapper moves at the boundary.
|
|
3149
|
+
const roots = new Set();
|
|
3150
|
+
for (let i = 1; i < sortedNodes.length; i += 1) {
|
|
3151
|
+
const root = getCommonAncestor(sortedNodes[i - 1], sortedNodes[i]);
|
|
3152
|
+
if (root) {
|
|
3153
|
+
roots.add(root);
|
|
1436
3154
|
}
|
|
1437
|
-
if (labelsRef && labelsRef.current.length !== sortedMap.size) {
|
|
1438
|
-
labelsRef.current.length = sortedMap.size;
|
|
1439
|
-
}
|
|
1440
|
-
nextIndexRef.current = sortedMap.size;
|
|
1441
3155
|
}
|
|
1442
|
-
|
|
1443
|
-
|
|
3156
|
+
roots.forEach(root => mutationObserver.observe(root, {
|
|
3157
|
+
childList: true
|
|
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
|
+
});
|
|
1444
3169
|
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
|
+
}
|
|
1445
3175
|
return () => {
|
|
1446
3176
|
elementsRef.current = [];
|
|
1447
|
-
};
|
|
1448
|
-
}, [elementsRef]);
|
|
1449
|
-
useIsoLayoutEffect(() => {
|
|
1450
|
-
return () => {
|
|
1451
3177
|
if (labelsRef) {
|
|
1452
3178
|
labelsRef.current = [];
|
|
1453
3179
|
}
|
|
1454
3180
|
};
|
|
1455
|
-
}, [labelsRef]);
|
|
3181
|
+
}, [elementsRef, labelsRef, syncRefs]);
|
|
3182
|
+
useIsoLayoutEffect(() => {
|
|
3183
|
+
if (isDirtyRef.current) {
|
|
3184
|
+
flush();
|
|
3185
|
+
}
|
|
3186
|
+
});
|
|
3187
|
+
useIsoLayoutEffect(() => {
|
|
3188
|
+
return () => {
|
|
3189
|
+
mutationObserverRef.current?.disconnect();
|
|
3190
|
+
// React 18 Strict Mode replays effects without replaying callback refs.
|
|
3191
|
+
// Mark the retained map dirty so the replay rebuilds refs and observation.
|
|
3192
|
+
isDirtyRef.current = true;
|
|
3193
|
+
};
|
|
3194
|
+
}, []);
|
|
1456
3195
|
const subscribeMapChange = useStableCallback(fn => {
|
|
1457
3196
|
listeners.add(fn);
|
|
1458
3197
|
return () => {
|
|
1459
3198
|
listeners.delete(fn);
|
|
1460
3199
|
};
|
|
1461
3200
|
});
|
|
1462
|
-
useIsoLayoutEffect(() => {
|
|
1463
|
-
listeners.forEach(l => l(sortedMap));
|
|
1464
|
-
}, [listeners, sortedMap]);
|
|
1465
3201
|
const contextValue = React.useMemo(() => ({
|
|
1466
3202
|
register,
|
|
1467
3203
|
unregister,
|
|
1468
3204
|
subscribeMapChange,
|
|
1469
|
-
elementsRef,
|
|
1470
|
-
labelsRef,
|
|
1471
3205
|
nextIndexRef
|
|
1472
|
-
}), [register, unregister, subscribeMapChange,
|
|
3206
|
+
}), [register, unregister, subscribeMapChange, nextIndexRef]);
|
|
1473
3207
|
return /*#__PURE__*/jsx(CompositeListContext.Provider, {
|
|
1474
3208
|
value: contextValue,
|
|
1475
3209
|
children: children
|
|
@@ -1481,15 +3215,66 @@ function createMap() {
|
|
|
1481
3215
|
function createListeners() {
|
|
1482
3216
|
return new Set();
|
|
1483
3217
|
}
|
|
1484
|
-
function
|
|
1485
|
-
const
|
|
1486
|
-
|
|
1487
|
-
|
|
3218
|
+
function getCompositeListSnapshot(map) {
|
|
3219
|
+
const reservedIndices = new Set();
|
|
3220
|
+
const items = [];
|
|
3221
|
+
const automaticItems = [];
|
|
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);
|
|
1488
3251
|
}
|
|
1489
|
-
|
|
1490
|
-
|
|
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;
|
|
3261
|
+
}
|
|
3262
|
+
return ancestor;
|
|
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
|
+
}
|
|
1491
3271
|
}
|
|
1492
|
-
return
|
|
3272
|
+
return false;
|
|
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;
|
|
1493
3278
|
}
|
|
1494
3279
|
|
|
1495
3280
|
/**
|
|
@@ -1586,7 +3371,6 @@ const arrow = (options, deps) => ({
|
|
|
1586
3371
|
options: [options, deps]
|
|
1587
3372
|
});
|
|
1588
3373
|
|
|
1589
|
-
const nativeHideFn = hide$1().fn;
|
|
1590
3374
|
const hide = {
|
|
1591
3375
|
name: 'hide',
|
|
1592
3376
|
async fn(state) {
|
|
@@ -1597,10 +3381,15 @@ const hide = {
|
|
|
1597
3381
|
y
|
|
1598
3382
|
} = state.rects.reference;
|
|
1599
3383
|
const anchorHidden = width === 0 && height === 0 && x === 0 && y === 0;
|
|
1600
|
-
|
|
3384
|
+
// Mirrors Floating UI's `hide()` referenceHidden strategy. Floating UI injects
|
|
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;
|
|
1601
3390
|
return {
|
|
1602
3391
|
data: {
|
|
1603
|
-
referenceHidden:
|
|
3392
|
+
referenceHidden: referenceHidden || anchorHidden
|
|
1604
3393
|
}
|
|
1605
3394
|
};
|
|
1606
3395
|
}
|
|
@@ -1610,75 +3399,13 @@ const DEFAULT_SIDES = {
|
|
|
1610
3399
|
sideX: 'left',
|
|
1611
3400
|
sideY: 'top'
|
|
1612
3401
|
};
|
|
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
|
-
};
|
|
1644
3402
|
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
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
|
-
};
|
|
3403
|
+
// Self-contained stand-in for Floating UI's `Middleware` type. Referencing the real type in
|
|
3404
|
+
// store state makes `tsc` declaration emit reference `Platform`/`detectOverflow` from
|
|
3405
|
+
// `@floating-ui/core` internals, which fails as non-portable (TS2883) in consuming builds.
|
|
1681
3406
|
|
|
3407
|
+
const AVAILABLE_WIDTH_VAR = '--available-width';
|
|
3408
|
+
const AVAILABLE_HEIGHT_VAR = '--available-height';
|
|
1682
3409
|
function getLogicalSide(sideParam, renderedSide, isRtl) {
|
|
1683
3410
|
const isLogicalSideParam = sideParam === 'inline-start' || sideParam === 'inline-end';
|
|
1684
3411
|
const logicalRight = isRtl ? 'inline-start' : 'inline-end';
|
|
@@ -1714,6 +3441,9 @@ function getOffsetData(state, sideParam, isRtl) {
|
|
|
1714
3441
|
* `useFloating` hook.
|
|
1715
3442
|
*/
|
|
1716
3443
|
function useAnchorPositioning(params) {
|
|
3444
|
+
return useAnchorPositioningWithHook(params, useBaseUIFloating);
|
|
3445
|
+
}
|
|
3446
|
+
function useAnchorPositioningWithHook(params, useFloatingHook) {
|
|
1717
3447
|
const {
|
|
1718
3448
|
// Public parameters
|
|
1719
3449
|
anchor,
|
|
@@ -1733,7 +3463,7 @@ function useAnchorPositioning(params) {
|
|
|
1733
3463
|
floatingRootContext,
|
|
1734
3464
|
mounted,
|
|
1735
3465
|
collisionAvoidance,
|
|
1736
|
-
|
|
3466
|
+
shift: shift$1,
|
|
1737
3467
|
nodeId,
|
|
1738
3468
|
adaptiveOrigin,
|
|
1739
3469
|
lazyFlip = false,
|
|
@@ -1746,6 +3476,8 @@ function useAnchorPositioning(params) {
|
|
|
1746
3476
|
const collisionAvoidanceSide = collisionAvoidance.side || 'flip';
|
|
1747
3477
|
const collisionAvoidanceAlign = collisionAvoidance.align || 'flip';
|
|
1748
3478
|
const collisionAvoidanceFallbackAxisSide = collisionAvoidance.fallbackAxisSide || 'end';
|
|
3479
|
+
const shiftCrossAxis = shift$1?.crossAxis ?? false;
|
|
3480
|
+
const shiftRootBoundary = shift$1?.rootBoundary;
|
|
1749
3481
|
const anchorFn = typeof anchor === 'function' ? anchor : undefined;
|
|
1750
3482
|
const anchorFnCallback = useStableCallback(anchorFn);
|
|
1751
3483
|
const anchorDep = anchorFn ? anchorFnCallback : anchor;
|
|
@@ -1763,30 +3495,32 @@ function useAnchorPositioning(params) {
|
|
|
1763
3495
|
}[sideParam];
|
|
1764
3496
|
const placement = align === 'center' ? side : `${side}-${align}`;
|
|
1765
3497
|
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
|
+
}
|
|
1766
3513
|
|
|
1767
3514
|
// Create a bias to the preferred side.
|
|
1768
3515
|
// On iOS, when the mobile software keyboard opens, the input is exactly centered
|
|
1769
3516
|
// 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`.
|
|
1770
3519
|
const bias = 1;
|
|
1771
3520
|
const biasTop = sideParam === 'bottom' ? bias : 0;
|
|
1772
3521
|
const biasBottom = sideParam === 'top' ? bias : 0;
|
|
1773
3522
|
const biasLeft = sideParam === 'right' ? bias : 0;
|
|
1774
3523
|
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
|
-
}
|
|
1790
3524
|
const commonCollisionProps = {
|
|
1791
3525
|
boundary: collisionBoundary === 'clipping-ancestors' ? 'clippingAncestors' : collisionBoundary,
|
|
1792
3526
|
padding: collisionPadding
|
|
@@ -1823,46 +3557,37 @@ function useAnchorPositioning(params) {
|
|
|
1823
3557
|
// Ensure the popup flips if it's been limited by its --available-height and it resizes.
|
|
1824
3558
|
// Since the size() padding is smaller than the flip() padding, flip() will take precedence.
|
|
1825
3559
|
padding: {
|
|
1826
|
-
top: collisionPadding.top + bias,
|
|
1827
|
-
right: collisionPadding.right + bias,
|
|
1828
|
-
bottom: collisionPadding.bottom + bias,
|
|
1829
|
-
left: collisionPadding.left + bias
|
|
3560
|
+
top: collisionPadding.top + bias + biasTop,
|
|
3561
|
+
right: collisionPadding.right + bias + biasRight,
|
|
3562
|
+
bottom: collisionPadding.bottom + bias + biasBottom,
|
|
3563
|
+
left: collisionPadding.left + bias + biasLeft
|
|
1830
3564
|
},
|
|
1831
3565
|
mainAxis: !shiftCrossAxis && collisionAvoidanceSide === 'flip',
|
|
1832
3566
|
crossAxis: collisionAvoidanceAlign === 'flip' ? 'alignment' : false,
|
|
1833
3567
|
fallbackAxisSideDirection: collisionAvoidanceFallbackAxisSide
|
|
1834
3568
|
});
|
|
1835
|
-
const shiftMiddleware = shiftDisabled ? null : shift(
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
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]);
|
|
3569
|
+
const shiftMiddleware = shiftDisabled ? null : shift({
|
|
3570
|
+
...commonCollisionProps,
|
|
3571
|
+
// Use the Layout Viewport to avoid shifting around when pinch-zooming.
|
|
3572
|
+
rootBoundary: shiftRootBoundary,
|
|
3573
|
+
mainAxis: collisionAvoidanceAlign !== 'none',
|
|
3574
|
+
crossAxis: crossAxisShiftEnabled,
|
|
3575
|
+
limiter: sticky || shiftCrossAxis ? undefined : limitShift(limitData => {
|
|
3576
|
+
if (!arrowRef.current) {
|
|
3577
|
+
return {};
|
|
3578
|
+
}
|
|
3579
|
+
const {
|
|
3580
|
+
width,
|
|
3581
|
+
height
|
|
3582
|
+
} = arrowRef.current.getBoundingClientRect();
|
|
3583
|
+
const sideAxis = getSideAxis(getSide(limitData.placement));
|
|
3584
|
+
const arrowSize = sideAxis === 'y' ? width : height;
|
|
3585
|
+
const offsetAmount = sideAxis === 'y' ? collisionPadding.left + collisionPadding.right : collisionPadding.top + collisionPadding.bottom;
|
|
3586
|
+
return {
|
|
3587
|
+
offset: arrowSize / 2 + offsetAmount / 2
|
|
3588
|
+
};
|
|
3589
|
+
})
|
|
3590
|
+
}, [commonCollisionProps, sticky, shiftCrossAxis, shiftRootBoundary, collisionPadding, collisionAvoidanceAlign]);
|
|
1866
3591
|
|
|
1867
3592
|
// https://floating-ui.com/docs/flip#combining-with-shift
|
|
1868
3593
|
if (collisionAvoidanceSide === 'shift' || collisionAvoidanceAlign === 'shift' || align === 'center') {
|
|
@@ -1884,8 +3609,8 @@ function useAnchorPositioning(params) {
|
|
|
1884
3609
|
return;
|
|
1885
3610
|
}
|
|
1886
3611
|
const floatingStyle = floating.style;
|
|
1887
|
-
floatingStyle.setProperty(
|
|
1888
|
-
floatingStyle.setProperty(
|
|
3612
|
+
floatingStyle.setProperty(AVAILABLE_WIDTH_VAR, `${availableWidth}px`);
|
|
3613
|
+
floatingStyle.setProperty(AVAILABLE_HEIGHT_VAR, `${availableHeight}px`);
|
|
1889
3614
|
|
|
1890
3615
|
// Snap anchor dimensions to device pixels to ensure the popup's visual width matches the anchor's one.
|
|
1891
3616
|
const dpr = getWindow(floating).devicePixelRatio || 1;
|
|
@@ -1967,7 +3692,7 @@ function useAnchorPositioning(params) {
|
|
|
1967
3692
|
context,
|
|
1968
3693
|
isPositioned,
|
|
1969
3694
|
floatingStyles: originalFloatingStyles
|
|
1970
|
-
} =
|
|
3695
|
+
} = useFloatingHook({
|
|
1971
3696
|
rootContext: floatingRootContext,
|
|
1972
3697
|
open: keepMounted ? mounted : undefined,
|
|
1973
3698
|
placement,
|
|
@@ -1986,14 +3711,41 @@ function useAnchorPositioning(params) {
|
|
|
1986
3711
|
// This ensures the popup is inside the viewport initially before it gets positioned.
|
|
1987
3712
|
const resolvedPosition = isPositioned ? positionMethod : 'fixed';
|
|
1988
3713
|
const floatingStyles = React.useMemo(() => {
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
3714
|
+
let base;
|
|
3715
|
+
if (!isPositioned) {
|
|
3716
|
+
// Until a position for the current open is computed, ignore any coordinates retained from a
|
|
3717
|
+
// previous open (or from a pass that measured the hidden popup as 0x0). Rendering the
|
|
3718
|
+
// full-size popup at such stale coordinates can overflow the layout viewport, which makes
|
|
3719
|
+
// mobile Chrome zoom the page out and reflow everything the popup is anchored to.
|
|
3720
|
+
base = {
|
|
3721
|
+
position: resolvedPosition,
|
|
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';
|
|
1997
3749
|
if (!isPositioned) {
|
|
1998
3750
|
base.opacity = 0;
|
|
1999
3751
|
}
|
|
@@ -2044,10 +3796,10 @@ function useAnchorPositioning(params) {
|
|
|
2044
3796
|
// and flips back lazily, not eagerly. Ideal for filtered lists that change
|
|
2045
3797
|
// the size of the popup dynamically to avoid unwanted flipping when typing.
|
|
2046
3798
|
useIsoLayoutEffect(() => {
|
|
2047
|
-
if (lazyFlip && mounted && isPositioned) {
|
|
3799
|
+
if (lazyFlip && mounted && isPositioned && renderedSide !== side) {
|
|
2048
3800
|
setMountSide(renderedSide);
|
|
2049
3801
|
}
|
|
2050
|
-
}, [lazyFlip, mounted, isPositioned, renderedSide]);
|
|
3802
|
+
}, [lazyFlip, mounted, isPositioned, renderedSide, side]);
|
|
2051
3803
|
const arrowStyles = React.useMemo(() => ({
|
|
2052
3804
|
position: 'absolute',
|
|
2053
3805
|
top: middlewareData.arrow?.y,
|
|
@@ -2132,64 +3884,57 @@ function useAnchoredPopupScrollLock(enabled, touchOpen, positionerElement, refer
|
|
|
2132
3884
|
useScrollLock(enabled && (!touchOpen || touchOpenShouldLockScroll), referenceElement);
|
|
2133
3885
|
}
|
|
2134
3886
|
|
|
2135
|
-
let IndexGuessBehavior = /*#__PURE__*/function (IndexGuessBehavior) {
|
|
2136
|
-
IndexGuessBehavior[IndexGuessBehavior["None"] = 0] = "None";
|
|
2137
|
-
IndexGuessBehavior[IndexGuessBehavior["GuessFromOrder"] = 1] = "GuessFromOrder";
|
|
2138
|
-
return IndexGuessBehavior;
|
|
2139
|
-
}({});
|
|
2140
|
-
|
|
2141
3887
|
/**
|
|
2142
3888
|
* Used to register a list item and its index (DOM position) in the `CompositeList`.
|
|
2143
3889
|
*/
|
|
2144
3890
|
function useCompositeListItem(params = {}) {
|
|
2145
3891
|
const {
|
|
3892
|
+
guess,
|
|
2146
3893
|
label,
|
|
2147
3894
|
metadata,
|
|
2148
3895
|
textRef,
|
|
2149
|
-
indexGuessBehavior,
|
|
2150
3896
|
index: externalIndex
|
|
2151
3897
|
} = params;
|
|
2152
3898
|
const {
|
|
2153
3899
|
register,
|
|
2154
3900
|
unregister,
|
|
2155
3901
|
subscribeMapChange,
|
|
2156
|
-
elementsRef,
|
|
2157
|
-
labelsRef,
|
|
2158
3902
|
nextIndexRef
|
|
2159
3903
|
} = 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.
|
|
2160
3908
|
const indexRef = React.useRef(-1);
|
|
2161
|
-
const [
|
|
3909
|
+
const [internalIndex, setInternalIndex] = React.useState(externalIndex == null && guess ? () => {
|
|
2162
3910
|
if (indexRef.current === -1) {
|
|
2163
3911
|
const newIndex = nextIndexRef.current;
|
|
2164
3912
|
nextIndexRef.current += 1;
|
|
2165
3913
|
indexRef.current = newIndex;
|
|
2166
3914
|
}
|
|
2167
3915
|
return indexRef.current;
|
|
2168
|
-
} : -1)
|
|
3916
|
+
} : -1);
|
|
3917
|
+
const index = externalIndex ?? internalIndex;
|
|
2169
3918
|
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.
|
|
2170
3923
|
const ref = React.useCallback(node => {
|
|
2171
|
-
componentRef.current
|
|
2172
|
-
if (
|
|
2173
|
-
|
|
2174
|
-
if (labelsRef) {
|
|
2175
|
-
const isLabelDefined = label !== undefined;
|
|
2176
|
-
labelsRef.current[index] = isLabelDefined ? label : textRef?.current?.textContent ?? node.textContent;
|
|
2177
|
-
}
|
|
3924
|
+
const previousNode = componentRef.current;
|
|
3925
|
+
if (previousNode) {
|
|
3926
|
+
unregister(previousNode);
|
|
2178
3927
|
}
|
|
2179
|
-
|
|
2180
|
-
useIsoLayoutEffect(() => {
|
|
2181
|
-
if (externalIndex != null) {
|
|
2182
|
-
return undefined;
|
|
2183
|
-
}
|
|
2184
|
-
const node = componentRef.current;
|
|
3928
|
+
componentRef.current = node;
|
|
2185
3929
|
if (node) {
|
|
2186
|
-
register(node,
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
3930
|
+
register(node, {
|
|
3931
|
+
metadata: metadata ?? null,
|
|
3932
|
+
index: externalIndex ?? null,
|
|
3933
|
+
label,
|
|
3934
|
+
textRef
|
|
3935
|
+
});
|
|
2190
3936
|
}
|
|
2191
|
-
|
|
2192
|
-
}, [externalIndex, register, unregister, metadata]);
|
|
3937
|
+
}, [externalIndex, register, unregister, metadata, label, textRef]);
|
|
2193
3938
|
useIsoLayoutEffect(() => {
|
|
2194
3939
|
if (externalIndex != null) {
|
|
2195
3940
|
return undefined;
|
|
@@ -2197,14 +3942,14 @@ function useCompositeListItem(params = {}) {
|
|
|
2197
3942
|
return subscribeMapChange(map => {
|
|
2198
3943
|
const i = componentRef.current ? map.get(componentRef.current)?.index : null;
|
|
2199
3944
|
if (i != null) {
|
|
2200
|
-
|
|
3945
|
+
setInternalIndex(i);
|
|
2201
3946
|
}
|
|
2202
3947
|
});
|
|
2203
|
-
}, [externalIndex, subscribeMapChange
|
|
3948
|
+
}, [externalIndex, subscribeMapChange]);
|
|
2204
3949
|
return {
|
|
2205
3950
|
ref,
|
|
2206
3951
|
index
|
|
2207
3952
|
};
|
|
2208
3953
|
}
|
|
2209
3954
|
|
|
2210
|
-
export {
|
|
3955
|
+
export { useCompositeListItem as A, removeItem as B, CompositeList as C, DEFAULT_VALIDITY_STATE as D, isGroupedItems as E, FieldRootContext as F, findSelectionIndex as G, selectedValueIncludes as H, DEFAULT_FIELD_ROOT_CONTEXT as I, DEFAULT_FIELD_STATE_ATTRIBUTES as J, getDefaultLabelId as K, LabelableContext as L, DEFAULT_SIDES as M, 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, useOnFirstRender as l, defaultItemEquality as m, stringifyAsLabel as n, areArraysEqual as o, isMouseWithinBounds as p, resolveMultipleLabels as q, resolveAriaLabelledBy as r, stringifyAsValue as s, resolveSelectedLabel as t, useLabelableContext as u, useAnchoredPopupScrollLock as v, useAnchorPositioning as w, usePositioner as x, platform as y, getDisabledMountTransitionStyles as z };
|