{"mappings":";;;;;;AAAA;;;;;;;;;;CAUC;;;;;AA+CD,MAAM,wCAA+C,EAAE;AAOhD,SAAS,0CAAW,KAAuB,EAAE,GAA8B;IAChF,IAAI,WACF,OAAO,qBACP,iBAAiB,UACjB,MAAM,iBACN,gBAAgB,kCAChB,4BAA4B,qCAC5B,4BAA4B,EAC7B,GAAG;IAEJ,IAAI,qBAAqB,CAAA,GAAA,aAAK,EAA6B;IAE3D,wFAAwF;IACxF,CAAA,GAAA,gBAAQ,EAAE;QACR,IAAI,UAAU,CAAC,sCAAgB,QAAQ,CAAC,MAAM;YAC5C,sCAAgB,IAAI,CAAC;YACrB,OAAO;gBACL,IAAI,QAAQ,sCAAgB,OAAO,CAAC;gBACpC,IAAI,SAAS,GACX,sCAAgB,MAAM,CAAC,OAAO;YAElC;QACF;IACF,GAAG;QAAC;QAAQ;KAAI;IAEhB,4EAA4E;IAC5E,IAAI,SAAS;QACX,IAAI,qCAAe,CAAC,sCAAgB,MAAM,GAAG,EAAE,KAAK,OAAO,SACzD;IAEJ;IAEA,IAAI,yBAAyB,CAAC;QAC5B,MAAM,iBAAiB,qCAAe,CAAC,sCAAgB,MAAM,GAAG,EAAE;QAClE,mBAAmB,OAAO,GAAG;QAC7B,IAAI,CAAC,gCAAgC,6BAA6B,CAAA,GAAA,yCAAa,EAAE,KAC/E;YAAA,IAAI,mBAAmB,KACrB,EAAE,eAAe;QACnB;IAEJ;IAEA,IAAI,oBAAoB,CAAC;QACvB,IAAI,CAAC,gCAAgC,6BAA6B,CAAA,GAAA,yCAAa,EAAE,KAAgB;YAC/F,IAAI,qCAAe,CAAC,sCAAgB,MAAM,GAAG,EAAE,KAAK,KAClD,EAAE,eAAe;YAEnB,IAAI,mBAAmB,OAAO,KAAK,KACjC;QAEJ;QACA,mBAAmB,OAAO,GAAG;IAC/B;IAEA,wBAAwB;IACxB,IAAI,YAAY,CAAC;QACf,IAAI,EAAE,GAAG,KAAK,YAAY,CAAC,6BAA6B,CAAC,EAAE,WAAW,CAAC,WAAW,EAAE;YAClF,EAAE,eAAe;YACjB,EAAE,cAAc;YAChB;QACF;IACF;IAEA,kDAAkD;IAClD,CAAA,GAAA,yCAAiB,EAAE;aAAC;QAAK,mBAAmB,iBAAiB,SAAS,oBAAoB;gCAAW;IAAsB;IAE3H,IAAI,oBAAC,gBAAgB,EAAC,GAAG,CAAA,GAAA,yCAAa,EAAE;QACtC,YAAY,CAAC;QACb,cAAc,CAAC;YACb,gFAAgF;YAChF,8GAA8G;YAC9G,6FAA6F;YAC7F,sDAAsD;YACtD,sDAAsD;YACtD,EAAE;YACF,2EAA2E;YAC3E,yEAAyE;YACzE,kEAAkE;YAClE,IAAI,CAAC,EAAE,aAAa,IAAI,CAAA,GAAA,yCAA4B,EAAE,EAAE,aAAa,GACnE;YAGF,IAAI,CAAC,gCAAgC,6BAA6B,EAAE,aAAa,GAC/E;QAEJ;IACF;IAEA,OAAO;QACL,cAAc;uBACZ;YACA,GAAG,gBAAgB;QACrB;QACA,eAAe,CAAC;IAClB;AACF","sources":["packages/react-aria/src/overlays/useOverlay.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 {DOMAttributes, RefObject} from '@react-types/shared';\nimport {getEventTarget} from '../utils/shadowdom/DOMFunctions';\nimport {isElementInChildOfActiveScope} from '../focus/FocusScope';\nimport {useEffect, useRef} from 'react';\nimport {useFocusWithin} from '../interactions/useFocusWithin';\nimport {useInteractOutside} from '../interactions/useInteractOutside';\n\nexport interface AriaOverlayProps {\n  /** Whether the overlay is currently open. */\n  isOpen?: boolean,\n\n  /** Handler that is called when the overlay should close. */\n  onClose?: () => void,\n\n  /**\n   * Whether to close the overlay when the user interacts outside it.\n   * @default false\n   */\n  isDismissable?: boolean,\n\n  /** Whether the overlay should close when focus is lost or moves outside it. */\n  shouldCloseOnBlur?: boolean,\n\n  /**\n   * Whether pressing the escape key to close the overlay should be disabled.\n   * @default false\n   */\n  isKeyboardDismissDisabled?: boolean,\n\n  /**\n   * When user interacts with the argument element outside of the overlay ref,\n   * return true if onClose should be called.  This gives you a chance to filter\n   * out interaction with elements that should not dismiss the overlay.\n   * By default, onClose will always be called on interaction outside the overlay ref.\n   */\n  shouldCloseOnInteractOutside?: (element: Element) => boolean\n}\n\nexport interface OverlayAria {\n  /** Props to apply to the overlay container element. */\n  overlayProps: DOMAttributes,\n  /** Props to apply to the underlay element, if any. */\n  underlayProps: DOMAttributes\n}\n\nconst visibleOverlays: RefObject<Element | null>[] = [];\n\n/**\n * Provides the behavior for overlays such as dialogs, popovers, and menus.\n * Hides the overlay when the user interacts outside it, when the Escape key is pressed,\n * or optionally, on blur. Only the top-most overlay will close at once.\n */\nexport function useOverlay(props: AriaOverlayProps, ref: RefObject<Element | null>): OverlayAria {\n  let {\n    onClose,\n    shouldCloseOnBlur,\n    isOpen,\n    isDismissable = false,\n    isKeyboardDismissDisabled = false,\n    shouldCloseOnInteractOutside\n  } = props;\n\n  let lastVisibleOverlay = useRef<RefObject<Element | null>>(undefined);\n\n  // Add the overlay ref to the stack of visible overlays on mount, and remove on unmount.\n  useEffect(() => {\n    if (isOpen && !visibleOverlays.includes(ref)) {\n      visibleOverlays.push(ref);\n      return () => {\n        let index = visibleOverlays.indexOf(ref);\n        if (index >= 0) {\n          visibleOverlays.splice(index, 1);\n        }\n      };\n    }\n  }, [isOpen, ref]);\n\n  // Only hide the overlay when it is the topmost visible overlay in the stack\n  let onHide = () => {\n    if (visibleOverlays[visibleOverlays.length - 1] === ref && onClose) {\n      onClose();\n    }\n  };\n\n  let onInteractOutsideStart = (e: PointerEvent) => {\n    const topMostOverlay = visibleOverlays[visibleOverlays.length - 1];\n    lastVisibleOverlay.current = topMostOverlay;\n    if (!shouldCloseOnInteractOutside || shouldCloseOnInteractOutside(getEventTarget(e) as Element)) {\n      if (topMostOverlay === ref) {\n        e.stopPropagation();\n      }\n    }\n  };\n\n  let onInteractOutside = (e: PointerEvent) => {\n    if (!shouldCloseOnInteractOutside || shouldCloseOnInteractOutside(getEventTarget(e) as Element)) {\n      if (visibleOverlays[visibleOverlays.length - 1] === ref) {\n        e.stopPropagation();\n      }\n      if (lastVisibleOverlay.current === ref) {\n        onHide();\n      }\n    }\n    lastVisibleOverlay.current = undefined;\n  };\n\n  // Handle the escape key\n  let onKeyDown = (e) => {\n    if (e.key === 'Escape' && !isKeyboardDismissDisabled && !e.nativeEvent.isComposing) {\n      e.stopPropagation();\n      e.preventDefault();\n      onHide();\n    }\n  };\n\n  // Handle clicking outside the overlay to close it\n  useInteractOutside({ref, onInteractOutside: isDismissable && isOpen ? onInteractOutside : undefined, onInteractOutsideStart});\n\n  let {focusWithinProps} = useFocusWithin({\n    isDisabled: !shouldCloseOnBlur,\n    onBlurWithin: (e) => {\n      // Do not close if relatedTarget is null, which means focus is lost to the body.\n      // That can happen when switching tabs, or due to a VoiceOver/Chrome bug with Control+Option+Arrow navigation.\n      // Clicking on the body to close the overlay should already be handled by useInteractOutside.\n      // https://github.com/adobe/react-spectrum/issues/4130\n      // https://github.com/adobe/react-spectrum/issues/4922\n      //\n      // If focus is moving into a child focus scope (e.g. menu inside a dialog),\n      // do not close the outer overlay. At this point, the active scope should\n      // still be the outer overlay, since blur events run before focus.\n      if (!e.relatedTarget || isElementInChildOfActiveScope(e.relatedTarget)) {\n        return;\n      }\n\n      if (!shouldCloseOnInteractOutside || shouldCloseOnInteractOutside(e.relatedTarget as Element)) {\n        onClose?.();\n      }\n    }\n  });\n\n  return {\n    overlayProps: {\n      onKeyDown,\n      ...focusWithinProps\n    },\n    underlayProps: {}\n  };\n}\n"],"names":[],"version":3,"file":"useOverlay.mjs.map"}