43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
import type { PendingVisit } from '@inertiajs/core';
|
|
import { router } from '@inertiajs/vue3';
|
|
import { onMounted, onUnmounted, toValue } from 'vue';
|
|
import type { MaybeRefOrGetter } from 'vue';
|
|
import { useLocalization } from '@/composables/useLocalization';
|
|
|
|
export function useUnsavedChanges(
|
|
dirty: MaybeRefOrGetter<boolean>,
|
|
allowVisit: (visit: PendingVisit) => boolean = () => false,
|
|
) {
|
|
const { t } = useLocalization();
|
|
let removeBeforeListener: (() => void) | undefined;
|
|
|
|
const confirmLeave = (): boolean =>
|
|
!toValue(dirty) || window.confirm(t('forms.leaveConfirm'));
|
|
|
|
const beforeUnload = (event: BeforeUnloadEvent): void => {
|
|
if (toValue(dirty)) {
|
|
event.preventDefault();
|
|
event.returnValue = '';
|
|
}
|
|
};
|
|
|
|
onMounted(() => {
|
|
removeBeforeListener = router.on('before', (event) => {
|
|
if (event.defaultPrevented || allowVisit(event.detail.visit)) {
|
|
return;
|
|
}
|
|
|
|
// Keep the original visit and its callbacks; never replay a mutation.
|
|
return confirmLeave();
|
|
});
|
|
window.addEventListener('beforeunload', beforeUnload);
|
|
});
|
|
|
|
onUnmounted(() => {
|
|
removeBeforeListener?.();
|
|
window.removeEventListener('beforeunload', beforeUnload);
|
|
});
|
|
|
|
return { confirmLeave };
|
|
}
|