@react-aria/overlays 3.20.0 → 3.21.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
@@ -32,8 +32,8 @@ import $29700c92185d38f8$exports from "./tr-TR.mjs";
32
32
  import $662ccaf2be4c25b3$exports from "./uk-UA.mjs";
33
33
  import $d80a27deda7cdb3c$exports from "./zh-CN.mjs";
34
34
  import $2b2734393847c884$exports from "./zh-TW.mjs";
35
- 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";
36
- 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";
35
+ import $k7QOs$react, {useState as $k7QOs$useState, useRef as $k7QOs$useRef, useEffect as $k7QOs$useEffect, useCallback as $k7QOs$useCallback, useContext as $k7QOs$useContext, useMemo as $k7QOs$useMemo} from "react";
36
+ import {useLayoutEffect as $k7QOs$useLayoutEffect, useResizeObserver as $k7QOs$useResizeObserver, isWebKit as $k7QOs$isWebKit, 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";
37
37
  import {useLocale as $k7QOs$useLocale, useLocalizedStringFormatter as $k7QOs$useLocalizedStringFormatter} from "@react-aria/i18n";
38
38
  import {isElementInChildOfActiveScope as $k7QOs$isElementInChildOfActiveScope, FocusScope as $k7QOs$FocusScope} from "@react-aria/focus";
39
39
  import {useInteractOutside as $k7QOs$useInteractOutside, useFocusWithin as $k7QOs$useFocusWithin, ClearPressResponder as $k7QOs$ClearPressResponder} from "@react-aria/interactions";
@@ -106,6 +106,7 @@ let $edcf132a9284368a$var$visualViewport = typeof document !== "undefined" && wi
106
106
  function $edcf132a9284368a$var$getContainerDimensions(containerNode) {
107
107
  let width = 0, height = 0, totalWidth = 0, totalHeight = 0, top = 0, left = 0;
108
108
  let scroll = {};
109
+ let isPinchZoomedIn = ($edcf132a9284368a$var$visualViewport === null || $edcf132a9284368a$var$visualViewport === void 0 ? void 0 : $edcf132a9284368a$var$visualViewport.scale) > 1;
109
110
  if (containerNode.tagName === "BODY") {
110
111
  let documentElement = document.documentElement;
111
112
  totalWidth = documentElement.clientWidth;
@@ -116,6 +117,13 @@ function $edcf132a9284368a$var$getContainerDimensions(containerNode) {
116
117
  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;
117
118
  scroll.top = documentElement.scrollTop || containerNode.scrollTop;
118
119
  scroll.left = documentElement.scrollLeft || containerNode.scrollLeft;
120
+ // The goal of the below is to get a top/left value that represents the top/left of the visual viewport with
121
+ // respect to the layout viewport origin. This combined with the scrollTop/scrollLeft will allow us to calculate
122
+ // coordinates/values with respect to the visual viewport or with respect to the layout viewport.
123
+ if ($edcf132a9284368a$var$visualViewport) {
124
+ top = $edcf132a9284368a$var$visualViewport.offsetTop;
125
+ left = $edcf132a9284368a$var$visualViewport.offsetLeft;
126
+ }
119
127
  } else {
120
128
  ({ width: width, height: height, top: top, left: left } = $edcf132a9284368a$var$getOffset(containerNode));
121
129
  scroll.top = containerNode.scrollTop;
@@ -123,6 +131,16 @@ function $edcf132a9284368a$var$getContainerDimensions(containerNode) {
123
131
  totalWidth = width;
124
132
  totalHeight = height;
125
133
  }
134
+ if ((0, $k7QOs$isWebKit)() && (containerNode.tagName === "BODY" || containerNode.tagName === "HTML") && isPinchZoomedIn) {
135
+ // Safari will report a non-zero scrollTop/Left for the non-scrolling body/HTML element when pinch zoomed in unlike other browsers.
136
+ // Set to zero for parity calculations so we get consistent positioning of overlays across all browsers.
137
+ // Also switch to visualViewport.pageTop/pageLeft so that we still accomodate for scroll positioning for body/HTML elements that are actually scrollable
138
+ // before pinch zoom happens
139
+ scroll.top = 0;
140
+ scroll.left = 0;
141
+ top = $edcf132a9284368a$var$visualViewport.pageTop;
142
+ left = $edcf132a9284368a$var$visualViewport.pageLeft;
143
+ }
126
144
  return {
127
145
  width: width,
128
146
  height: height,
@@ -141,6 +159,7 @@ function $edcf132a9284368a$var$getScroll(node) {
141
159
  height: node.scrollHeight
142
160
  };
143
161
  }
162
+ // Determines the amount of space required when moving the overlay to ensure it remains in the boundary
144
163
  function $edcf132a9284368a$var$getDelta(axis, offset, size, // The dimensions of the boundary element that the popover is
145
164
  // positioned within (most of the time this is the <body>).
146
165
  boundaryDimensions, // The dimensions of the containing block element that the popover is
@@ -148,13 +167,20 @@ boundaryDimensions, // The dimensions of the containing block element that the p
148
167
  // Usually this is the same as the boundary element, but if the popover
149
168
  // is portaled somewhere other than the body and has an ancestor with
150
169
  // position: relative/absolute, it will be different.
151
- containerDimensions, padding) {
170
+ containerDimensions, padding, containerOffsetWithBoundary) {
152
171
  let containerScroll = containerDimensions.scroll[axis];
153
- let boundaryHeight = boundaryDimensions[$edcf132a9284368a$var$AXIS_SIZE[axis]];
154
- let startEdgeOffset = offset - padding - containerScroll;
155
- let endEdgeOffset = offset + padding - containerScroll + size;
156
- if (startEdgeOffset < 0) return -startEdgeOffset;
157
- else if (endEdgeOffset > boundaryHeight) return Math.max(boundaryHeight - endEdgeOffset, -startEdgeOffset);
172
+ // The height/width of the boundary. Matches the axis along which we are adjusting the overlay position
173
+ let boundarySize = boundaryDimensions[$edcf132a9284368a$var$AXIS_SIZE[axis]];
174
+ // Calculate the edges of the boundary (accomodating for the boundary padding) and the edges of the overlay.
175
+ // Note that these values are with respect to the visual viewport (aka 0,0 is the top left of the viewport)
176
+ let boundaryStartEdge = boundaryDimensions.scroll[$edcf132a9284368a$var$AXIS[axis]] + padding;
177
+ let boundaryEndEdge = boundarySize + boundaryDimensions.scroll[$edcf132a9284368a$var$AXIS[axis]] - padding;
178
+ let startEdgeOffset = offset - containerScroll + containerOffsetWithBoundary[axis] - boundaryDimensions[$edcf132a9284368a$var$AXIS[axis]];
179
+ let endEdgeOffset = offset - containerScroll + size + containerOffsetWithBoundary[axis] - boundaryDimensions[$edcf132a9284368a$var$AXIS[axis]];
180
+ // If any of the overlay edges falls outside of the boundary, shift the overlay the required amount to align one of the overlay's
181
+ // edges with the closest boundary edge.
182
+ if (startEdgeOffset < boundaryStartEdge) return boundaryStartEdge - startEdgeOffset;
183
+ else if (endEdgeOffset > boundaryEndEdge) return Math.max(boundaryEndEdge - endEdgeOffset, boundaryStartEdge - startEdgeOffset);
158
184
  else return 0;
159
185
  }
160
186
  function $edcf132a9284368a$var$getMargins(node) {
@@ -198,7 +224,6 @@ function $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions,
198
224
  /* else {
199
225
  the overlay top should match the button top
200
226
  } */
201
- // add the crossOffset from props
202
227
  position[crossAxis] += crossOffset;
203
228
  // overlay top overlapping arrow with button bottom
204
229
  const minPosition = childOffset[crossAxis] - overlaySize[crossSize] + arrowSize + arrowBoundaryOffset;
@@ -216,14 +241,20 @@ function $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions,
216
241
  } else position[axis] = Math.floor(childOffset[axis] + childOffset[size] + offset);
217
242
  return position;
218
243
  }
219
- function $edcf132a9284368a$var$getMaxHeight(position, boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding) {
220
- return position.top != null ? Math.max(0, boundaryDimensions.height + boundaryDimensions.top + boundaryDimensions.scroll.top // this is the bottom of the boundary
221
- - (containerOffsetWithBoundary.top + position.top // this is the top of the overlay
222
- ) - (margins.top + margins.bottom + padding // save additional space for margin and padding
223
- )) : Math.max(0, childOffset.top + containerOffsetWithBoundary.top // this is the top of the trigger
244
+ function $edcf132a9284368a$var$getMaxHeight(position, boundaryDimensions, containerOffsetWithBoundary, isContainerPositioned, margins, padding, overlayHeight, heightGrowthDirection) {
245
+ const containerHeight = isContainerPositioned ? containerOffsetWithBoundary.height : boundaryDimensions[$edcf132a9284368a$var$TOTAL_SIZE.height];
246
+ // For cases where position is set via "bottom" instead of "top", we need to calculate the true overlay top with respect to the boundary. Reverse calculate this with the same method
247
+ // used in computePosition.
248
+ let overlayTop = position.top != null ? containerOffsetWithBoundary.top + position.top : containerOffsetWithBoundary.top + (containerHeight - position.bottom - overlayHeight);
249
+ let maxHeight = heightGrowthDirection !== "top" ? // We want the distance between the top of the overlay to the bottom of the boundary
250
+ Math.max(0, boundaryDimensions.height + boundaryDimensions.top + boundaryDimensions.scroll.top // this is the bottom of the boundary
251
+ - overlayTop // this is the top of the overlay
252
+ - (margins.top + margins.bottom + padding // save additional space for margin and padding
253
+ )) : Math.max(0, overlayTop + overlayHeight // this is the bottom of the overlay
224
254
  - (boundaryDimensions.top + boundaryDimensions.scroll.top // this is the top of the boundary
225
255
  ) - (margins.top + margins.bottom + padding // save additional space for margin and padding
226
256
  ));
257
+ return Math.min(boundaryDimensions.height - padding * 2, maxHeight);
227
258
  }
228
259
  function $edcf132a9284368a$var$getAvailableSpace(boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding, placementInfo) {
229
260
  let { placement: placement, axis: axis, size: size } = placementInfo;
@@ -248,13 +279,22 @@ function $edcf132a9284368a$export$6839422d1f33cee9(placementInput, childOffset,
248
279
  normalizedOffset = offset;
249
280
  }
250
281
  }
251
- let delta = $edcf132a9284368a$var$getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, containerDimensions, padding);
282
+ // Determine the direction the height of the overlay can grow so that we can choose how to calculate the max height
283
+ let heightGrowthDirection = "bottom";
284
+ if (placementInfo.axis === "top") {
285
+ if (placementInfo.placement === "top") heightGrowthDirection = "top";
286
+ else if (placementInfo.placement === "bottom") heightGrowthDirection = "bottom";
287
+ } else if (placementInfo.crossAxis === "top") {
288
+ if (placementInfo.crossPlacement === "top") heightGrowthDirection = "bottom";
289
+ else if (placementInfo.crossPlacement === "bottom") heightGrowthDirection = "top";
290
+ }
291
+ let delta = $edcf132a9284368a$var$getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, containerDimensions, padding, containerOffsetWithBoundary);
252
292
  position[crossAxis] += delta;
253
- let maxHeight = $edcf132a9284368a$var$getMaxHeight(position, boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding);
293
+ let maxHeight = $edcf132a9284368a$var$getMaxHeight(position, boundaryDimensions, containerOffsetWithBoundary, isContainerPositioned, margins, padding, overlaySize.height, heightGrowthDirection);
254
294
  if (userSetMaxHeight && userSetMaxHeight < maxHeight) maxHeight = userSetMaxHeight;
255
295
  overlaySize.height = Math.min(overlaySize.height, maxHeight);
256
296
  position = $edcf132a9284368a$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, normalizedOffset, crossOffset, containerOffsetWithBoundary, isContainerPositioned, arrowSize, arrowBoundaryOffset);
257
- delta = $edcf132a9284368a$var$getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, containerDimensions, padding);
297
+ delta = $edcf132a9284368a$var$getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, containerDimensions, padding, containerOffsetWithBoundary);
258
298
  position[crossAxis] += delta;
259
299
  let arrowPosition = {};
260
300
  // All values are transformed so that 0 is at the top/left of the overlay depending on the orientation
@@ -296,7 +336,14 @@ function $edcf132a9284368a$export$b3ceb0cbf1056d98(opts) {
296
336
  let scrollSize = $edcf132a9284368a$var$getScroll(scrollNode);
297
337
  let boundaryDimensions = $edcf132a9284368a$var$getContainerDimensions(boundaryElement);
298
338
  let containerDimensions = $edcf132a9284368a$var$getContainerDimensions(container);
339
+ // If the container is the HTML element wrapping the body element, the retrieved scrollTop/scrollLeft will be equal to the
340
+ // body element's scroll. Set the container's scroll values to 0 since the overlay's edge position value in getDelta don't then need to be further offset
341
+ // by the container scroll since they are essentially the same containing element and thus in the same coordinate system
299
342
  let containerOffsetWithBoundary = boundaryElement.tagName === "BODY" ? $edcf132a9284368a$var$getOffset(container) : $edcf132a9284368a$var$getPosition(container, boundaryElement);
343
+ if (container.tagName === "HTML" && boundaryElement.tagName === "BODY") {
344
+ containerDimensions.scroll.top = 0;
345
+ containerDimensions.scroll.left = 0;
346
+ }
300
347
  return $edcf132a9284368a$export$6839422d1f33cee9(placement, childOffset, overlaySize, scrollSize, margins, padding, shouldFlip, boundaryDimensions, containerDimensions, containerOffsetWithBoundary, offset, crossOffset, isContainerPositioned, maxHeight, arrowSize, arrowBoundaryOffset);
301
348
  }
302
349
  function $edcf132a9284368a$var$getOffset(node) {
@@ -432,8 +479,21 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
432
479
  arrowBoundaryOffset,
433
480
  arrowSize
434
481
  ];
482
+ // Note, the position freezing breaks if body sizes itself dynamicly with the visual viewport but that might
483
+ // just be a non-realistic use case
484
+ // Upon opening a overlay, record the current visual viewport scale so we can freeze the overlay styles
485
+ let lastScale = (0, $k7QOs$useRef)($2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.scale);
486
+ (0, $k7QOs$useEffect)(()=>{
487
+ if (isOpen) lastScale.current = $2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.scale;
488
+ }, [
489
+ isOpen
490
+ ]);
435
491
  let updatePosition = (0, $k7QOs$useCallback)(()=>{
436
492
  if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !scrollRef.current || !boundaryElement) return;
493
+ if (($2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.scale) !== lastScale.current) return;
494
+ // Always reset the overlay's previous max height if not defined by the user so that we can compensate for
495
+ // RAC collections populating after a second render and properly set a correct max height + positioning when it populates.
496
+ if (!maxHeight && overlayRef.current) overlayRef.current.style.maxHeight = "none";
437
497
  let position = (0, $edcf132a9284368a$export$b3ceb0cbf1056d98)({
438
498
  placement: $2a41e45df1593e64$var$translateRTL(placement, direction),
439
499
  overlayNode: overlayRef.current,
@@ -479,11 +539,16 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
479
539
  }, 500);
480
540
  updatePosition();
481
541
  };
542
+ // Only reposition the overlay if a scroll event happens immediately as a result of resize (aka the virtual keyboard has appears)
543
+ // We don't want to reposition the overlay if the user has pinch zoomed in and is scrolling the viewport around.
544
+ let onScroll = ()=>{
545
+ if (isResizing.current) onResize();
546
+ };
482
547
  $2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.addEventListener("resize", onResize);
483
- $2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.addEventListener("scroll", onResize);
548
+ $2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.addEventListener("scroll", onScroll);
484
549
  return ()=>{
485
550
  $2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.removeEventListener("resize", onResize);
486
- $2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.removeEventListener("scroll", onResize);
551
+ $2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.removeEventListener("scroll", onScroll);
487
552
  };
488
553
  }, [
489
554
  updatePosition
package/dist/main.js CHANGED
@@ -126,6 +126,7 @@ let $5935ba4d7da2c103$var$visualViewport = typeof document !== "undefined" && wi
126
126
  function $5935ba4d7da2c103$var$getContainerDimensions(containerNode) {
127
127
  let width = 0, height = 0, totalWidth = 0, totalHeight = 0, top = 0, left = 0;
128
128
  let scroll = {};
129
+ let isPinchZoomedIn = ($5935ba4d7da2c103$var$visualViewport === null || $5935ba4d7da2c103$var$visualViewport === void 0 ? void 0 : $5935ba4d7da2c103$var$visualViewport.scale) > 1;
129
130
  if (containerNode.tagName === "BODY") {
130
131
  let documentElement = document.documentElement;
131
132
  totalWidth = documentElement.clientWidth;
@@ -136,6 +137,13 @@ function $5935ba4d7da2c103$var$getContainerDimensions(containerNode) {
136
137
  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;
137
138
  scroll.top = documentElement.scrollTop || containerNode.scrollTop;
138
139
  scroll.left = documentElement.scrollLeft || containerNode.scrollLeft;
140
+ // The goal of the below is to get a top/left value that represents the top/left of the visual viewport with
141
+ // respect to the layout viewport origin. This combined with the scrollTop/scrollLeft will allow us to calculate
142
+ // coordinates/values with respect to the visual viewport or with respect to the layout viewport.
143
+ if ($5935ba4d7da2c103$var$visualViewport) {
144
+ top = $5935ba4d7da2c103$var$visualViewport.offsetTop;
145
+ left = $5935ba4d7da2c103$var$visualViewport.offsetLeft;
146
+ }
139
147
  } else {
140
148
  ({ width: width, height: height, top: top, left: left } = $5935ba4d7da2c103$var$getOffset(containerNode));
141
149
  scroll.top = containerNode.scrollTop;
@@ -143,6 +151,16 @@ function $5935ba4d7da2c103$var$getContainerDimensions(containerNode) {
143
151
  totalWidth = width;
144
152
  totalHeight = height;
145
153
  }
154
+ if ((0, $6Zb2x$reactariautils.isWebKit)() && (containerNode.tagName === "BODY" || containerNode.tagName === "HTML") && isPinchZoomedIn) {
155
+ // Safari will report a non-zero scrollTop/Left for the non-scrolling body/HTML element when pinch zoomed in unlike other browsers.
156
+ // Set to zero for parity calculations so we get consistent positioning of overlays across all browsers.
157
+ // Also switch to visualViewport.pageTop/pageLeft so that we still accomodate for scroll positioning for body/HTML elements that are actually scrollable
158
+ // before pinch zoom happens
159
+ scroll.top = 0;
160
+ scroll.left = 0;
161
+ top = $5935ba4d7da2c103$var$visualViewport.pageTop;
162
+ left = $5935ba4d7da2c103$var$visualViewport.pageLeft;
163
+ }
146
164
  return {
147
165
  width: width,
148
166
  height: height,
@@ -161,6 +179,7 @@ function $5935ba4d7da2c103$var$getScroll(node) {
161
179
  height: node.scrollHeight
162
180
  };
163
181
  }
182
+ // Determines the amount of space required when moving the overlay to ensure it remains in the boundary
164
183
  function $5935ba4d7da2c103$var$getDelta(axis, offset, size, // The dimensions of the boundary element that the popover is
165
184
  // positioned within (most of the time this is the <body>).
166
185
  boundaryDimensions, // The dimensions of the containing block element that the popover is
@@ -168,13 +187,20 @@ boundaryDimensions, // The dimensions of the containing block element that the p
168
187
  // Usually this is the same as the boundary element, but if the popover
169
188
  // is portaled somewhere other than the body and has an ancestor with
170
189
  // position: relative/absolute, it will be different.
171
- containerDimensions, padding) {
190
+ containerDimensions, padding, containerOffsetWithBoundary) {
172
191
  let containerScroll = containerDimensions.scroll[axis];
173
- let boundaryHeight = boundaryDimensions[$5935ba4d7da2c103$var$AXIS_SIZE[axis]];
174
- let startEdgeOffset = offset - padding - containerScroll;
175
- let endEdgeOffset = offset + padding - containerScroll + size;
176
- if (startEdgeOffset < 0) return -startEdgeOffset;
177
- else if (endEdgeOffset > boundaryHeight) return Math.max(boundaryHeight - endEdgeOffset, -startEdgeOffset);
192
+ // The height/width of the boundary. Matches the axis along which we are adjusting the overlay position
193
+ let boundarySize = boundaryDimensions[$5935ba4d7da2c103$var$AXIS_SIZE[axis]];
194
+ // Calculate the edges of the boundary (accomodating for the boundary padding) and the edges of the overlay.
195
+ // Note that these values are with respect to the visual viewport (aka 0,0 is the top left of the viewport)
196
+ let boundaryStartEdge = boundaryDimensions.scroll[$5935ba4d7da2c103$var$AXIS[axis]] + padding;
197
+ let boundaryEndEdge = boundarySize + boundaryDimensions.scroll[$5935ba4d7da2c103$var$AXIS[axis]] - padding;
198
+ let startEdgeOffset = offset - containerScroll + containerOffsetWithBoundary[axis] - boundaryDimensions[$5935ba4d7da2c103$var$AXIS[axis]];
199
+ let endEdgeOffset = offset - containerScroll + size + containerOffsetWithBoundary[axis] - boundaryDimensions[$5935ba4d7da2c103$var$AXIS[axis]];
200
+ // If any of the overlay edges falls outside of the boundary, shift the overlay the required amount to align one of the overlay's
201
+ // edges with the closest boundary edge.
202
+ if (startEdgeOffset < boundaryStartEdge) return boundaryStartEdge - startEdgeOffset;
203
+ else if (endEdgeOffset > boundaryEndEdge) return Math.max(boundaryEndEdge - endEdgeOffset, boundaryStartEdge - startEdgeOffset);
178
204
  else return 0;
179
205
  }
180
206
  function $5935ba4d7da2c103$var$getMargins(node) {
@@ -218,7 +244,6 @@ function $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions,
218
244
  /* else {
219
245
  the overlay top should match the button top
220
246
  } */
221
- // add the crossOffset from props
222
247
  position[crossAxis] += crossOffset;
223
248
  // overlay top overlapping arrow with button bottom
224
249
  const minPosition = childOffset[crossAxis] - overlaySize[crossSize] + arrowSize + arrowBoundaryOffset;
@@ -236,14 +261,20 @@ function $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions,
236
261
  } else position[axis] = Math.floor(childOffset[axis] + childOffset[size] + offset);
237
262
  return position;
238
263
  }
239
- function $5935ba4d7da2c103$var$getMaxHeight(position, boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding) {
240
- return position.top != null ? Math.max(0, boundaryDimensions.height + boundaryDimensions.top + boundaryDimensions.scroll.top // this is the bottom of the boundary
241
- - (containerOffsetWithBoundary.top + position.top // this is the top of the overlay
242
- ) - (margins.top + margins.bottom + padding // save additional space for margin and padding
243
- )) : Math.max(0, childOffset.top + containerOffsetWithBoundary.top // this is the top of the trigger
264
+ function $5935ba4d7da2c103$var$getMaxHeight(position, boundaryDimensions, containerOffsetWithBoundary, isContainerPositioned, margins, padding, overlayHeight, heightGrowthDirection) {
265
+ const containerHeight = isContainerPositioned ? containerOffsetWithBoundary.height : boundaryDimensions[$5935ba4d7da2c103$var$TOTAL_SIZE.height];
266
+ // For cases where position is set via "bottom" instead of "top", we need to calculate the true overlay top with respect to the boundary. Reverse calculate this with the same method
267
+ // used in computePosition.
268
+ let overlayTop = position.top != null ? containerOffsetWithBoundary.top + position.top : containerOffsetWithBoundary.top + (containerHeight - position.bottom - overlayHeight);
269
+ let maxHeight = heightGrowthDirection !== "top" ? // We want the distance between the top of the overlay to the bottom of the boundary
270
+ Math.max(0, boundaryDimensions.height + boundaryDimensions.top + boundaryDimensions.scroll.top // this is the bottom of the boundary
271
+ - overlayTop // this is the top of the overlay
272
+ - (margins.top + margins.bottom + padding // save additional space for margin and padding
273
+ )) : Math.max(0, overlayTop + overlayHeight // this is the bottom of the overlay
244
274
  - (boundaryDimensions.top + boundaryDimensions.scroll.top // this is the top of the boundary
245
275
  ) - (margins.top + margins.bottom + padding // save additional space for margin and padding
246
276
  ));
277
+ return Math.min(boundaryDimensions.height - padding * 2, maxHeight);
247
278
  }
248
279
  function $5935ba4d7da2c103$var$getAvailableSpace(boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding, placementInfo) {
249
280
  let { placement: placement, axis: axis, size: size } = placementInfo;
@@ -268,13 +299,22 @@ function $5935ba4d7da2c103$export$6839422d1f33cee9(placementInput, childOffset,
268
299
  normalizedOffset = offset;
269
300
  }
270
301
  }
271
- let delta = $5935ba4d7da2c103$var$getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, containerDimensions, padding);
302
+ // Determine the direction the height of the overlay can grow so that we can choose how to calculate the max height
303
+ let heightGrowthDirection = "bottom";
304
+ if (placementInfo.axis === "top") {
305
+ if (placementInfo.placement === "top") heightGrowthDirection = "top";
306
+ else if (placementInfo.placement === "bottom") heightGrowthDirection = "bottom";
307
+ } else if (placementInfo.crossAxis === "top") {
308
+ if (placementInfo.crossPlacement === "top") heightGrowthDirection = "bottom";
309
+ else if (placementInfo.crossPlacement === "bottom") heightGrowthDirection = "top";
310
+ }
311
+ let delta = $5935ba4d7da2c103$var$getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, containerDimensions, padding, containerOffsetWithBoundary);
272
312
  position[crossAxis] += delta;
273
- let maxHeight = $5935ba4d7da2c103$var$getMaxHeight(position, boundaryDimensions, containerOffsetWithBoundary, childOffset, margins, padding);
313
+ let maxHeight = $5935ba4d7da2c103$var$getMaxHeight(position, boundaryDimensions, containerOffsetWithBoundary, isContainerPositioned, margins, padding, overlaySize.height, heightGrowthDirection);
274
314
  if (userSetMaxHeight && userSetMaxHeight < maxHeight) maxHeight = userSetMaxHeight;
275
315
  overlaySize.height = Math.min(overlaySize.height, maxHeight);
276
316
  position = $5935ba4d7da2c103$var$computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, normalizedOffset, crossOffset, containerOffsetWithBoundary, isContainerPositioned, arrowSize, arrowBoundaryOffset);
277
- delta = $5935ba4d7da2c103$var$getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, containerDimensions, padding);
317
+ delta = $5935ba4d7da2c103$var$getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, containerDimensions, padding, containerOffsetWithBoundary);
278
318
  position[crossAxis] += delta;
279
319
  let arrowPosition = {};
280
320
  // All values are transformed so that 0 is at the top/left of the overlay depending on the orientation
@@ -316,7 +356,14 @@ function $5935ba4d7da2c103$export$b3ceb0cbf1056d98(opts) {
316
356
  let scrollSize = $5935ba4d7da2c103$var$getScroll(scrollNode);
317
357
  let boundaryDimensions = $5935ba4d7da2c103$var$getContainerDimensions(boundaryElement);
318
358
  let containerDimensions = $5935ba4d7da2c103$var$getContainerDimensions(container);
359
+ // If the container is the HTML element wrapping the body element, the retrieved scrollTop/scrollLeft will be equal to the
360
+ // body element's scroll. Set the container's scroll values to 0 since the overlay's edge position value in getDelta don't then need to be further offset
361
+ // by the container scroll since they are essentially the same containing element and thus in the same coordinate system
319
362
  let containerOffsetWithBoundary = boundaryElement.tagName === "BODY" ? $5935ba4d7da2c103$var$getOffset(container) : $5935ba4d7da2c103$var$getPosition(container, boundaryElement);
363
+ if (container.tagName === "HTML" && boundaryElement.tagName === "BODY") {
364
+ containerDimensions.scroll.top = 0;
365
+ containerDimensions.scroll.left = 0;
366
+ }
320
367
  return $5935ba4d7da2c103$export$6839422d1f33cee9(placement, childOffset, overlaySize, scrollSize, margins, padding, shouldFlip, boundaryDimensions, containerDimensions, containerOffsetWithBoundary, offset, crossOffset, isContainerPositioned, maxHeight, arrowSize, arrowBoundaryOffset);
321
368
  }
322
369
  function $5935ba4d7da2c103$var$getOffset(node) {
@@ -452,8 +499,21 @@ function $cd94b4896dd97759$export$d39e1813b3bdd0e1(props) {
452
499
  arrowBoundaryOffset,
453
500
  arrowSize
454
501
  ];
502
+ // Note, the position freezing breaks if body sizes itself dynamicly with the visual viewport but that might
503
+ // just be a non-realistic use case
504
+ // Upon opening a overlay, record the current visual viewport scale so we can freeze the overlay styles
505
+ let lastScale = (0, $6Zb2x$react.useRef)($cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.scale);
506
+ (0, $6Zb2x$react.useEffect)(()=>{
507
+ if (isOpen) lastScale.current = $cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.scale;
508
+ }, [
509
+ isOpen
510
+ ]);
455
511
  let updatePosition = (0, $6Zb2x$react.useCallback)(()=>{
456
512
  if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !scrollRef.current || !boundaryElement) return;
513
+ if (($cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.scale) !== lastScale.current) return;
514
+ // Always reset the overlay's previous max height if not defined by the user so that we can compensate for
515
+ // RAC collections populating after a second render and properly set a correct max height + positioning when it populates.
516
+ if (!maxHeight && overlayRef.current) overlayRef.current.style.maxHeight = "none";
457
517
  let position = (0, $5935ba4d7da2c103$export$b3ceb0cbf1056d98)({
458
518
  placement: $cd94b4896dd97759$var$translateRTL(placement, direction),
459
519
  overlayNode: overlayRef.current,
@@ -499,11 +559,16 @@ function $cd94b4896dd97759$export$d39e1813b3bdd0e1(props) {
499
559
  }, 500);
500
560
  updatePosition();
501
561
  };
562
+ // Only reposition the overlay if a scroll event happens immediately as a result of resize (aka the virtual keyboard has appears)
563
+ // We don't want to reposition the overlay if the user has pinch zoomed in and is scrolling the viewport around.
564
+ let onScroll = ()=>{
565
+ if (isResizing.current) onResize();
566
+ };
502
567
  $cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.addEventListener("resize", onResize);
503
- $cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.addEventListener("scroll", onResize);
568
+ $cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.addEventListener("scroll", onScroll);
504
569
  return ()=>{
505
570
  $cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.removeEventListener("resize", onResize);
506
- $cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.removeEventListener("scroll", onResize);
571
+ $cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.removeEventListener("scroll", onScroll);
507
572
  };
508
573
  }, [
509
574
  updatePosition