UNPKG

@kwiz/fluentui

Version:

KWIZ common controls for FluentUI

79 lines 3.47 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { isNotEmptyArray, isNullOrEmptyString, jsonClone, objectsEqual } from "@kwiz/common"; import { useCallback, useEffect } from "react"; import { Prompter } from "../controls/prompt"; import { useEffectOnlyOnMount, useStateEX } from "./hooks"; /** set block message if you want to block nav. * - call setMessage to add a blocker message * - call onNav when you have internal navigation (open / close popups) * - render the navPrompt control to your page * FYI for page unload, most modern browsers won't show your message but a generic one instead. */ export function useBlockNav() { const [, setBlockNavMessages, blockNavMessagesRef] = useStateEX({}); const [_prompt, setPrompt] = useStateEX(null); const getMessagesArr = useCallback(() => { return Object.keys(blockNavMessagesRef.current).map(id => blockNavMessagesRef.current[id]); }, useEffectOnlyOnMount); const getMessages = useCallback(() => { return getMessagesArr().join(); }, useEffectOnlyOnMount); const onNav = useCallback((nav) => { let messages = getMessagesArr(); if (isNotEmptyArray(messages)) { //need to release react to re-render the prompt window.setTimeout(() => { //prompt, if ok - clear messages and nav. setPrompt({ okButtonText: "Leave", cancelButtonText: "Cancel", title: "Leave page?", children: messages.length > 1 ? _jsx("ul", { children: messages.map((m, i) => _jsx("li", { children: m }, `m${i}`)) }) : _jsx("p", { children: messages[0] }), onCancel: () => setPrompt(null), onOK: () => { setPrompt(null); setBlockNavMessages({}); //clear messages nav(); } }); }, 1); } else nav(); }, useEffectOnlyOnMount); useEffect(() => { function handleBeforeUnload(e) { //todo: use blockMessageRef.current so that we don't have to re-register every time message changes. //otherwise we would have to add blockMessage as a dependency for this useEffect const message = getMessages(); if (!isNullOrEmptyString(message)) { e.preventDefault(); e.returnValue = message; } } // Add event listener window.addEventListener("beforeunload", handleBeforeUnload); // Remove event listener on cleanup return () => window.removeEventListener("beforeunload", handleBeforeUnload); }, useEffectOnlyOnMount); return { setMessage: (id, message) => { let current = jsonClone(blockNavMessagesRef.current); if (isNullOrEmptyString(message)) delete current[id]; else current[id] = message; if (!objectsEqual(current, blockNavMessagesRef.current)) setBlockNavMessages(current); }, // clearMessages: () => { // setBlockNavMessages({}); // }, // getMessages, // getMessagesArr, onNav, navPrompt: _prompt ? _jsx(Prompter, Object.assign({}, _prompt)) : undefined }; } //# sourceMappingURL=block-nav.js.map