import { computed, onUnmounted, ref, watch } from 'vue';
import { onClickOutside } from '@vueuse/core';
import { DrawerEmit, DrawerProps, UseDrawerFn } from './drawer-types';
import { lockScroll } from '../../shared/utils/lock-scroll';
import { useNamespace } from '../../shared/hooks/use-namespace';
export function useDrawer(props: DrawerProps, emit: DrawerEmit): UseDrawerFn {
const ns = useNamespace('drawer');
const modalNs = useNamespace('modal', true);
const drawerRef = ref<HTMLElement>();
const overlayRef = ref<HTMLElement>();
const drawerClasses = computed(() => ({
[ns.b()]: true,
[ns.m(props.position)]: true,
}));
const close = () => {
emit('update:modelValue', false);
emit('close');
};
let lockScrollCb: () => void;
const execClose = () => {
props.beforeClose ? props.beforeClose(close) : close();
};
const handleOverlayClick = () => {
props.closeOnClickOverlay && execClose();
};
const handleEscClose = (e: KeyboardEvent) => {
e.code === 'Escape' && execClose();
};
const handleClickOutside = (e: PointerEvent) => {
const composedPath = e.composedPath();
const modalOverlay = document.querySelectorAll(modalNs.e('overlay'));
const modal = document.querySelectorAll(modalNs.b());
const isClickModalOverlay = Array.from(modalOverlay).filter((item) => composedPath.includes(item));
const isClickModal = Array.from(modal).filter((item) => composedPath.includes(item));
if (isClickModalOverlay.length || isClickModal.length) {
return;
}
execClose();
};
setTimeout(() => {
onClickOutside(drawerRef, handleClickOutside, { capture: false, ignore: [overlayRef] });
});
const removeBodyAdditions = () => {
lockScrollCb?.();
document.removeEventListener('keyup', handleEscClose);
};
watch(
() => props.modelValue,
(val) => {
if (val) {
emit('open');
props.lockScroll && (lockScrollCb = lockScroll());
props.escKeyCloseable && document.addEventListener('keyup', handleEscClose);
} else {
removeBodyAdditions();
}
}
);
onUnmounted(removeBodyAdditions);
return { overlayRef, drawerRef, drawerClasses, handleOverlayClick };
}