@kwiz/fluentui
Version:
KWIZ common controls for FluentUI
79 lines • 3.47 kB
JavaScript
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