{"mappings":";;;;;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;;;;AA4HD,IAAI,uCAAiB,OAAO,aAAa,cAAc,OAAO,cAAc,GAAG;AAMxE,SAAS,0CAAmB,KAAwB;IACzD,IAAI,aAAC,SAAS,EAAC,GAAG,CAAA,GAAA,mCAAQ;IAC1B,IAAI,aACF,SAAS,aACT,SAAS,cACT,UAAU,YACV,QAAQ,aACR,YAAY,uBACZ,YAAY,4BACZ,mBAAmB,gBACnB,aAAa,uBACb,kBAAkB,OAAO,aAAa,cAAc,SAAS,IAAI,GAAG,cACpE,SAAS,gBACT,cAAc,yBACd,uBAAuB,cACvB,SAAS,eACT,OAAO,aACP,SAAS,uBACT,sBAAsB,GACvB,GAAG;IACJ,IAAI,CAAC,UAAU,YAAY,GAAG,CAAA,GAAA,qBAAO,EAAyB;IAE9D,IAAI,OAAO;QACT;QACA;QACA,WAAW,OAAO;QAClB,UAAU,OAAO;QACjB,UAAU;QACV,UAAU,OAAO;QACjB;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;KACD;IAED,4GAA4G;IAC5G,mCAAmC;IACnC,uGAAuG;IACvG,IAAI,YAAY,CAAA,GAAA,mBAAK,EAAE,sCAAgB;IACvC,CAAA,GAAA,sBAAQ,EAAE;QACR,IAAI,QACF,UAAU,OAAO,GAAG,sCAAgB;IAExC,GAAG;QAAC;KAAO;IAEX,IAAI,iBAAiB,CAAA,GAAA,wBAAU,EAAE;QAC/B,IAAI,yBAAyB,SAAS,CAAC,UAAU,CAAC,WAAW,OAAO,IAAI,CAAC,UAAU,OAAO,IAAI,CAAC,iBAC7F;QAGF,IAAI,sCAAgB,UAAU,UAAU,OAAO,EAC7C;QAGF,0DAA0D;QAC1D,yEAAyE;QACzE,4EAA4E;QAC5E,qEAAqE;QACrE,IAAI,SAA8B;QAClC,IAAI,UAAU,OAAO,IAAI,CAAA,GAAA,uCAAY,EAAE,UAAU,OAAO,GAAG;YACzD,IAAI,aAAa,CAAA,GAAA,0CAAe,KAAK;YACrC,IAAI,aAAa,UAAU,OAAO,CAAC,qBAAqB;YACxD,kFAAkF;YAClF,oCAAoC;YACpC,SAAS;gBACP,MAAM;gBACN,QAAQ,AAAC,CAAA,YAAY,OAAO,CAAA,IAAK,WAAW,GAAG;YACjD;YACA,IAAI,OAAO,MAAM,GAAG,WAAW,MAAM,GAAG,GAAG;gBACzC,OAAO,IAAI,GAAG;gBACd,OAAO,MAAM,GAAG,AAAC,CAAA,YAAY,UAAU,CAAA,IAAK,WAAW,MAAM;YAC/D;QACF;QAEA,0GAA0G;QAC1G,0HAA0H;QAC1H,IAAI,UAAW,WAAW,OAAO;QACjC,IAAI,CAAC,aAAa,WAAW,OAAO,EAAE;YACpC,QAAQ,KAAK,CAAC,GAAG,GAAG;YACpB,QAAQ,KAAK,CAAC,MAAM,GAAG;YACvB,QAAQ,KAAK,CAAC,SAAS,GAAG,AAAC,CAAA,OAAO,cAAc,EAAE,UAAU,OAAO,WAAW,AAAD,IAAK;QACpF;QAEA,IAAI,WAAW,CAAA,GAAA,2CAAgB,EAAE;YAC/B,WAAW,mCAAa,WAAW;YACnC,aAAa,WAAW,OAAO;YAC/B,YAAY,UAAU,OAAO;YAC7B,YAAY,UAAU,OAAO,IAAI,WAAW,OAAO;YACnD,SAAS;wBACT;6BACA;oBACA;yBACA;uBACA;YACA,WAAW,aAAc,CAAA,UAAU,UAAU,CAAA,GAAA,iCAAM,EAAE,SAAS,OAAO,EAAE,MAAM,KAAK,GAAG,CAAA;iCACrF;QACF;QAEA,IAAI,CAAC,SAAS,QAAQ,EACpB;QAGF,wGAAwG;QACxG,qGAAqG;QACrG,QAAQ,KAAK,CAAC,GAAG,GAAG;QACpB,QAAQ,KAAK,CAAC,MAAM,GAAG;QACvB,QAAQ,KAAK,CAAC,IAAI,GAAG;QACrB,QAAQ,KAAK,CAAC,KAAK,GAAG;QAEtB,OAAO,IAAI,CAAC,SAAS,QAAQ,EAAE,OAAO,CAAC,CAAA,MAAO,QAAQ,KAAK,CAAC,IAAI,GAAG,AAAC,SAAS,QAAQ,AAAE,CAAC,IAAI,GAAG;QAC/F,QAAQ,KAAK,CAAC,SAAS,GAAG,SAAS,SAAS,IAAI,OAAQ,SAAS,SAAS,GAAG,OAAO;QAEpF,sDAAsD;QACtD,IAAI,gBAAgB,CAAA,GAAA,0CAAe;QACnC,IAAI,UAAU,iBAAiB,UAAU,OAAO,EAAE;YAChD,IAAI,aAAa,cAAc,qBAAqB;YACpD,IAAI,aAAa,UAAU,OAAO,CAAC,qBAAqB;YACxD,IAAI,YAAY,UAAU,CAAC,OAAO,IAAI,CAAC,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC;YACjE,UAAU,OAAO,CAAC,SAAS,IAAI,YAAY,OAAO,MAAM;QAC1D;QAEA,uEAAuE;QACvE,YAAY;IACd,uDAAuD;IACvD,GAAG;IAEH,wCAAwC;IACxC,uDAAuD;IACvD,CAAA,GAAA,yCAAc,EAAE,gBAAgB;IAEhC,mCAAmC;IACnC,gCAAU;IAEV,sEAAsE;IACtE,CAAA,GAAA,2CAAgB,EAAE;QAChB,KAAK;QACL,UAAU;IACZ;IAEA,qEAAqE;IACrE,CAAA,GAAA,2CAAgB,EAAE;QAChB,KAAK;QACL,UAAU;IACZ;IAEA,2FAA2F;IAC3F,iGAAiG;IACjG,IAAI,aAAa,CAAA,GAAA,mBAAK,EAAE;IACxB,CAAA,GAAA,yCAAc,EAAE;QACd,IAAI;QACJ,IAAI,WAAW;YACb,WAAW,OAAO,GAAG;YACrB,aAAa;YAEb,UAAU,WAAW;gBACnB,WAAW,OAAO,GAAG;YACvB,GAAG;YAEH;QACF;QAEA,iIAAiI;QACjI,gHAAgH;QAChH,IAAI,WAAW;YACb,IAAI,WAAW,OAAO,EACpB;QAEJ;QAEA,sCAAgB,iBAAiB,UAAU;QAC3C,sCAAgB,iBAAiB,UAAU;QAC3C,OAAO;YACL,sCAAgB,oBAAoB,UAAU;YAC9C,sCAAgB,oBAAoB,UAAU;QAChD;IACF,GAAG;QAAC;KAAe;IAEnB,IAAI,QAAQ,CAAA,GAAA,wBAAU,EAAE;QACtB,IAAI,CAAC,WAAW,OAAO,EACrB;IAEJ,GAAG;QAAC;QAAS;KAAW;IAExB,kFAAkF;IAClF,mEAAmE;IACnE,CAAA,GAAA,0CAAe,EAAE;QACf,YAAY;gBACZ;QACA,SAAS,WAAW;IACtB;IAEA,OAAO;QACL,cAAc;YACZ,OAAO;gBACL,UAAU,WAAW,aAAa;gBAClC,KAAK,CAAC,WAAW,IAAI;gBACrB,MAAM,CAAC,WAAW,IAAI;gBACtB,QAAQ;gBACR,GAAG,UAAU,QAAQ;gBACrB,WAAW,UAAU,aAAa;YACpC;QACF;QACA,WAAW,UAAU,aAAa;QAClC,oBAAoB,UAAU,sBAAsB;QACpD,YAAY;YACV,eAAe;YACf,MAAM;YACN,OAAO;gBACL,MAAM,UAAU;gBAChB,KAAK,UAAU;YACjB;QACF;wBACA;IACF;AACF;AAEA,SAAS,gCAAU,QAAQ;IACzB,CAAA,GAAA,yCAAc,EAAE;QACd,OAAO,gBAAgB,CAAC,UAAU,UAAU;QAC5C,OAAO;YACL,OAAO,mBAAmB,CAAC,UAAU,UAAU;QACjD;IACF,GAAG;QAAC;KAAS;AACf;AAEA,SAAS,mCAAa,QAAQ,EAAE,SAAS;IACvC,IAAI,cAAc,OAChB,OAAO,SAAS,OAAO,CAAC,SAAS,SAAS,OAAO,CAAC,OAAO;IAE3D,OAAO,SAAS,OAAO,CAAC,SAAS,QAAQ,OAAO,CAAC,OAAO;AAC1D","sources":["packages/react-aria/src/overlays/useOverlayPosition.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {calculatePosition, getRect, PositionResult} from './calculatePosition';\nimport {DOMAttributes, RefObject} from '@react-types/shared';\nimport {getActiveElement, isFocusWithin} from '../utils/shadowdom/DOMFunctions';\nimport {useCallback, useEffect, useRef, useState} from 'react';\nimport {useCloseOnScroll} from './useCloseOnScroll';\nimport {useLayoutEffect} from '../utils/useLayoutEffect';\nimport {useLocale} from '../i18n/I18nProvider';\nimport {useResizeObserver} from '../utils/useResizeObserver';\n\nexport type Placement = 'bottom' | 'bottom left' | 'bottom right' | 'bottom start' | 'bottom end' |\n    'top' | 'top left' | 'top right' | 'top start' | 'top end' |\n    'left' | 'left top' | 'left bottom' | 'start' | 'start top' | 'start bottom' |\n    'right' | 'right top' | 'right bottom' | 'end' | 'end top' | 'end bottom';\n\nexport type Axis = 'top' | 'bottom' | 'left' | 'right';\nexport type SizeAxis = 'width' | 'height';\nexport type PlacementAxis = Axis | 'center';\n\nexport interface PositionProps {\n  /**\n   * The placement of the element with respect to its anchor element.\n   * @default 'bottom'\n   */\n  placement?: Placement,\n  /**\n   * The placement padding that should be applied between the element and its\n   * surrounding container.\n   * @default 12\n   */\n  containerPadding?: number,\n  /**\n   * The additional offset applied along the main axis between the element and its\n   * anchor element.\n   * @default 0\n   */\n  offset?: number,\n  /**\n   * The additional offset applied along the cross axis between the element and its\n   * anchor element.\n   * @default 0\n   */\n  crossOffset?: number,\n  /**\n   * Whether the element should flip its orientation (e.g. top to bottom or left to right) when\n   * there is insufficient room for it to render completely.\n   * @default true\n   */\n  shouldFlip?: boolean,\n  // /**\n  //  * The element that should be used as the bounding container when calculating container offset\n  //  * or whether it should flip.\n  //  */\n  // boundaryElement?: Element,\n  /** Whether the element is rendered. */\n  isOpen?: boolean\n}\n\nexport interface AriaPositionProps extends PositionProps {\n  /**\n   * Cross size of the overlay arrow in pixels.\n   * @default 0\n   */\n  arrowSize?: number,\n  /**\n   * Element that that serves as the positioning boundary.\n   * @default document.body\n   */\n  boundaryElement?: Element,\n  /**\n   * The ref for the element which the overlay positions itself with respect to.\n   */\n  targetRef: RefObject<Element | null>,\n  /**\n   * The ref for the overlay element.\n   */\n  overlayRef: RefObject<Element | null>,\n  /**\n   * The ref for the arrow element.\n   */\n  arrowRef?: RefObject<Element | null>,\n  /**\n   * A ref for the scrollable region within the overlay.\n   * @default overlayRef\n   */\n  scrollRef?: RefObject<Element | null>,\n  /**\n   * Whether the overlay should update its position automatically.\n   * @default true\n   */\n  shouldUpdatePosition?: boolean,\n  /** Handler that is called when the overlay should close. */\n  onClose?: (() => void) | null,\n  /**\n   * The maxHeight specified for the overlay element.\n   * By default, it will take all space up to the current viewport height.\n   */\n  maxHeight?: number,\n  /**\n   * The minimum distance the arrow's edge should be from the edge of the overlay element.\n   * @default 0\n   */\n  arrowBoundaryOffset?: number\n}\n\nexport interface PositionAria {\n  /** Props for the overlay container element. */\n  overlayProps: DOMAttributes,\n  /** Props for the overlay tip arrow if any. */\n  arrowProps: DOMAttributes,\n  /** Placement of the overlay with respect to the overlay trigger. */\n  placement: PlacementAxis | null,\n  /** The origin of the target in the overlay's coordinate system. Useful for animations. */\n  triggerAnchorPoint: {x: number, y: number} | null,\n  /** Updates the position of the overlay. */\n  updatePosition(): void\n}\n\ninterface ScrollAnchor {\n  type: 'top' | 'bottom',\n  offset: number\n}\n\nlet visualViewport = typeof document !== 'undefined' ? window.visualViewport : null;\n\n/**\n * Handles positioning overlays like popovers and menus relative to a trigger\n * element, and updating the position when the window resizes.\n */\nexport function useOverlayPosition(props: AriaPositionProps): PositionAria {\n  let {direction} = useLocale();\n  let {\n    arrowSize,\n    targetRef,\n    overlayRef,\n    arrowRef,\n    scrollRef = overlayRef,\n    placement = 'bottom' as Placement,\n    containerPadding = 12,\n    shouldFlip = true,\n    boundaryElement = typeof document !== 'undefined' ? document.body : null,\n    offset = 0,\n    crossOffset = 0,\n    shouldUpdatePosition = true,\n    isOpen = true,\n    onClose,\n    maxHeight,\n    arrowBoundaryOffset = 0\n  } = props;\n  let [position, setPosition] = useState<PositionResult | null>(null);\n\n  let deps = [\n    shouldUpdatePosition,\n    placement,\n    overlayRef.current,\n    targetRef.current,\n    arrowRef?.current,\n    scrollRef.current,\n    containerPadding,\n    shouldFlip,\n    boundaryElement,\n    offset,\n    crossOffset,\n    isOpen,\n    direction,\n    maxHeight,\n    arrowBoundaryOffset,\n    arrowSize\n  ];\n\n  // Note, the position freezing breaks if body sizes itself dynamicly with the visual viewport but that might\n  // just be a non-realistic use case\n  // Upon opening a overlay, record the current visual viewport scale so we can freeze the overlay styles\n  let lastScale = useRef(visualViewport?.scale);\n  useEffect(() => {\n    if (isOpen) {\n      lastScale.current = visualViewport?.scale;\n    }\n  }, [isOpen]);\n\n  let updatePosition = useCallback(() => {\n    if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !boundaryElement) {\n      return;\n    }\n\n    if (visualViewport?.scale !== lastScale.current) {\n      return;\n    }\n\n    // Determine a scroll anchor based on the focused element.\n    // This stores the offset of the anchor element from the scroll container\n    // so it can be restored after repositioning. This way if the overlay height\n    // changes, the focused element appears to stay in the same position.\n    let anchor: ScrollAnchor | null = null;\n    if (scrollRef.current && isFocusWithin(scrollRef.current)) {\n      let anchorRect = getActiveElement()?.getBoundingClientRect();\n      let scrollRect = scrollRef.current.getBoundingClientRect();\n      // Anchor from the top if the offset is in the top half of the scrollable element,\n      // otherwise anchor from the bottom.\n      anchor = {\n        type: 'top',\n        offset: (anchorRect?.top ?? 0) - scrollRect.top\n      };\n      if (anchor.offset > scrollRect.height / 2) {\n        anchor.type = 'bottom';\n        anchor.offset = (anchorRect?.bottom ?? 0) - scrollRect.bottom;\n      }\n    }\n\n    // Always reset the overlay's previous max height if not defined by the user so that we can compensate for\n    // RAC collections populating after a second render and properly set a correct max height + positioning when it populates.\n    let overlay = (overlayRef.current as HTMLElement);\n    if (!maxHeight && overlayRef.current) {\n      overlay.style.top = '0px';\n      overlay.style.bottom = '';\n      overlay.style.maxHeight = (window.visualViewport?.height ?? window.innerHeight) + 'px';\n    }\n\n    let position = calculatePosition({\n      placement: translateRTL(placement, direction),\n      overlayNode: overlayRef.current,\n      targetNode: targetRef.current,\n      scrollNode: scrollRef.current || overlayRef.current,\n      padding: containerPadding,\n      shouldFlip,\n      boundaryElement,\n      offset,\n      crossOffset,\n      maxHeight,\n      arrowSize: arrowSize ?? (arrowRef?.current ? getRect(arrowRef.current, true).width : 0),\n      arrowBoundaryOffset\n    });\n\n    if (!position.position) {\n      return;\n    }\n\n    // Modify overlay styles directly so positioning happens immediately without the need of a second render\n    // This is so we don't have to delay autoFocus scrolling or delay applying preventScroll for popovers\n    overlay.style.top = '';\n    overlay.style.bottom = '';\n    overlay.style.left = '';\n    overlay.style.right = '';\n\n    Object.keys(position.position).forEach(key => overlay.style[key] = (position.position!)[key] + 'px');\n    overlay.style.maxHeight = position.maxHeight != null ?  position.maxHeight + 'px' : '';\n\n    // Restore scroll position relative to anchor element.\n    let activeElement = getActiveElement();\n    if (anchor && activeElement && scrollRef.current) {\n      let anchorRect = activeElement.getBoundingClientRect();\n      let scrollRect = scrollRef.current.getBoundingClientRect();\n      let newOffset = anchorRect[anchor.type] - scrollRect[anchor.type];\n      scrollRef.current.scrollTop += newOffset - anchor.offset;\n    }\n\n    // Trigger a set state for a second render anyway for arrow positioning\n    setPosition(position);\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, deps);\n\n  // Update position when anything changes\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  useLayoutEffect(updatePosition, deps);\n\n  // Update position on window resize\n  useResize(updatePosition);\n\n  // Update position when the overlay changes size (might need to flip).\n  useResizeObserver({\n    ref: overlayRef,\n    onResize: updatePosition\n  });\n\n  // Update position when the target changes size (might need to flip).\n  useResizeObserver({\n    ref: targetRef,\n    onResize: updatePosition\n  });\n\n  // Reposition the overlay and do not close on scroll while the visual viewport is resizing.\n  // This will ensure that overlays adjust their positioning when the iOS virtual keyboard appears.\n  let isResizing = useRef(false);\n  useLayoutEffect(() => {\n    let timeout: ReturnType<typeof setTimeout>;\n    let onResize = () => {\n      isResizing.current = true;\n      clearTimeout(timeout);\n\n      timeout = setTimeout(() => {\n        isResizing.current = false;\n      }, 500);\n\n      updatePosition();\n    };\n\n    // Only reposition the overlay if a scroll event happens immediately as a result of resize (aka the virtual keyboard has appears)\n    // We don't want to reposition the overlay if the user has pinch zoomed in and is scrolling the viewport around.\n    let onScroll = () => {\n      if (isResizing.current) {\n        onResize();\n      }\n    };\n\n    visualViewport?.addEventListener('resize', onResize);\n    visualViewport?.addEventListener('scroll', onScroll);\n    return () => {\n      visualViewport?.removeEventListener('resize', onResize);\n      visualViewport?.removeEventListener('scroll', onScroll);\n    };\n  }, [updatePosition]);\n\n  let close = useCallback(() => {\n    if (!isResizing.current) {\n      onClose?.();\n    }\n  }, [onClose, isResizing]);\n\n  // When scrolling a parent scrollable region of the trigger (other than the body),\n  // we hide the popover. Otherwise, its position would be incorrect.\n  useCloseOnScroll({\n    triggerRef: targetRef,\n    isOpen,\n    onClose: onClose && close\n  });\n\n  return {\n    overlayProps: {\n      style: {\n        position: position ? 'absolute' : 'fixed',\n        top: !position ? 0 : undefined,\n        left: !position ? 0 : undefined,\n        zIndex: 100000, // should match the z-index in ModalTrigger\n        ...position?.position,\n        maxHeight: position?.maxHeight ?? '100vh'\n      }\n    },\n    placement: position?.placement ?? null,\n    triggerAnchorPoint: position?.triggerAnchorPoint ?? null,\n    arrowProps: {\n      'aria-hidden': 'true',\n      role: 'presentation',\n      style: {\n        left: position?.arrowOffsetLeft,\n        top: position?.arrowOffsetTop\n      }\n    },\n    updatePosition\n  };\n}\n\nfunction useResize(onResize) {\n  useLayoutEffect(() => {\n    window.addEventListener('resize', onResize, false);\n    return () => {\n      window.removeEventListener('resize', onResize, false);\n    };\n  }, [onResize]);\n}\n\nfunction translateRTL(position, direction) {\n  if (direction === 'rtl') {\n    return position.replace('start', 'right').replace('end', 'left');\n  }\n  return position.replace('start', 'left').replace('end', 'right');\n}\n"],"names":[],"version":3,"file":"useOverlayPosition.cjs.map"}