@atlaskit/modal-dialog
Version:
A modal dialog displays content that requires user interaction, in a layer above the page.
141 lines (138 loc) • 5.55 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _react = require("react");
var _react2 = require("@emotion/react");
var _reactUid = require("react-uid");
var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
var _useAutoFocus = _interopRequireDefault(require("@atlaskit/ds-lib/use-auto-focus"));
var _focusRing = _interopRequireDefault(require("@atlaskit/focus-ring"));
var _fadeIn = _interopRequireDefault(require("@atlaskit/motion/fade-in"));
var _colors = require("@atlaskit/theme/colors");
var _constants = require("../constants");
var _context = require("../context");
var _useOnMotionFinish3 = _interopRequireDefault(require("../hooks/use-on-motion-finish"));
var _utils = require("../utils");
var _positioner = _interopRequireDefault(require("./positioner"));
/** @jsx jsx */
var dialogStyles = (0, _react2.css)({
display: 'flex',
width: '100%',
maxWidth: '100vw',
height: '100%',
minHeight: 0,
maxHeight: '100vh',
// Flex-grow set to 0 to prevent this element from filling its parent flexbox container
flex: '0 1 auto',
flexDirection: 'column',
backgroundColor: "var(--ds-surface-overlay, ".concat(_colors.N0, ")"),
color: _constants.textColor,
pointerEvents: 'auto',
'@media (min-width: 480px)': {
width: 'var(--modal-dialog-width)',
maxWidth: 'inherit',
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage-spacing
marginRight: 'inherit',
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage-spacing
marginLeft: 'inherit',
borderRadius: _constants.borderRadius,
boxShadow: "var(--ds-shadow-overlay, ".concat("0 0 0 1px ".concat(_colors.N30A, ", 0 2px 1px ").concat(_colors.N30A, ", 0 0 20px -6px ").concat(_colors.N60A), ")")
},
/**
* This is to support scrolling if the modal's children are wrapped in
* a form.
*/
// eslint-disable-next-line @repo/internal/styles/no-nested-styles
'& > form:only-child': {
display: 'inherit',
maxHeight: 'inherit',
flexDirection: 'inherit'
}
});
var viewportScrollStyles = (0, _react2.css)({
/**
* This ensures that the element fills the viewport on mobile
* while also allowing it to overflow if its height is larger than
* the viewport.
*/
minHeight: '100vh',
maxHeight: 'none',
'@media (min-width: 480px)': {
minHeight: 'var(--modal-dialog-height)'
}
});
var bodyScrollStyles = (0, _react2.css)({
'@media (min-width: 480px)': {
height: 'var(--modal-dialog-height)',
maxHeight: 'inherit'
}
});
var ModalDialog = function ModalDialog(props) {
var _props$width = props.width,
width = _props$width === void 0 ? 'medium' : _props$width,
_props$shouldScrollIn = props.shouldScrollInViewport,
shouldScrollInViewport = _props$shouldScrollIn === void 0 ? false : _props$shouldScrollIn,
autoFocus = props.autoFocus,
stackIndex = props.stackIndex,
onClose = props.onClose,
onCloseComplete = props.onCloseComplete,
onOpenComplete = props.onOpenComplete,
height = props.height,
children = props.children,
testId = props.testId;
var id = (0, _reactUid.useUID)();
var titleId = "modal-dialog-title-".concat(id);
(0, _useAutoFocus.default)((0, _typeof2.default)(autoFocus) === 'object' ? autoFocus : undefined,
// When a user supplies a ref to focus we enable this hook
(0, _typeof2.default)(autoFocus) === 'object');
var _useOnMotionFinish = (0, _useOnMotionFinish3.default)({
onOpenComplete: onOpenComplete,
onCloseComplete: onCloseComplete
}),
_useOnMotionFinish2 = (0, _slicedToArray2.default)(_useOnMotionFinish, 2),
motionRef = _useOnMotionFinish2[0],
onMotionFinish = _useOnMotionFinish2[1];
var modalDialogContext = (0, _react.useMemo)(function () {
return {
testId: testId,
titleId: titleId,
onClose: onClose
};
}, [testId, titleId, onClose]);
return (0, _react2.jsx)(_positioner.default, {
stackIndex: stackIndex,
shouldScrollInViewport: shouldScrollInViewport,
testId: testId
}, (0, _react2.jsx)(_context.ModalContext.Provider, {
value: modalDialogContext
}, (0, _react2.jsx)(_context.ScrollContext.Provider, {
value: shouldScrollInViewport
}, (0, _react2.jsx)(_fadeIn.default, {
entranceDirection: "bottom",
onFinish: onMotionFinish
}, function (bottomFadeInProps) {
return (0, _react2.jsx)(_focusRing.default, null, (0, _react2.jsx)("section", (0, _extends2.default)({}, bottomFadeInProps, {
ref: (0, _mergeRefs.default)([bottomFadeInProps.ref, motionRef]),
style: {
'--modal-dialog-width': (0, _utils.dialogWidth)(width),
'--modal-dialog-height': (0, _utils.dialogHeight)(height)
},
css: [dialogStyles, shouldScrollInViewport ? viewportScrollStyles : bodyScrollStyles],
role: "dialog",
"aria-labelledby": titleId,
"data-testid": testId,
"data-modal-stack": stackIndex,
tabIndex: -1,
"aria-modal": true
}), children));
}))));
};
// eslint-disable-next-line @repo/internal/react/require-jsdoc
var _default = ModalDialog;
exports.default = _default;