UNPKG

vite-plugin-entry-shaking-debugger

Version:
93 lines (80 loc) 2.73 kB
import type { Ref } from 'vue'; import { computed, onMounted, onUnmounted, ref } from 'vue'; import type { ShortEmits } from '#uitypes'; import { useFocusTrap } from '@composables/useFocusTrap'; import { useTeleport } from '@composables/useTeleport'; import type { DialogEvents, DialogProps } from './Dialog.types'; export const DIALOG_CONTAINER_ID_VAR = 'dialogContainerId'; export const DIALOG_MAIN_CONTAINER_ID = 'dialog-container-main'; export const DIALOG_CONTAINER_CLASS = 'dialog-container'; /** * Dialog composable. * @param props Dialog props. * @param emit Dialog events emitter. * @param element Dialog content template ref. */ export function useDialog( props: DialogProps, emit: ShortEmits<DialogEvents>, element: Ref<HTMLDialogElement | null>, ) { const trap = useFocusTrap(element); const timeout = ref<ReturnType<typeof setTimeout>>(); const teleport = useTeleport('dialog'); /** Closes the dialog. */ const close = () => { element.value?.close(); }; /** Triggered when dialog is clicked. */ const handleClick = (event: Event) => { const [topTarget] = event.composedPath(); if (topTarget === element.value) close(); }; /** Triggered when opening the dialog. */ const handleOpen = () => { // Clear any existing close animation's timeout. if (timeout.value) clearTimeout(timeout.value); // Refresh focus trap in case dialog content changed. trap.refresh(); }; /** Triggered when closing the dialog. */ const handleClose = () => { const animationCustomProp = '--transition-duration-short'; const computedStyle = getComputedStyle(element.value!); const duration = computedStyle.getPropertyValue(animationCustomProp); const delay = duration.endsWith('ms') ? Number(duration.slice(0, -2)) : Number(duration.slice(0, -1)) * 1000; // Wait for the closing animation to finish before emitting the close event. timeout.value = setTimeout(() => { emit('close'); }, delay); }; const dialogTransitionName = computed(() => `dialog-${props.id}-transition`); const backdropTransitionName = computed(() => `dialog-backdrop-${props.id}-transition`); const isOpen = ref(element.value?.open ?? false); let observer: MutationObserver | undefined; onMounted(() => { observer = new MutationObserver(() => { isOpen.value = element.value?.open ?? false; }); observer.observe(element.value!, { attributes: true, attributeFilter: ['open'], }); }); onUnmounted(() => { observer?.disconnect(); }); return { trap, close, handleClick, handleOpen, handleClose, dialogTransitionName, backdropTransitionName, teleport, isOpen, }; }