Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: kimatata <117462761+kimatata@users.noreply.github.com>
55 lines
1.5 KiB
TypeScript
55 lines
1.5 KiB
TypeScript
import { useEffect } from 'react';
|
|
|
|
const isIgnoredPath = (href: string, compiledPatterns: RegExp[]): boolean => {
|
|
return compiledPatterns.some((regex) => regex.test(href));
|
|
};
|
|
|
|
export const useFormGuard = (isDirty: boolean, confirmText: string, ignorePathPatterns?: string[]) => {
|
|
useEffect(() => {
|
|
const compiledPatterns: RegExp[] = (ignorePathPatterns ?? []).flatMap((pattern) => {
|
|
try {
|
|
return [new RegExp(pattern)];
|
|
} catch {
|
|
return [];
|
|
}
|
|
});
|
|
|
|
const handleClick = (event: MouseEvent) => {
|
|
if (!isDirty) return;
|
|
|
|
if (event.target instanceof Element) {
|
|
const anchor = event.target.closest('a:not([target="_blank"])');
|
|
if (!anchor) return;
|
|
|
|
const href = anchor.getAttribute('href');
|
|
if (!href) return;
|
|
|
|
// do not show confirm for ignored paths
|
|
if (isIgnoredPath(href, compiledPatterns)) {
|
|
return;
|
|
}
|
|
|
|
if (!window.confirm(confirmText)) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
}
|
|
}
|
|
};
|
|
|
|
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
|
|
if (isDirty) {
|
|
event.preventDefault();
|
|
return (event.returnValue = '');
|
|
}
|
|
};
|
|
|
|
window.addEventListener('beforeunload', handleBeforeUnload);
|
|
window.addEventListener('click', handleClick, true);
|
|
|
|
return () => {
|
|
window.removeEventListener('beforeunload', handleBeforeUnload);
|
|
window.removeEventListener('click', handleClick, true);
|
|
};
|
|
}, [confirmText, isDirty, ignorePathPatterns]);
|
|
};
|