UNPKG

@codegouvfr/react-dsfr

Version:

French State Design System React integration library

93 lines 4.42 kB
"use client"; import { useEffect, useState } from "react"; import { assert } from "tsafe/assert"; import { symToStr } from "tsafe/symToStr"; import { useConstCallback } from "../tools/powerhooks/useConstCallback"; export function useIsModalOpen(modal, callbacks) { const { id, isOpenedByDefault } = modal; const [isModalOpen, setIsModalOpen] = useState(isOpenedByDefault); const getCurrentCallbacks = useConstCallback(() => callbacks); useEffect(() => { const cleanups = []; const observeDialogHtmlElement = (element) => { const onConceal = () => { setIsModalOpen(false); setTimeout(() => { var _a, _b; (_b = (_a = getCurrentCallbacks()) === null || _a === void 0 ? void 0 : _a.onConceal) === null || _b === void 0 ? void 0 : _b.call(_a); }, 0); }; const onDisclose = () => { var _a, _b; setIsModalOpen(true); (_b = (_a = getCurrentCallbacks()) === null || _a === void 0 ? void 0 : _a.onDisclose) === null || _b === void 0 ? void 0 : _b.call(_a); }; element.addEventListener("dsfr.conceal", onConceal); element.addEventListener("dsfr.disclose", onDisclose); const removeEventListeners = () => { element.removeEventListener("dsfr.conceal", onConceal); element.removeEventListener("dsfr.disclose", onDisclose); }; cleanups.push(removeEventListeners); const observer = new MutationObserver(mutationsList => { const isDetached = mutationsList.find(mutation => Array.from(mutation.removedNodes).indexOf(element) !== -1) !== undefined; if (!isDetached) { return; } cleanups.splice(cleanups.indexOf(removeEventListeners), 1); observer.disconnect(); cleanups.splice(cleanups.indexOf(disconnectObserver), 1); setIsModalOpen(false); observeMountAndObserveDialogHtmlElement({ "isInitialCall": false }); }); observer.observe(document, { childList: true, subtree: true }); const disconnectObserver = () => observer.disconnect(); cleanups.push(disconnectObserver); }; const observeMountAndObserveDialogHtmlElement = (params) => { const { isInitialCall } = params; if (isInitialCall) { assert(!isOpenedByDefault, [ `The ${id} modal isn't initially mounted,`, `it's ok but in this case ${symToStr({ isOpenedByDefault })} must be set to false.`, "This limitation is to prevent inconsistent state in SSR setups." ].join(" ")); } const observer = new MutationObserver((mutationsList, observer) => { // Filter the mutations list for nodes that match our criteria const matchedNode = mutationsList .map(mutation => Array.from(mutation.addedNodes)) .reduce((acc, curr) => acc.concat(curr), []) .find(node => node.nodeType === Node.ELEMENT_NODE && node.nodeName === "DIALOG" && node.id === id); if (matchedNode === undefined) { return; } observer.disconnect(); cleanups.splice(cleanups.indexOf(disconnectObserver), 1); observeDialogHtmlElement(matchedNode); if (isOpenedByDefault) { setIsModalOpen(true); } }); observer.observe(document, { "childList": true, "subtree": true }); const disconnectObserver = () => observer.disconnect(); cleanups.push(disconnectObserver); }; const element = document.getElementById(id); if (element !== null) { observeDialogHtmlElement(element); } else { observeMountAndObserveDialogHtmlElement({ "isInitialCall": true }); } return () => { cleanups.forEach(cleanup => cleanup()); }; }, [id]); return isModalOpen; } //# sourceMappingURL=useIsModalOpen.js.map