UNPKG

nishant-design-system

Version:
197 lines (191 loc) 7.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ModalHeader = exports.ModalFooter = exports.ModalBody = exports.Modal = void 0; var React = _interopRequireWildcard(require("react")); var _reactDom = require("react-dom"); var _reactDomInteractions = require("@floating-ui/react-dom-interactions"); var _useMountTransition = _interopRequireDefault(require("../../hooks/useMountTransition")); var _motion = require("../../styles/variables/_motion"); var _classify = _interopRequireDefault(require("../../utils/classify")); var _helpers = require("../../utils/helpers"); var _Button = require("../Button/Button"); var _Truncate = require("../Truncate/Truncate"); var _ModalModule = _interopRequireDefault(require("./Modal.module.css")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } // $FlowFixMe[untyped-import] const ModalHeader = _ref => { let { children, hideCloseBtn, onCloseButtonClick, className } = _ref; return /*#__PURE__*/React.createElement(React.Fragment, null, React.Children.count(children) > 0 && /*#__PURE__*/React.createElement("div", { className: (0, _classify.default)(_ModalModule.default.modalHeader, className) }, /*#__PURE__*/React.createElement("div", { className: _ModalModule.default.headerContent }, /*#__PURE__*/React.createElement(_Truncate.Truncate, null, children)), !hideCloseBtn && /*#__PURE__*/React.createElement(_Button.Button, { iconLeftName: "xmark", type: "ghost", onClick: onCloseButtonClick, ariaLabel: "Close Button" }))); }; exports.ModalHeader = ModalHeader; const ModalBody = _ref2 => { let { children, className } = _ref2; return /*#__PURE__*/React.createElement("div", { className: (0, _classify.default)(_ModalModule.default.modalBody, className) }, children); }; exports.ModalBody = ModalBody; const ModalFooter = _ref3 => { let { children, classNames } = _ref3; return /*#__PURE__*/React.createElement(React.Fragment, null, React.Children.count(children) > 0 && /*#__PURE__*/React.createElement("div", { className: (0, _classify.default)(_ModalModule.default.modalFooter, classNames?.wrapper) }, /*#__PURE__*/React.createElement("div", { className: (0, _classify.default)(_ModalModule.default.modalFooterActions, classNames?.actions) }, children))); }; exports.ModalFooter = ModalFooter; const createPortalRoot = id => { const modalRoot = document.createElement('div'); modalRoot.setAttribute('id', `modal-root-${id}`); return modalRoot; }; const getModalRoot = id => document.getElementById(`modal-root-${id}`); function hasChildNode(nodeList) { for (let i = 0, len = nodeList.length; i < len; i++) { if (nodeList[i].firstChild !== null) { return true; } } return false; } const fixBody = bodyEl => { document.getElementsByTagName('body')[0].classList.add('fixed'); bodyEl.style.overflow = 'hidden'; }; const unfixBody = bodyEl => { document.getElementsByTagName('body')[0].classList.remove('fixed'); bodyEl.style.overflow = ''; }; const checkAndAddBodyOverflow = bodyEl => { const nodes = document.querySelectorAll('[id^="modal-root"]'); let isParentModalPresent = false; if (nodes.length) { isParentModalPresent = hasChildNode(nodes); } if (isParentModalPresent) { fixBody(bodyEl); } else { unfixBody(bodyEl); } }; const Modal = _ref4 => { let { classNames, children, isOpen = false, onClose, hideBackdrop = false, tapOutsideToClose = true, initialFocus = -1 } = _ref4; const { floating, context } = (0, _reactDomInteractions.useFloating)(); const modalId = (0, _helpers.uuid)(); const bodyRef = React.useRef(document.querySelector('body')); const portalRootRef = React.useRef(getModalRoot(modalId) || createPortalRoot(modalId)); const isTransitioning = (0, _useMountTransition.default)(isOpen, parseInt(_motion.motionDurationNormal)); // Append portal root on mount React.useEffect(() => { bodyRef.current?.appendChild(portalRootRef.current); const portal = portalRootRef.current; const bodyEl = bodyRef.current; return () => { // Clean up the portal when modal component unmounts portal.remove(); // Ensure scroll overflow is removed if (bodyEl) { unfixBody(bodyEl); } }; }, []); // Prevent page scrolling when the modal is open React.useEffect(() => { const updatePageScroll = () => { if (isOpen) { if (bodyRef.current) { fixBody(bodyRef.current); } } else { if (bodyRef.current) { unfixBody(bodyRef.current); } } }; updatePageScroll(); }, [isOpen]); // Allow Escape key to dismiss the modal React.useEffect(() => { const onKeyPress = e => { if (e.key === 'Escape') { tapOutsideToClose && onClose && onClose(e); } }; if (isOpen) { window.addEventListener('keyup', onKeyPress); } return () => { window.removeEventListener('keyup', onKeyPress); }; }, [isOpen, onClose]); if (!isTransitioning && !isOpen) { // Check overflow after resetting the DOM for modal. This should always happen after DOM reset // TODO(Nishant): Better way to do this? setTimeout(() => { if (bodyRef && !!bodyRef.current) { checkAndAddBodyOverflow(bodyRef.current); } }); return null; } const onBackdropClick = e => { if (tapOutsideToClose && onClose) { onClose(e); } }; return /*#__PURE__*/(0, _reactDom.createPortal)( /*#__PURE__*/React.createElement(_reactDomInteractions.FloatingFocusManager, { context: context, initialFocus: initialFocus }, /*#__PURE__*/React.createElement("div", { ref: floating, "aria-hidden": isOpen ? 'false' : 'true', className: (0, _classify.default)(_ModalModule.default.modalContainer, { [_ModalModule.default.in]: isTransitioning, [_ModalModule.default.open]: isOpen }, classNames?.container) }, /*#__PURE__*/React.createElement("div", { className: (0, _classify.default)(_ModalModule.default.backdrop, { [_ModalModule.default.darkBackdrop]: !hideBackdrop }, classNames?.backdrop), onClick: onBackdropClick }), /*#__PURE__*/React.createElement("div", { className: (0, _classify.default)(_ModalModule.default.modal, classNames?.content), role: "dialog" }, children))), portalRootRef.current); }; exports.Modal = Modal;