@react-aria/overlays 3.13.0 → 3.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/import.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import $k7QOs$react, {useState as $k7QOs$useState, useCallback as $k7QOs$useCallback, useRef as $k7QOs$useRef, useEffect as $k7QOs$useEffect, useContext as $k7QOs$useContext, useMemo as $k7QOs$useMemo} from "react";
2
- import {useLayoutEffect as $k7QOs$useLayoutEffect, useResizeObserver as $k7QOs$useResizeObserver, useId as $k7QOs$useId, isIOS as $k7QOs$isIOS, chain as $k7QOs$chain, getScrollParent as $k7QOs$getScrollParent, useLabels as $k7QOs$useLabels, mergeProps as $k7QOs$mergeProps} from "@react-aria/utils";
2
+ import {useLayoutEffect as $k7QOs$useLayoutEffect, useResizeObserver as $k7QOs$useResizeObserver, clamp as $k7QOs$clamp, useId as $k7QOs$useId, isIOS as $k7QOs$isIOS, chain as $k7QOs$chain, getScrollParent as $k7QOs$getScrollParent, useLabels as $k7QOs$useLabels, mergeProps as $k7QOs$mergeProps} from "@react-aria/utils";
3
3
  import {useLocale as $k7QOs$useLocale, useLocalizedStringFormatter as $k7QOs$useLocalizedStringFormatter} from "@react-aria/i18n";
4
4
  import {isElementInChildOfActiveScope as $k7QOs$isElementInChildOfActiveScope, FocusScope as $k7QOs$FocusScope} from "@react-aria/focus";
5
5
  import {useInteractOutside as $k7QOs$useInteractOutside, useFocusWithin as $k7QOs$useFocusWithin} from "@react-aria/interactions";
@@ -40,7 +40,8 @@ function $parcel$interopDefault(a) {
40
40
  * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
41
41
  * OF ANY KIND, either express or implied. See the License for the specific language
42
42
  * governing permissions and limitations under the License.
43
- */ const $edcf132a9284368a$var$AXIS = {
43
+ */
44
+ const $edcf132a9284368a$var$AXIS = {
44
45
  top: "top",
45
46
  bottom: "top",
46
47
  left: "left",
@@ -60,28 +61,38 @@ const $edcf132a9284368a$var$AXIS_SIZE = {
60
61
  top: "height",
61
62
  left: "width"
62
63
  };
64
+ const $edcf132a9284368a$var$TOTAL_SIZE = {
65
+ width: "totalWidth",
66
+ height: "totalHeight"
67
+ };
63
68
  const $edcf132a9284368a$var$PARSED_PLACEMENT_CACHE = {};
64
69
  // @ts-ignore
65
70
  let $edcf132a9284368a$var$visualViewport = typeof window !== "undefined" && window.visualViewport;
66
71
  function $edcf132a9284368a$var$getContainerDimensions(containerNode) {
67
- let width = 0, height = 0, top = 0, left = 0;
72
+ let width = 0, height = 0, totalWidth = 0, totalHeight = 0, top = 0, left = 0;
68
73
  let scroll = {};
69
74
  if (containerNode.tagName === "BODY") {
70
75
  let documentElement = document.documentElement;
76
+ totalWidth = documentElement.clientWidth;
77
+ totalHeight = documentElement.clientHeight;
71
78
  var _visualViewport_width;
72
- width = (_visualViewport_width = $edcf132a9284368a$var$visualViewport === null || $edcf132a9284368a$var$visualViewport === void 0 ? void 0 : $edcf132a9284368a$var$visualViewport.width) !== null && _visualViewport_width !== void 0 ? _visualViewport_width : documentElement.clientWidth;
79
+ width = (_visualViewport_width = $edcf132a9284368a$var$visualViewport === null || $edcf132a9284368a$var$visualViewport === void 0 ? void 0 : $edcf132a9284368a$var$visualViewport.width) !== null && _visualViewport_width !== void 0 ? _visualViewport_width : totalWidth;
73
80
  var _visualViewport_height;
74
- height = (_visualViewport_height = $edcf132a9284368a$var$visualViewport === null || $edcf132a9284368a$var$visualViewport === void 0 ? void 0 : $edcf132a9284368a$var$visualViewport.height) !== null && _visualViewport_height !== void 0 ? _visualViewport_height : documentElement.clientHeight;
81
+ height = (_visualViewport_height = $edcf132a9284368a$var$visualViewport === null || $edcf132a9284368a$var$visualViewport === void 0 ? void 0 : $edcf132a9284368a$var$visualViewport.height) !== null && _visualViewport_height !== void 0 ? _visualViewport_height : totalHeight;
75
82
  scroll.top = documentElement.scrollTop || containerNode.scrollTop;
76
83
  scroll.left = documentElement.scrollLeft || containerNode.scrollLeft;
77
84
  } else {
78
85
  ({ width: width , height: height , top: top , left: left } = $edcf132a9284368a$var$getOffset(containerNode));
79
86
  scroll.top = containerNode.scrollTop;
80
87
  scroll.left = containerNode.scrollLeft;
88
+ totalWidth = width;
89
+ totalHeight = height;
81
90
  }
82
91
  return {
83
92
  width: width,
84
93
  height: height,
94
+ totalWidth: totalWidth,
95
+ totalHeight: totalHeight,
85
96
  scroll: scroll,
86
97
  top: top,
87
98
  left: left
@@ -131,7 +142,7 @@ function $edcf132a9284368a$var$parsePlacement(input) {
131
142
  };
132
143
  return $edcf132a9284368a$var$PARSED_PLACEMENT_CACHE[input];
133
144
  }
134
- function $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned) {
145
+ function $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned, arrowSize, arrowBoundaryOffset) {
135
146
  let { placement: placement , crossPlacement: crossPlacement , axis: axis , crossAxis: crossAxis , size: size , crossSize: crossSize } = placementInfo;
136
147
  let position = {};
137
148
  // button position
@@ -147,19 +158,18 @@ function $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions,
147
158
  } */
148
159
  // add the crossOffset from props
149
160
  position[crossAxis] += crossOffset;
150
- // this is button center position - the overlay size + half of the button to align bottom of overlay with button center
151
- let minViablePosition = childOffset[crossAxis] + childOffset[crossSize] / 2 - overlaySize[crossSize];
152
- // this is button position of center, aligns top of overlay with button center
153
- let maxViablePosition = childOffset[crossAxis] + childOffset[crossSize] / 2;
154
- // clamp it into the range of the min/max positions
155
- position[crossAxis] = Math.min(Math.max(minViablePosition, position[crossAxis]), maxViablePosition);
161
+ // overlay top overlapping arrow with button bottom
162
+ const minPosition = childOffset[crossAxis] - overlaySize[crossSize] + arrowSize + arrowBoundaryOffset;
163
+ // overlay bottom overlapping arrow with button top
164
+ const maxPosition = childOffset[crossAxis] + childOffset[crossSize] - arrowSize - arrowBoundaryOffset;
165
+ position[crossAxis] = (0, $k7QOs$clamp)(position[crossAxis], minPosition, maxPosition);
156
166
  // Floor these so the position isn't placed on a partial pixel, only whole pixels. Shouldn't matter if it was floored or ceiled, so chose one.
157
167
  if (placement === axis) {
158
168
  // If the container is positioned (non-static), then we use the container's actual
159
169
  // height, as `bottom` will be relative to this height. But if the container is static,
160
170
  // then it can only be the `document.body`, and `bottom` will be relative to _its_
161
171
  // container, which should be as large as boundaryDimensions.
162
- const containerHeight = isContainerPositioned ? containerOffsetWithBoundary[size] : boundaryDimensions[size];
172
+ const containerHeight = isContainerPositioned ? containerOffsetWithBoundary[size] : boundaryDimensions[$edcf132a9284368a$var$TOTAL_SIZE[size]];
163
173
  position[$edcf132a9284368a$var$FLIPPED_DIRECTION[axis]] = Math.floor(containerHeight - childOffset[axis] + offset);
164
174
  } else position[axis] = Math.floor(childOffset[axis] + childOffset[size] + offset);
165
175
  return position;
@@ -178,16 +188,16 @@ function $edcf132a9284368a$var$getAvailableSpace(boundaryDimensions, containerOf
178
188
  if (placement === axis) return Math.max(0, childOffset[axis] - boundaryDimensions[axis] - boundaryDimensions.scroll[axis] + containerOffsetWithBoundary[axis] - margins[axis] - margins[$edcf132a9284368a$var$FLIPPED_DIRECTION[axis]] - padding);
179
189
  return Math.max(0, boundaryDimensions[size] + boundaryDimensions[axis] + boundaryDimensions.scroll[axis] - containerOffsetWithBoundary[axis] - childOffset[axis] - childOffset[size] - margins[axis] - margins[$edcf132a9284368a$var$FLIPPED_DIRECTION[axis]] - padding);
180
190
  }
181
- function $edcf132a9284368a$export$6839422d1f33cee9(placementInput, childOffset, overlaySize, scrollSize, margins, padding, flip, boundaryDimensions, containerOffsetWithBoundary, offset, crossOffset, isContainerPositioned, userSetMaxHeight) {
191
+ function $edcf132a9284368a$export$6839422d1f33cee9(placementInput, childOffset, overlaySize, scrollSize, margins, padding, flip, boundaryDimensions, containerOffsetWithBoundary, offset, crossOffset, isContainerPositioned, userSetMaxHeight, arrowSize, arrowBoundaryOffset) {
182
192
  let placementInfo = $edcf132a9284368a$var$parsePlacement(placementInput);
183
193
  let { size: size , crossAxis: crossAxis , crossSize: crossSize , placement: placement , crossPlacement: crossPlacement } = placementInfo;
184
- let position = $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned);
194
+ let position = $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned, arrowSize, arrowBoundaryOffset);
185
195
  let normalizedOffset = offset;
186
196
  let space = $edcf132a9284368a$var$getAvailableSpace(boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding + offset, placementInfo);
187
197
  // Check if the scroll size of the overlay is greater than the available space to determine if we need to flip
188
198
  if (flip && scrollSize[size] > space) {
189
199
  let flippedPlacementInfo = $edcf132a9284368a$var$parsePlacement(`${$edcf132a9284368a$var$FLIPPED_DIRECTION[placement]} ${crossPlacement}`);
190
- let flippedPosition = $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions, overlaySize, flippedPlacementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned);
200
+ let flippedPosition = $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions, overlaySize, flippedPlacementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned, arrowSize, arrowBoundaryOffset);
191
201
  let flippedSpace = $edcf132a9284368a$var$getAvailableSpace(boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding + offset, flippedPlacementInfo);
192
202
  // If the available space for the flipped position is greater than the original available space, flip.
193
203
  if (flippedSpace > space) {
@@ -201,11 +211,22 @@ function $edcf132a9284368a$export$6839422d1f33cee9(placementInput, childOffset,
201
211
  let maxHeight = $edcf132a9284368a$var$getMaxHeight(position, boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding);
202
212
  if (userSetMaxHeight && userSetMaxHeight < maxHeight) maxHeight = userSetMaxHeight;
203
213
  overlaySize.height = Math.min(overlaySize.height, maxHeight);
204
- position = $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, normalizedOffset, crossOffset, containerOffsetWithBoundary, isContainerPositioned);
214
+ position = $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, normalizedOffset, crossOffset, containerOffsetWithBoundary, isContainerPositioned, arrowSize, arrowBoundaryOffset);
205
215
  delta = $edcf132a9284368a$var$getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, padding);
206
216
  position[crossAxis] += delta;
207
217
  let arrowPosition = {};
208
- arrowPosition[crossAxis] = childOffset[crossAxis] - position[crossAxis] + childOffset[crossSize] / 2;
218
+ // All values are transformed so that 0 is at the top/left of the overlay depending on the orientation
219
+ // Prefer the arrow being in the center of the trigger/overlay anchor element
220
+ let preferredArrowPosition = childOffset[crossAxis] + .5 * childOffset[crossSize] - overlaySize[crossAxis];
221
+ // Min/Max position limits for the arrow with respect to the overlay
222
+ const arrowMinPosition = arrowSize / 2 + arrowBoundaryOffset;
223
+ const arrowMaxPosition = overlaySize[crossSize] - arrowSize / 2 - arrowBoundaryOffset;
224
+ // Min/Max position limits for the arrow with respect to the trigger/overlay anchor element
225
+ const arrowOverlappingChildMinEdge = childOffset[crossAxis] - overlaySize[crossAxis] + arrowSize / 2;
226
+ const arrowOverlappingChildMaxEdge = childOffset[crossAxis] + childOffset[crossSize] - overlaySize[crossAxis] - arrowSize / 2;
227
+ // Clamp the arrow positioning so that it always is within the bounds of the anchor and the overlay
228
+ const arrowPositionOverlappingChild = (0, $k7QOs$clamp)(preferredArrowPosition, arrowOverlappingChildMinEdge, arrowOverlappingChildMaxEdge);
229
+ arrowPosition[crossAxis] = (0, $k7QOs$clamp)(arrowPositionOverlappingChild, arrowMinPosition, arrowMaxPosition);
209
230
  return {
210
231
  position: position,
211
232
  maxHeight: maxHeight,
@@ -215,13 +236,13 @@ function $edcf132a9284368a$export$6839422d1f33cee9(placementInput, childOffset,
215
236
  };
216
237
  }
217
238
  function $edcf132a9284368a$export$b3ceb0cbf1056d98(opts) {
218
- let { placement: placement , targetNode: targetNode , overlayNode: overlayNode , scrollNode: scrollNode , padding: padding , shouldFlip: shouldFlip , boundaryElement: boundaryElement , offset: offset , crossOffset: crossOffset , maxHeight: maxHeight } = opts;
219
- let container = overlayNode instanceof HTMLElement && overlayNode.offsetParent || document.body;
220
- let isBodyContainer = container.tagName === "BODY";
239
+ let { placement: placement , targetNode: targetNode , overlayNode: overlayNode , scrollNode: scrollNode , padding: padding , shouldFlip: shouldFlip , boundaryElement: boundaryElement , offset: offset , crossOffset: crossOffset , maxHeight: maxHeight , arrowSize: arrowSize , arrowBoundaryOffset: arrowBoundaryOffset = 0 } = opts;
240
+ let container = overlayNode instanceof HTMLElement ? $edcf132a9284368a$var$getContainingBlock(overlayNode) : document.documentElement;
241
+ let isViewportContainer = container === document.documentElement;
221
242
  const containerPositionStyle = window.getComputedStyle(container).position;
222
243
  let isContainerPositioned = !!containerPositionStyle && containerPositionStyle !== "static";
223
- let childOffset = isBodyContainer ? $edcf132a9284368a$var$getOffset(targetNode) : $edcf132a9284368a$var$getPosition(targetNode, container);
224
- if (!isBodyContainer) {
244
+ let childOffset = isViewportContainer ? $edcf132a9284368a$var$getOffset(targetNode) : $edcf132a9284368a$var$getPosition(targetNode, container);
245
+ if (!isViewportContainer) {
225
246
  let { marginTop: marginTop , marginLeft: marginLeft } = window.getComputedStyle(targetNode);
226
247
  childOffset.top += parseInt(marginTop, 10) || 0;
227
248
  childOffset.left += parseInt(marginLeft, 10) || 0;
@@ -233,7 +254,7 @@ function $edcf132a9284368a$export$b3ceb0cbf1056d98(opts) {
233
254
  let scrollSize = $edcf132a9284368a$var$getScroll(scrollNode);
234
255
  let boundaryDimensions = $edcf132a9284368a$var$getContainerDimensions(boundaryElement);
235
256
  let containerOffsetWithBoundary = boundaryElement.tagName === "BODY" ? $edcf132a9284368a$var$getOffset(container) : $edcf132a9284368a$var$getPosition(container, boundaryElement);
236
- return $edcf132a9284368a$export$6839422d1f33cee9(placement, childOffset, overlaySize, scrollSize, margins, padding, shouldFlip, boundaryDimensions, containerOffsetWithBoundary, offset, crossOffset, isContainerPositioned, maxHeight);
257
+ return $edcf132a9284368a$export$6839422d1f33cee9(placement, childOffset, overlaySize, scrollSize, margins, padding, shouldFlip, boundaryDimensions, containerOffsetWithBoundary, offset, crossOffset, isContainerPositioned, maxHeight, arrowSize, arrowBoundaryOffset);
237
258
  }
238
259
  function $edcf132a9284368a$var$getOffset(node) {
239
260
  let { top: top , left: left , width: width , height: height } = node.getBoundingClientRect();
@@ -269,6 +290,35 @@ function $edcf132a9284368a$var$getPosition(node, parent) {
269
290
  offset.left -= parseInt(style.marginLeft, 10) || 0;
270
291
  return offset;
271
292
  }
293
+ // Returns the containing block of an element, which is the element that
294
+ // this element will be positioned relative to.
295
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block
296
+ function $edcf132a9284368a$var$getContainingBlock(node) {
297
+ // The offsetParent of an element in most cases equals the containing block.
298
+ // https://w3c.github.io/csswg-drafts/cssom-view/#dom-htmlelement-offsetparent
299
+ let offsetParent = node.offsetParent;
300
+ // The offsetParent algorithm terminates at the document body,
301
+ // even if the body is not a containing block. Double check that
302
+ // and use the documentElement if so.
303
+ if (offsetParent && offsetParent === document.body && window.getComputedStyle(offsetParent).position === "static" && !$edcf132a9284368a$var$isContainingBlock(offsetParent)) offsetParent = document.documentElement;
304
+ // TODO(later): handle table elements?
305
+ // The offsetParent can be null if the element has position: fixed, or a few other cases.
306
+ // We have to walk up the tree manually in this case because fixed positioned elements
307
+ // are still positioned relative to their containing block, which is not always the viewport.
308
+ if (offsetParent == null) {
309
+ offsetParent = node.parentElement;
310
+ while(offsetParent && !$edcf132a9284368a$var$isContainingBlock(offsetParent))offsetParent = offsetParent.parentElement;
311
+ }
312
+ // Fall back to the viewport.
313
+ return offsetParent || document.documentElement;
314
+ }
315
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
316
+ function $edcf132a9284368a$var$isContainingBlock(node) {
317
+ let style = window.getComputedStyle(node);
318
+ return style.transform !== "none" || /transform|perspective/.test(style.willChange) || style.filter !== "none" || style.contain === "paint" || // @ts-ignore
319
+ "backdropFilter" in style && style.backdropFilter !== "none" || // @ts-ignore
320
+ "WebkitBackdropFilter" in style && style.WebkitBackdropFilter !== "none";
321
+ }
272
322
 
273
323
 
274
324
 
@@ -314,7 +364,7 @@ function $dd149f63282afbbf$export$18fc8428861184da(opts) {
314
364
  let $2a41e45df1593e64$var$visualViewport = typeof window !== "undefined" && window.visualViewport;
315
365
  function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
316
366
  let { direction: direction } = (0, $k7QOs$useLocale)();
317
- let { targetRef: targetRef , overlayRef: overlayRef , scrollRef: scrollRef = overlayRef , placement: placement = "bottom" , containerPadding: containerPadding = 12 , shouldFlip: shouldFlip = true , boundaryElement: boundaryElement = typeof document !== "undefined" ? document.body : null , offset: offset = 0 , crossOffset: crossOffset = 0 , shouldUpdatePosition: shouldUpdatePosition = true , isOpen: isOpen = true , onClose: onClose , maxHeight: maxHeight } = props;
367
+ let { arrowSize: arrowSize = 0 , targetRef: targetRef , overlayRef: overlayRef , scrollRef: scrollRef = overlayRef , placement: placement = "bottom" , containerPadding: containerPadding = 12 , shouldFlip: shouldFlip = true , boundaryElement: boundaryElement = typeof document !== "undefined" ? document.body : null , offset: offset = 0 , crossOffset: crossOffset = 0 , shouldUpdatePosition: shouldUpdatePosition = true , isOpen: isOpen = true , onClose: onClose , maxHeight: maxHeight , arrowBoundaryOffset: arrowBoundaryOffset = 0 } = props;
318
368
  let [position, setPosition] = (0, $k7QOs$useState)({
319
369
  position: {},
320
370
  arrowOffsetLeft: undefined,
@@ -335,7 +385,9 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
335
385
  crossOffset,
336
386
  isOpen,
337
387
  direction,
338
- maxHeight
388
+ maxHeight,
389
+ arrowBoundaryOffset,
390
+ arrowSize
339
391
  ];
340
392
  let updatePosition = (0, $k7QOs$useCallback)(()=>{
341
393
  if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !scrollRef.current || !boundaryElement) return;
@@ -349,7 +401,9 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
349
401
  boundaryElement: boundaryElement,
350
402
  offset: offset,
351
403
  crossOffset: crossOffset,
352
- maxHeight: maxHeight
404
+ maxHeight: maxHeight,
405
+ arrowSize: arrowSize,
406
+ arrowBoundaryOffset: arrowBoundaryOffset
353
407
  });
354
408
  // Modify overlay styles directly so positioning happens immediately without the need of a second render
355
409
  // This is so we don't have to delay autoFocus scrolling or delay applying preventScroll for popovers
@@ -383,8 +437,10 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
383
437
  updatePosition();
384
438
  };
385
439
  $2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.addEventListener("resize", onResize);
440
+ $2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.addEventListener("scroll", onResize);
386
441
  return ()=>{
387
442
  $2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.removeEventListener("resize", onResize);
443
+ $2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.removeEventListener("scroll", onResize);
388
444
  };
389
445
  }, [
390
446
  updatePosition
package/dist/main.js CHANGED
@@ -59,7 +59,8 @@ $parcel$export(module.exports, "useOverlayFocusContain", () => $745edbb83ab4296f
59
59
  * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
60
60
  * OF ANY KIND, either express or implied. See the License for the specific language
61
61
  * governing permissions and limitations under the License.
62
- */ const $5935ba4d7da2c103$var$AXIS = {
62
+ */
63
+ const $5935ba4d7da2c103$var$AXIS = {
63
64
  top: "top",
64
65
  bottom: "top",
65
66
  left: "left",
@@ -79,28 +80,38 @@ const $5935ba4d7da2c103$var$AXIS_SIZE = {
79
80
  top: "height",
80
81
  left: "width"
81
82
  };
83
+ const $5935ba4d7da2c103$var$TOTAL_SIZE = {
84
+ width: "totalWidth",
85
+ height: "totalHeight"
86
+ };
82
87
  const $5935ba4d7da2c103$var$PARSED_PLACEMENT_CACHE = {};
83
88
  // @ts-ignore
84
89
  let $5935ba4d7da2c103$var$visualViewport = typeof window !== "undefined" && window.visualViewport;
85
90
  function $5935ba4d7da2c103$var$getContainerDimensions(containerNode) {
86
- let width = 0, height = 0, top = 0, left = 0;
91
+ let width = 0, height = 0, totalWidth = 0, totalHeight = 0, top = 0, left = 0;
87
92
  let scroll = {};
88
93
  if (containerNode.tagName === "BODY") {
89
94
  let documentElement = document.documentElement;
95
+ totalWidth = documentElement.clientWidth;
96
+ totalHeight = documentElement.clientHeight;
90
97
  var _visualViewport_width;
91
- width = (_visualViewport_width = $5935ba4d7da2c103$var$visualViewport === null || $5935ba4d7da2c103$var$visualViewport === void 0 ? void 0 : $5935ba4d7da2c103$var$visualViewport.width) !== null && _visualViewport_width !== void 0 ? _visualViewport_width : documentElement.clientWidth;
98
+ width = (_visualViewport_width = $5935ba4d7da2c103$var$visualViewport === null || $5935ba4d7da2c103$var$visualViewport === void 0 ? void 0 : $5935ba4d7da2c103$var$visualViewport.width) !== null && _visualViewport_width !== void 0 ? _visualViewport_width : totalWidth;
92
99
  var _visualViewport_height;
93
- height = (_visualViewport_height = $5935ba4d7da2c103$var$visualViewport === null || $5935ba4d7da2c103$var$visualViewport === void 0 ? void 0 : $5935ba4d7da2c103$var$visualViewport.height) !== null && _visualViewport_height !== void 0 ? _visualViewport_height : documentElement.clientHeight;
100
+ height = (_visualViewport_height = $5935ba4d7da2c103$var$visualViewport === null || $5935ba4d7da2c103$var$visualViewport === void 0 ? void 0 : $5935ba4d7da2c103$var$visualViewport.height) !== null && _visualViewport_height !== void 0 ? _visualViewport_height : totalHeight;
94
101
  scroll.top = documentElement.scrollTop || containerNode.scrollTop;
95
102
  scroll.left = documentElement.scrollLeft || containerNode.scrollLeft;
96
103
  } else {
97
104
  ({ width: width , height: height , top: top , left: left } = $5935ba4d7da2c103$var$getOffset(containerNode));
98
105
  scroll.top = containerNode.scrollTop;
99
106
  scroll.left = containerNode.scrollLeft;
107
+ totalWidth = width;
108
+ totalHeight = height;
100
109
  }
101
110
  return {
102
111
  width: width,
103
112
  height: height,
113
+ totalWidth: totalWidth,
114
+ totalHeight: totalHeight,
104
115
  scroll: scroll,
105
116
  top: top,
106
117
  left: left
@@ -150,7 +161,7 @@ function $5935ba4d7da2c103$var$parsePlacement(input) {
150
161
  };
151
162
  return $5935ba4d7da2c103$var$PARSED_PLACEMENT_CACHE[input];
152
163
  }
153
- function $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned) {
164
+ function $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned, arrowSize, arrowBoundaryOffset) {
154
165
  let { placement: placement , crossPlacement: crossPlacement , axis: axis , crossAxis: crossAxis , size: size , crossSize: crossSize } = placementInfo;
155
166
  let position = {};
156
167
  // button position
@@ -166,19 +177,18 @@ function $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions,
166
177
  } */
167
178
  // add the crossOffset from props
168
179
  position[crossAxis] += crossOffset;
169
- // this is button center position - the overlay size + half of the button to align bottom of overlay with button center
170
- let minViablePosition = childOffset[crossAxis] + childOffset[crossSize] / 2 - overlaySize[crossSize];
171
- // this is button position of center, aligns top of overlay with button center
172
- let maxViablePosition = childOffset[crossAxis] + childOffset[crossSize] / 2;
173
- // clamp it into the range of the min/max positions
174
- position[crossAxis] = Math.min(Math.max(minViablePosition, position[crossAxis]), maxViablePosition);
180
+ // overlay top overlapping arrow with button bottom
181
+ const minPosition = childOffset[crossAxis] - overlaySize[crossSize] + arrowSize + arrowBoundaryOffset;
182
+ // overlay bottom overlapping arrow with button top
183
+ const maxPosition = childOffset[crossAxis] + childOffset[crossSize] - arrowSize - arrowBoundaryOffset;
184
+ position[crossAxis] = (0, $6Zb2x$reactariautils.clamp)(position[crossAxis], minPosition, maxPosition);
175
185
  // Floor these so the position isn't placed on a partial pixel, only whole pixels. Shouldn't matter if it was floored or ceiled, so chose one.
176
186
  if (placement === axis) {
177
187
  // If the container is positioned (non-static), then we use the container's actual
178
188
  // height, as `bottom` will be relative to this height. But if the container is static,
179
189
  // then it can only be the `document.body`, and `bottom` will be relative to _its_
180
190
  // container, which should be as large as boundaryDimensions.
181
- const containerHeight = isContainerPositioned ? containerOffsetWithBoundary[size] : boundaryDimensions[size];
191
+ const containerHeight = isContainerPositioned ? containerOffsetWithBoundary[size] : boundaryDimensions[$5935ba4d7da2c103$var$TOTAL_SIZE[size]];
182
192
  position[$5935ba4d7da2c103$var$FLIPPED_DIRECTION[axis]] = Math.floor(containerHeight - childOffset[axis] + offset);
183
193
  } else position[axis] = Math.floor(childOffset[axis] + childOffset[size] + offset);
184
194
  return position;
@@ -197,16 +207,16 @@ function $5935ba4d7da2c103$var$getAvailableSpace(boundaryDimensions, containerOf
197
207
  if (placement === axis) return Math.max(0, childOffset[axis] - boundaryDimensions[axis] - boundaryDimensions.scroll[axis] + containerOffsetWithBoundary[axis] - margins[axis] - margins[$5935ba4d7da2c103$var$FLIPPED_DIRECTION[axis]] - padding);
198
208
  return Math.max(0, boundaryDimensions[size] + boundaryDimensions[axis] + boundaryDimensions.scroll[axis] - containerOffsetWithBoundary[axis] - childOffset[axis] - childOffset[size] - margins[axis] - margins[$5935ba4d7da2c103$var$FLIPPED_DIRECTION[axis]] - padding);
199
209
  }
200
- function $5935ba4d7da2c103$export$6839422d1f33cee9(placementInput, childOffset, overlaySize, scrollSize, margins, padding, flip, boundaryDimensions, containerOffsetWithBoundary, offset, crossOffset, isContainerPositioned, userSetMaxHeight) {
210
+ function $5935ba4d7da2c103$export$6839422d1f33cee9(placementInput, childOffset, overlaySize, scrollSize, margins, padding, flip, boundaryDimensions, containerOffsetWithBoundary, offset, crossOffset, isContainerPositioned, userSetMaxHeight, arrowSize, arrowBoundaryOffset) {
201
211
  let placementInfo = $5935ba4d7da2c103$var$parsePlacement(placementInput);
202
212
  let { size: size , crossAxis: crossAxis , crossSize: crossSize , placement: placement , crossPlacement: crossPlacement } = placementInfo;
203
- let position = $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned);
213
+ let position = $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned, arrowSize, arrowBoundaryOffset);
204
214
  let normalizedOffset = offset;
205
215
  let space = $5935ba4d7da2c103$var$getAvailableSpace(boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding + offset, placementInfo);
206
216
  // Check if the scroll size of the overlay is greater than the available space to determine if we need to flip
207
217
  if (flip && scrollSize[size] > space) {
208
218
  let flippedPlacementInfo = $5935ba4d7da2c103$var$parsePlacement(`${$5935ba4d7da2c103$var$FLIPPED_DIRECTION[placement]} ${crossPlacement}`);
209
- let flippedPosition = $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions, overlaySize, flippedPlacementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned);
219
+ let flippedPosition = $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions, overlaySize, flippedPlacementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned, arrowSize, arrowBoundaryOffset);
210
220
  let flippedSpace = $5935ba4d7da2c103$var$getAvailableSpace(boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding + offset, flippedPlacementInfo);
211
221
  // If the available space for the flipped position is greater than the original available space, flip.
212
222
  if (flippedSpace > space) {
@@ -220,11 +230,22 @@ function $5935ba4d7da2c103$export$6839422d1f33cee9(placementInput, childOffset,
220
230
  let maxHeight = $5935ba4d7da2c103$var$getMaxHeight(position, boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding);
221
231
  if (userSetMaxHeight && userSetMaxHeight < maxHeight) maxHeight = userSetMaxHeight;
222
232
  overlaySize.height = Math.min(overlaySize.height, maxHeight);
223
- position = $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, normalizedOffset, crossOffset, containerOffsetWithBoundary, isContainerPositioned);
233
+ position = $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, normalizedOffset, crossOffset, containerOffsetWithBoundary, isContainerPositioned, arrowSize, arrowBoundaryOffset);
224
234
  delta = $5935ba4d7da2c103$var$getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, padding);
225
235
  position[crossAxis] += delta;
226
236
  let arrowPosition = {};
227
- arrowPosition[crossAxis] = childOffset[crossAxis] - position[crossAxis] + childOffset[crossSize] / 2;
237
+ // All values are transformed so that 0 is at the top/left of the overlay depending on the orientation
238
+ // Prefer the arrow being in the center of the trigger/overlay anchor element
239
+ let preferredArrowPosition = childOffset[crossAxis] + .5 * childOffset[crossSize] - overlaySize[crossAxis];
240
+ // Min/Max position limits for the arrow with respect to the overlay
241
+ const arrowMinPosition = arrowSize / 2 + arrowBoundaryOffset;
242
+ const arrowMaxPosition = overlaySize[crossSize] - arrowSize / 2 - arrowBoundaryOffset;
243
+ // Min/Max position limits for the arrow with respect to the trigger/overlay anchor element
244
+ const arrowOverlappingChildMinEdge = childOffset[crossAxis] - overlaySize[crossAxis] + arrowSize / 2;
245
+ const arrowOverlappingChildMaxEdge = childOffset[crossAxis] + childOffset[crossSize] - overlaySize[crossAxis] - arrowSize / 2;
246
+ // Clamp the arrow positioning so that it always is within the bounds of the anchor and the overlay
247
+ const arrowPositionOverlappingChild = (0, $6Zb2x$reactariautils.clamp)(preferredArrowPosition, arrowOverlappingChildMinEdge, arrowOverlappingChildMaxEdge);
248
+ arrowPosition[crossAxis] = (0, $6Zb2x$reactariautils.clamp)(arrowPositionOverlappingChild, arrowMinPosition, arrowMaxPosition);
228
249
  return {
229
250
  position: position,
230
251
  maxHeight: maxHeight,
@@ -234,13 +255,13 @@ function $5935ba4d7da2c103$export$6839422d1f33cee9(placementInput, childOffset,
234
255
  };
235
256
  }
236
257
  function $5935ba4d7da2c103$export$b3ceb0cbf1056d98(opts) {
237
- let { placement: placement , targetNode: targetNode , overlayNode: overlayNode , scrollNode: scrollNode , padding: padding , shouldFlip: shouldFlip , boundaryElement: boundaryElement , offset: offset , crossOffset: crossOffset , maxHeight: maxHeight } = opts;
238
- let container = overlayNode instanceof HTMLElement && overlayNode.offsetParent || document.body;
239
- let isBodyContainer = container.tagName === "BODY";
258
+ let { placement: placement , targetNode: targetNode , overlayNode: overlayNode , scrollNode: scrollNode , padding: padding , shouldFlip: shouldFlip , boundaryElement: boundaryElement , offset: offset , crossOffset: crossOffset , maxHeight: maxHeight , arrowSize: arrowSize , arrowBoundaryOffset: arrowBoundaryOffset = 0 } = opts;
259
+ let container = overlayNode instanceof HTMLElement ? $5935ba4d7da2c103$var$getContainingBlock(overlayNode) : document.documentElement;
260
+ let isViewportContainer = container === document.documentElement;
240
261
  const containerPositionStyle = window.getComputedStyle(container).position;
241
262
  let isContainerPositioned = !!containerPositionStyle && containerPositionStyle !== "static";
242
- let childOffset = isBodyContainer ? $5935ba4d7da2c103$var$getOffset(targetNode) : $5935ba4d7da2c103$var$getPosition(targetNode, container);
243
- if (!isBodyContainer) {
263
+ let childOffset = isViewportContainer ? $5935ba4d7da2c103$var$getOffset(targetNode) : $5935ba4d7da2c103$var$getPosition(targetNode, container);
264
+ if (!isViewportContainer) {
244
265
  let { marginTop: marginTop , marginLeft: marginLeft } = window.getComputedStyle(targetNode);
245
266
  childOffset.top += parseInt(marginTop, 10) || 0;
246
267
  childOffset.left += parseInt(marginLeft, 10) || 0;
@@ -252,7 +273,7 @@ function $5935ba4d7da2c103$export$b3ceb0cbf1056d98(opts) {
252
273
  let scrollSize = $5935ba4d7da2c103$var$getScroll(scrollNode);
253
274
  let boundaryDimensions = $5935ba4d7da2c103$var$getContainerDimensions(boundaryElement);
254
275
  let containerOffsetWithBoundary = boundaryElement.tagName === "BODY" ? $5935ba4d7da2c103$var$getOffset(container) : $5935ba4d7da2c103$var$getPosition(container, boundaryElement);
255
- return $5935ba4d7da2c103$export$6839422d1f33cee9(placement, childOffset, overlaySize, scrollSize, margins, padding, shouldFlip, boundaryDimensions, containerOffsetWithBoundary, offset, crossOffset, isContainerPositioned, maxHeight);
276
+ return $5935ba4d7da2c103$export$6839422d1f33cee9(placement, childOffset, overlaySize, scrollSize, margins, padding, shouldFlip, boundaryDimensions, containerOffsetWithBoundary, offset, crossOffset, isContainerPositioned, maxHeight, arrowSize, arrowBoundaryOffset);
256
277
  }
257
278
  function $5935ba4d7da2c103$var$getOffset(node) {
258
279
  let { top: top , left: left , width: width , height: height } = node.getBoundingClientRect();
@@ -288,6 +309,35 @@ function $5935ba4d7da2c103$var$getPosition(node, parent) {
288
309
  offset.left -= parseInt(style.marginLeft, 10) || 0;
289
310
  return offset;
290
311
  }
312
+ // Returns the containing block of an element, which is the element that
313
+ // this element will be positioned relative to.
314
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block
315
+ function $5935ba4d7da2c103$var$getContainingBlock(node) {
316
+ // The offsetParent of an element in most cases equals the containing block.
317
+ // https://w3c.github.io/csswg-drafts/cssom-view/#dom-htmlelement-offsetparent
318
+ let offsetParent = node.offsetParent;
319
+ // The offsetParent algorithm terminates at the document body,
320
+ // even if the body is not a containing block. Double check that
321
+ // and use the documentElement if so.
322
+ if (offsetParent && offsetParent === document.body && window.getComputedStyle(offsetParent).position === "static" && !$5935ba4d7da2c103$var$isContainingBlock(offsetParent)) offsetParent = document.documentElement;
323
+ // TODO(later): handle table elements?
324
+ // The offsetParent can be null if the element has position: fixed, or a few other cases.
325
+ // We have to walk up the tree manually in this case because fixed positioned elements
326
+ // are still positioned relative to their containing block, which is not always the viewport.
327
+ if (offsetParent == null) {
328
+ offsetParent = node.parentElement;
329
+ while(offsetParent && !$5935ba4d7da2c103$var$isContainingBlock(offsetParent))offsetParent = offsetParent.parentElement;
330
+ }
331
+ // Fall back to the viewport.
332
+ return offsetParent || document.documentElement;
333
+ }
334
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
335
+ function $5935ba4d7da2c103$var$isContainingBlock(node) {
336
+ let style = window.getComputedStyle(node);
337
+ return style.transform !== "none" || /transform|perspective/.test(style.willChange) || style.filter !== "none" || style.contain === "paint" || // @ts-ignore
338
+ "backdropFilter" in style && style.backdropFilter !== "none" || // @ts-ignore
339
+ "WebkitBackdropFilter" in style && style.WebkitBackdropFilter !== "none";
340
+ }
291
341
 
292
342
 
293
343
 
@@ -333,7 +383,7 @@ function $9a8aa1b0b336ea3a$export$18fc8428861184da(opts) {
333
383
  let $cd94b4896dd97759$var$visualViewport = typeof window !== "undefined" && window.visualViewport;
334
384
  function $cd94b4896dd97759$export$d39e1813b3bdd0e1(props) {
335
385
  let { direction: direction } = (0, $6Zb2x$reactariai18n.useLocale)();
336
- let { targetRef: targetRef , overlayRef: overlayRef , scrollRef: scrollRef = overlayRef , placement: placement = "bottom" , containerPadding: containerPadding = 12 , shouldFlip: shouldFlip = true , boundaryElement: boundaryElement = typeof document !== "undefined" ? document.body : null , offset: offset = 0 , crossOffset: crossOffset = 0 , shouldUpdatePosition: shouldUpdatePosition = true , isOpen: isOpen = true , onClose: onClose , maxHeight: maxHeight } = props;
386
+ let { arrowSize: arrowSize = 0 , targetRef: targetRef , overlayRef: overlayRef , scrollRef: scrollRef = overlayRef , placement: placement = "bottom" , containerPadding: containerPadding = 12 , shouldFlip: shouldFlip = true , boundaryElement: boundaryElement = typeof document !== "undefined" ? document.body : null , offset: offset = 0 , crossOffset: crossOffset = 0 , shouldUpdatePosition: shouldUpdatePosition = true , isOpen: isOpen = true , onClose: onClose , maxHeight: maxHeight , arrowBoundaryOffset: arrowBoundaryOffset = 0 } = props;
337
387
  let [position, setPosition] = (0, $6Zb2x$react.useState)({
338
388
  position: {},
339
389
  arrowOffsetLeft: undefined,
@@ -354,7 +404,9 @@ function $cd94b4896dd97759$export$d39e1813b3bdd0e1(props) {
354
404
  crossOffset,
355
405
  isOpen,
356
406
  direction,
357
- maxHeight
407
+ maxHeight,
408
+ arrowBoundaryOffset,
409
+ arrowSize
358
410
  ];
359
411
  let updatePosition = (0, $6Zb2x$react.useCallback)(()=>{
360
412
  if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !scrollRef.current || !boundaryElement) return;
@@ -368,7 +420,9 @@ function $cd94b4896dd97759$export$d39e1813b3bdd0e1(props) {
368
420
  boundaryElement: boundaryElement,
369
421
  offset: offset,
370
422
  crossOffset: crossOffset,
371
- maxHeight: maxHeight
423
+ maxHeight: maxHeight,
424
+ arrowSize: arrowSize,
425
+ arrowBoundaryOffset: arrowBoundaryOffset
372
426
  });
373
427
  // Modify overlay styles directly so positioning happens immediately without the need of a second render
374
428
  // This is so we don't have to delay autoFocus scrolling or delay applying preventScroll for popovers
@@ -402,8 +456,10 @@ function $cd94b4896dd97759$export$d39e1813b3bdd0e1(props) {
402
456
  updatePosition();
403
457
  };
404
458
  $cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.addEventListener("resize", onResize);
459
+ $cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.addEventListener("scroll", onResize);
405
460
  return ()=>{
406
461
  $cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.removeEventListener("resize", onResize);
462
+ $cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.removeEventListener("scroll", onResize);
407
463
  };
408
464
  }, [
409
465
  updatePosition