UNPKG

@robotical/sensors-dashboard

Version:

A dashboard tool for depicting Marty data by Robotical

184 lines (183 loc) 8.22 kB
"use strict"; require("core-js/modules/es.weak-map.js"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; require("core-js/modules/esnext.iterator.constructor.js"); require("core-js/modules/esnext.iterator.filter.js"); require("core-js/modules/web.dom-collections.iterator.js"); var _react = _interopRequireWildcard(require("react")); var _reactDom = _interopRequireDefault(require("react-dom")); var _Logo = _interopRequireDefault(require("../Logo")); var _ModalState = _interopRequireDefault(require("../../state-observables/modal/ModalState")); var _stylesModule = _interopRequireDefault(require("./styles.module.css")); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } const FOCUSABLE_ELEMENTS = ["a[href]", "area[href]", "button:not([disabled])", "input:not([disabled]):not([type='hidden'])", "select:not([disabled])", "textarea:not([disabled])", "summary", "[contenteditable='true']", "[tabindex]:not([tabindex='-1'])"].join(","); const getFocusableElements = container => Array.from(container.querySelectorAll(FOCUSABLE_ELEMENTS)).filter(element => element.tabIndex >= 0 && !element.hidden && element.getAttribute("aria-hidden") !== "true"); function Modal(_ref) { let { children, title, shouldCloseModal, withLogo, modalResetter } = _ref; const [isBrowser, setIsBrowser] = (0, _react.useState)(false); const [closing, setClosing] = (0, _react.useState)(false); const [showModal, setShowModal] = (0, _react.useState)(true); const dialogRef = (0, _react.useRef)(null); const previouslyFocusedElementRef = (0, _react.useRef)(null); const closeTimerRef = (0, _react.useRef)(null); const focusRestoreTimerRef = (0, _react.useRef)(null); const closingRef = (0, _react.useRef)(false); const hasRestoredFocusRef = (0, _react.useRef)(false); const generatedId = (0, _react.useId)(); const titleId = "".concat(generatedId, "-title"); const scheduleFocusRestoration = (0, _react.useCallback)(() => { if (hasRestoredFocusRef.current) { return; } hasRestoredFocusRef.current = true; const previouslyFocusedElement = previouslyFocusedElementRef.current; focusRestoreTimerRef.current = window.setTimeout(() => { focusRestoreTimerRef.current = null; if (previouslyFocusedElement !== null && previouslyFocusedElement !== void 0 && previouslyFocusedElement.isConnected) { previouslyFocusedElement.focus({ preventScroll: true }); } }, 0); }, []); const closeModalHandler = (0, _react.useCallback)(() => { if (closingRef.current) { return; } closingRef.current = true; setClosing(true); const prefersReducedMotion = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches; closeTimerRef.current = window.setTimeout(() => { setShowModal(false); modalResetter(); closeTimerRef.current = null; }, prefersReducedMotion ? 0 : 700); }, [modalResetter]); (0, _react.useEffect)(() => { if (focusRestoreTimerRef.current !== null) { window.clearTimeout(focusRestoreTimerRef.current); focusRestoreTimerRef.current = null; } hasRestoredFocusRef.current = false; previouslyFocusedElementRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null; setIsBrowser(true); return () => { if (closeTimerRef.current !== null) { window.clearTimeout(closeTimerRef.current); } scheduleFocusRestoration(); }; }, [scheduleFocusRestoration]); (0, _react.useEffect)(() => { if (showModal) { window.scrollTo({ top: 0 }); const previousBodyOverflow = document.body.style.overflow; document.body.style.overflow = "hidden"; return () => { document.body.style.overflow = previousBodyOverflow; }; } return undefined; }, [showModal]); (0, _react.useEffect)(() => { if (shouldCloseModal) { closeModalHandler(); } }, [shouldCloseModal, closeModalHandler]); (0, _react.useEffect)(() => { if (!isBrowser || !showModal) { return undefined; } const dialog = dialogRef.current; if (!dialog) { return undefined; } const initialFocusTarget = dialog.querySelector("[data-modal-initial-focus]") || getFocusableElements(dialog)[0] || dialog; initialFocusTarget.focus(); const handleKeyDown = event => { if (event.key === "Escape") { if (!closingRef.current) { event.preventDefault(); event.stopPropagation(); _ModalState.default.closeModal(); } return; } if (event.key !== "Tab") { return; } const focusableElements = getFocusableElements(dialog); if (focusableElements.length === 0) { event.preventDefault(); dialog.focus(); return; } const firstFocusableElement = focusableElements[0]; const lastFocusableElement = focusableElements[focusableElements.length - 1]; const activeElement = document.activeElement; if (event.shiftKey && (activeElement === firstFocusableElement || activeElement === dialog)) { event.preventDefault(); lastFocusableElement.focus(); } else if (!event.shiftKey && activeElement === lastFocusableElement) { event.preventDefault(); firstFocusableElement.focus(); } else if (!dialog.contains(activeElement)) { event.preventDefault(); (event.shiftKey ? lastFocusableElement : firstFocusableElement).focus(); } }; document.addEventListener("keydown", handleKeyDown, true); return () => { document.removeEventListener("keydown", handleKeyDown, true); }; }, [isBrowser, showModal]); const modalContent = showModal ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: _stylesModule.default.styledModalOverlay, children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", { ref: dialogRef, role: "dialog", "aria-modal": "true", "aria-labelledby": title ? titleId : undefined, "aria-label": title ? undefined : "Dialog", tabIndex: -1, className: [_stylesModule.default.styledModal, closing ? _stylesModule.default.styleModalLeaveToTop : _stylesModule.default.styleModalComeInFromTop].join(" "), children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: _stylesModule.default.styledModalHeader }), withLogo && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: _stylesModule.default.modalLogoContainer, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Logo.default, {}) }), title && /*#__PURE__*/(0, _jsxRuntime.jsx)("h2", { id: titleId, className: _stylesModule.default.styledTitle, children: title }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: _stylesModule.default.styledModalBody, children: children })] }) }) : null; if (isBrowser && showModal) { const portalTarget = document.getElementById("sensors-dashboard-modal-main-container"); if (!portalTarget) { return null; } return /*#__PURE__*/_reactDom.default.createPortal(modalContent, portalTarget); } else { return null; } } var _default = exports.default = Modal;