feat: init
This commit is contained in:
61
apps/web/core/hooks/use-reload-confirmation.tsx
Normal file
61
apps/web/core/hooks/use-reload-confirmation.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
//TODO: remove temp flag isActive later and use showAlert as the source of truth
|
||||
const useReloadConfirmations = (isActive = true, message?: string, defaultShowAlert = false, onLeave?: () => void) => {
|
||||
const [showAlert, setShowAlert] = useState(defaultShowAlert);
|
||||
|
||||
const alertMessage = message ?? "Are you sure you want to leave? Changes you made may not be saved.";
|
||||
|
||||
const handleBeforeUnload = useCallback(
|
||||
(event: BeforeUnloadEvent) => {
|
||||
if (!isActive || !showAlert) return;
|
||||
event.preventDefault();
|
||||
event.returnValue = "";
|
||||
},
|
||||
[isActive, showAlert]
|
||||
);
|
||||
|
||||
const handleAnchorClick = useCallback(
|
||||
(event: MouseEvent) => {
|
||||
if (!isActive || !showAlert) return;
|
||||
// Skip if event target is not available or defaultPrevented
|
||||
if (!event.target || event.defaultPrevented) return;
|
||||
// Skip control/command/option/alt+click
|
||||
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
||||
// check if the event target is an anchor or a child of an anchor tag
|
||||
const eventTarget = event.target as HTMLElement;
|
||||
if (!eventTarget.closest("a")) return; // This is intentionally not type safe
|
||||
// check if anchor target is _blank
|
||||
const anchorElement = eventTarget.closest("a") as HTMLAnchorElement;
|
||||
const isAnchorTargetBlank = anchorElement.getAttribute("target") === "_blank";
|
||||
if (isAnchorTargetBlank) return;
|
||||
// show confirm dialog
|
||||
const isLeaving = confirm(alertMessage);
|
||||
if (isLeaving) {
|
||||
onLeave && onLeave();
|
||||
} else {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
},
|
||||
[isActive, showAlert]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// handle browser refresh
|
||||
window.addEventListener("beforeunload", handleBeforeUnload, true);
|
||||
// handle anchor tag click
|
||||
window.addEventListener("click", handleAnchorClick, true);
|
||||
// TODO: handle back / forward button click
|
||||
|
||||
return () => {
|
||||
// cleanup
|
||||
window.removeEventListener("beforeunload", handleBeforeUnload, true);
|
||||
window.removeEventListener("click", handleAnchorClick, true);
|
||||
};
|
||||
}, [handleAnchorClick, handleBeforeUnload]);
|
||||
|
||||
return { setShowAlert };
|
||||
};
|
||||
|
||||
export default useReloadConfirmations;
|
||||
Reference in New Issue
Block a user