UNPKG

@kwiz/fluentui

Version:
79 lines 3.69 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { isNotEmptyArray, isNotEmptyString, isNullOrEmptyString, stringEqualsOrEmpty } from "@kwiz/common"; import { useCallback, useEffect, useMemo } from "react"; import { Prompter } from "../controls/prompt"; import { useEffectOnlyOnMount, useStateEX } from "./hooks"; /** @deprecated replace with useTrackChanges * 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() { //todo: once we remove this and replace it with useTrackChanges keep this only for the window unload event registration 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 setMessage = useCallback((id, message) => { if (!stringEqualsOrEmpty(message, blockNavMessagesRef.current[id])) { const current = Object.assign({}, blockNavMessagesRef.current); if (isNotEmptyString(message)) current[id] = message; else delete current[id]; setBlockNavMessages(current); } }, [setBlockNavMessages]); 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) { //using 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); const navPrompt = useMemo(() => _prompt ? _jsx(Prompter, Object.assign({}, _prompt)) : undefined, [_prompt]); return useMemo(() => ({ setMessage, onNav, navPrompt }), [setMessage, onNav, navPrompt]); } //# sourceMappingURL=block-nav.js.map