@robotical/sensors-dashboard
Version:
A dashboard tool for depicting Marty data by Robotical
184 lines (183 loc) • 8.22 kB
JavaScript
;
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;