UNPKG

@atlaskit/modal-dialog

Version:

A modal dialog displays content that requires user interaction, in a layer above the page.

119 lines (116 loc) 4.86 kB
import _extends from "@babel/runtime/helpers/extends"; /** @jsx jsx */ import { useCallback } from 'react'; import { css, jsx } from '@emotion/react'; import FocusLock from 'react-focus-lock'; import ScrollLock, { TouchScrollable } from 'react-scrolllock'; import { usePlatformLeafEventHandler } from '@atlaskit/analytics-next'; import Blanket from '@atlaskit/blanket'; import noop from '@atlaskit/ds-lib/noop'; import useCloseOnEscapePress from '@atlaskit/ds-lib/use-close-on-escape-press'; import FadeIn from '@atlaskit/motion/fade-in'; import Portal from '@atlaskit/portal'; import { layers } from '@atlaskit/theme/constants'; import ModalDialog from './internal/components/modal-dialog'; import useModalStack from './internal/hooks/use-modal-stack'; import usePreventProgrammaticScroll from './internal/hooks/use-prevent-programmatic-scroll'; var fillScreenStyles = css({ width: '100vw', height: '100vh', position: 'fixed', // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage-spacing top: 0, // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage-spacing left: 0, overflowY: 'auto', WebkitOverflowScrolling: 'touch' }); var whiteListElements = function whiteListElements(element) { // allows focus to reach elements outside the modal if they contain the data-atlas-extension attribute return !element.hasAttribute('data-atlas-extension'); }; /** * __Modal wrapper__ * * A modal wrapper displays content that requires user interaction, in a layer above the page. * This component is primary container for other modal components. * * - [Examples](https://atlassian.design/components/modal-dialog/examples) * - [Code](https://atlassian.design/components/modal-dialog/code) * - [Usage](https://atlassian.design/components/modal-dialog/usage) */ var ModalWrapper = function ModalWrapper(props) { var _props$autoFocus = props.autoFocus, autoFocus = _props$autoFocus === void 0 ? true : _props$autoFocus, _props$shouldCloseOnE = props.shouldCloseOnEscapePress, shouldCloseOnEscapePress = _props$shouldCloseOnE === void 0 ? true : _props$shouldCloseOnE, _props$shouldCloseOnO = props.shouldCloseOnOverlayClick, shouldCloseOnOverlayClick = _props$shouldCloseOnO === void 0 ? true : _props$shouldCloseOnO, _props$shouldScrollIn = props.shouldScrollInViewport, shouldScrollInViewport = _props$shouldScrollIn === void 0 ? false : _props$shouldScrollIn, stackIndexOverride = props.stackIndex, _props$onClose = props.onClose, onClose = _props$onClose === void 0 ? noop : _props$onClose, _props$onStackChange = props.onStackChange, onStackChange = _props$onStackChange === void 0 ? noop : _props$onStackChange, isBlanketHidden = props.isBlanketHidden, children = props.children, height = props.height, width = props.width, onCloseComplete = props.onCloseComplete, onOpenComplete = props.onOpenComplete, testId = props.testId; var calculatedStackIndex = useModalStack({ onStackChange: onStackChange }); var stackIndex = stackIndexOverride || calculatedStackIndex; var isForeground = stackIndex === 0; // When a user supplies a ref to focus we skip auto focus via react-focus-lock var autoFocusLock = typeof autoFocus === 'boolean' ? autoFocus : false; var onCloseHandler = usePlatformLeafEventHandler({ fn: onClose, action: 'closed', componentName: 'modalDialog', packageName: "@atlaskit/modal-dialog", packageVersion: "12.4.12" }); var onBlanketClicked = useCallback(function (e) { if (shouldCloseOnOverlayClick) { onCloseHandler(e); } }, [shouldCloseOnOverlayClick, onCloseHandler]); usePreventProgrammaticScroll(); useCloseOnEscapePress({ onClose: onCloseHandler, isDisabled: !shouldCloseOnEscapePress || !isForeground }); var modalDialogWithBlanket = jsx(Blanket, { isTinted: !isBlanketHidden, onBlanketClicked: onBlanketClicked, testId: testId && "".concat(testId, "--blanket") }, jsx(ModalDialog, { testId: testId, autoFocus: autoFocus, stackIndex: stackIndex, onClose: onCloseHandler, shouldScrollInViewport: shouldScrollInViewport, height: height, width: width, onCloseComplete: onCloseComplete, onOpenComplete: onOpenComplete }, children)); return jsx(Portal, { zIndex: layers.modal() }, jsx(FadeIn, null, function (fadeInProps) { return jsx("div", _extends({}, fadeInProps, { css: fillScreenStyles, "aria-hidden": !isForeground }), jsx(FocusLock, { autoFocus: autoFocusLock, disabled: !isForeground, returnFocus: true, whiteList: whiteListElements }, jsx(ScrollLock, null), shouldScrollInViewport ? jsx(TouchScrollable, null, modalDialogWithBlanket) : modalDialogWithBlanket)); })); }; export default ModalWrapper;