{"mappings":";;;;;AAAA;;;;;;;;;;CAUC;;;;AAmBD,MAAM,8CAAU,CAAA,GAAA,YAAI,EAAE,aAAa,CAAsB;AAUlD,SAAS,yCAAc,KAAyB;IACrD,IAAI,YAAC,QAAQ,EAAC,GAAG;IACjB,IAAI,SAAS,CAAA,GAAA,iBAAS,EAAE;IACxB,IAAI,CAAC,YAAY,cAAc,GAAG,CAAA,GAAA,eAAO,EAAE;IAC3C,IAAI,UAAU,CAAA,GAAA,cAAM,EAAE,IAAO,CAAA;oBAC3B;wBACA;YACA;gBACE,cAAc,CAAA,QAAS,QAAQ;gBAC/B,IAAI,QACF,OAAO,QAAQ;YAEnB;YACA;gBACE,cAAc,CAAA,QAAS,QAAQ;gBAC/B,IAAI,QACF,OAAO,WAAW;YAEtB;QACF,CAAA,GAAI;QAAC;QAAQ;KAAW;IAExB,qBACE,gCAAC,8BAAQ,QAAQ;QAAC,OAAO;OACtB;AAGP;AAaO,SAAS;IACd,IAAI,UAAU,CAAA,GAAA,iBAAS,EAAE;IACzB,OAAO;QACL,oBAAoB;YAClB,eAAe,WAAW,QAAQ,UAAU,GAAG,IAAI,OAAO;QAC5D;IACF;AACF;AAEA;;CAEC,GACD,SAAS,0CAAoB,KAAyB;IACpD,IAAI,sBAAC,kBAAkB,EAAC,GAAG;IAC3B,qBAAO,gCAAC;QAAI,0BAAA;QAAwB,GAAG,KAAK;QAAG,GAAG,kBAAkB;;AACtE;AAUO,SAAS,0CAAgB,KAAyB;IACvD,qBACE,gCAAC,8DACC,gCAAC,2CAAwB;AAG/B;AAkBO,SAAS,0CAAiB,KAA4B;IAC3D,IAAI,QAAQ,CAAA,GAAA,yCAAO;IACnB,IAAI,mBAAC,kBAAkB,QAAQ,OAAO,SAAS,IAAI,EAAE,GAAG,MAAK,GAAG;IAChE,IAAI,gBAAC,YAAY,EAAC,GAAG,CAAA,GAAA,yCAAsB;IAC3C,IAAI,CAAC,MAAM,eAAe,IAAI,cAC5B,kBAAkB;IAGpB,CAAA,GAAA,YAAI,EAAE,SAAS,CAAC;QACd,IAAI,iBAAiB,QAAQ,6BAC3B,MAAM,IAAI,MAAM;IAEpB,GAAG;QAAC;KAAgB;IAEpB,IAAI,CAAC,iBACH,OAAO;IAGT,IAAI,yBAAW,gCAAC,2CAAoB;IACpC,qBAAO,CAAA,GAAA,eAAO,EAAE,YAAY,CAAC,UAAU;AACzC;AAsBO,SAAS,0CAAS,OAA0B;IACjD,4EAA4E;IAC5E,IAAI,UAAU,CAAA,GAAA,iBAAS,EAAE;IACzB,IAAI,CAAC,SACH,MAAM,IAAI,MAAM;IAGlB,CAAA,GAAA,gBAAQ,EAAE;QACR,IAAI,SAAS,cAAc,CAAC,WAAW,CAAC,QAAQ,MAAM,EACpD;QAGF,+EAA+E;QAC/E,+EAA+E;QAC/E,QAAQ,MAAM,CAAC,QAAQ;QACvB,OAAO;YACL,IAAI,WAAW,QAAQ,MAAM,EAC3B,QAAQ,MAAM,CAAC,WAAW;QAE9B;IACF,GAAG;QAAC;QAAS,QAAQ,MAAM;QAAE,SAAS;KAAW;IAEjD,OAAO;QACL,YAAY;YACV,gBAAgB,CAAC,SAAS;QAC5B;IACF;AACF","sources":["packages/react-aria/src/overlays/useModal.tsx"],"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} from '@react-types/shared';\nimport React, {AriaAttributes, JSX, ReactNode, useContext, useEffect, useMemo, useState} from 'react';\nimport ReactDOM from 'react-dom';\nimport {useIsSSR} from '../ssr/SSRProvider';\nimport {useUNSAFE_PortalContext} from './PortalProvider';\n\nexport interface ModalProviderProps extends DOMAttributes {\n  children: ReactNode\n}\n\ninterface ModalContext {\n  parent: ModalContext | null,\n  modalCount: number,\n  addModal: () => void,\n  removeModal: () => void\n}\n\nconst Context = React.createContext<ModalContext | null>(null);\n\n/**\n * Each ModalProvider tracks how many modals are open in its subtree. On mount, the modals\n * trigger `addModal` to increment the count, and trigger `removeModal` on unmount to decrement it.\n * This is done recursively so that all parent providers are incremented and decremented.\n * If the modal count is greater than zero, we add `aria-hidden` to this provider to hide its\n * subtree from screen readers. This is done using React context in order to account for things\n * like portals, which can cause the React tree and the DOM tree to differ significantly in structure.\n */\nexport function ModalProvider(props: ModalProviderProps): JSX.Element {\n  let {children} = props;\n  let parent = useContext(Context);\n  let [modalCount, setModalCount] = useState(0);\n  let context = useMemo(() => ({\n    parent,\n    modalCount,\n    addModal() {\n      setModalCount(count => count + 1);\n      if (parent) {\n        parent.addModal();\n      }\n    },\n    removeModal() {\n      setModalCount(count => count - 1);\n      if (parent) {\n        parent.removeModal();\n      }\n    }\n  }), [parent, modalCount]);\n\n  return (\n    <Context.Provider value={context}>\n      {children}\n    </Context.Provider>\n  );\n}\n\nexport interface ModalProviderAria {\n  /**\n   * Props to be spread on the container element.\n   */\n  modalProviderProps: AriaAttributes\n}\n\n/**\n * Used to determine if the tree should be aria-hidden based on how many\n * modals are open.\n */\nexport function useModalProvider(): ModalProviderAria {\n  let context = useContext(Context);\n  return {\n    modalProviderProps: {\n      'aria-hidden': context && context.modalCount > 0 ? true : undefined\n    }\n  };\n}\n\n/**\n * Creates a root node that will be aria-hidden if there are other modals open.\n */\nfunction OverlayContainerDOM(props: ModalProviderProps) {\n  let {modalProviderProps} = useModalProvider();\n  return <div data-overlay-container {...props} {...modalProviderProps} />;\n}\n\n/**\n * An OverlayProvider acts as a container for the top-level application.\n * Any application that uses modal dialogs or other overlays should\n * be wrapped in a `<OverlayProvider>`. This is used to ensure that\n * the main content of the application is hidden from screen readers\n * if a modal or other overlay is opened. Only the top-most modal or\n * overlay should be accessible at once.\n */\nexport function OverlayProvider(props: ModalProviderProps): JSX.Element {\n  return (\n    <ModalProvider>\n      <OverlayContainerDOM {...props} />\n    </ModalProvider>\n  );\n}\n\nexport interface OverlayContainerProps extends ModalProviderProps {\n  /**\n   * The container element in which the overlay portal will be placed.\n   * @default document.body\n   * @deprecated - Use a parent UNSAFE_PortalProvider to set your portal container instead.\n   */\n  portalContainer?: Element\n}\n\n/**\n * A container for overlays like modals and popovers. Renders the overlay\n * into a Portal which is placed at the end of the document body.\n * Also ensures that the overlay is hidden from screen readers if a\n * nested modal is opened. Only the top-most modal or overlay should\n * be accessible at once.\n */\nexport function OverlayContainer(props: OverlayContainerProps): React.ReactPortal | null {\n  let isSSR = useIsSSR();\n  let {portalContainer = isSSR ? null : document.body, ...rest} = props;\n  let {getContainer} = useUNSAFE_PortalContext();\n  if (!props.portalContainer && getContainer) {\n    portalContainer = getContainer();\n  }\n\n  React.useEffect(() => {\n    if (portalContainer?.closest('[data-overlay-container]')) {\n      throw new Error('An OverlayContainer must not be inside another container. Please change the portalContainer prop.');\n    }\n  }, [portalContainer]);\n\n  if (!portalContainer) {\n    return null;\n  }\n\n  let contents = <OverlayProvider {...rest} />;\n  return ReactDOM.createPortal(contents, portalContainer);\n}\n\ninterface ModalAriaProps extends DOMAttributes {\n  /** Data attribute marks the dom node as a modal for the aria-modal-polyfill. */\n  'data-ismodal': boolean\n}\n\nexport interface AriaModalOptions {\n  isDisabled?: boolean\n}\n\nexport interface ModalAria {\n  /** Props for the modal content element. */\n  modalProps: ModalAriaProps\n}\n\n/**\n * Hides content outside the current `<OverlayContainer>` from screen readers\n * on mount and restores it on unmount. Typically used by modal dialogs and\n * other types of overlays to ensure that only the top-most modal is\n * accessible at once.\n */\nexport function useModal(options?: AriaModalOptions): ModalAria {\n  // Add aria-hidden to all parent providers on mount, and restore on unmount.\n  let context = useContext(Context);\n  if (!context) {\n    throw new Error('Modal is not contained within a provider');\n  }\n\n  useEffect(() => {\n    if (options?.isDisabled || !context || !context.parent) {\n      return;\n    }\n\n    // The immediate context is from the provider containing this modal, so we only\n    // want to trigger aria-hidden on its parents not on the modal provider itself.\n    context.parent.addModal();\n    return () => {\n      if (context && context.parent) {\n        context.parent.removeModal();\n      }\n    };\n  }, [context, context.parent, options?.isDisabled]);\n\n  return {\n    modalProps: {\n      'data-ismodal': !options?.isDisabled\n    }\n  };\n}\n"],"names":[],"version":3,"file":"useModal.mjs.map"}