@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
JavaScript
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;