UNPKG

element-plus

Version:

A Component Library for Vue 3

178 lines (152 loc) 3.91 kB
import { computed, ref, watch, nextTick, onMounted } from 'vue' import { useTimeoutFn } from '@vueuse/core' import { useLockScreen, useRestoreActive, useModal } from '@element-plus/hooks' import { UPDATE_MODEL_EVENT } from '@element-plus/utils/constants' import isServer from '@element-plus/utils/isServer' import PopupManager from '@element-plus/utils/popup-manager' import { isNumber } from '@element-plus/utils/util' import type { CSSProperties, Ref, SetupContext } from 'vue' import type { DialogEmits, DialogProps } from './dialog' export const useDialog = ( props: DialogProps, { emit }: SetupContext<DialogEmits>, targetRef: Ref<HTMLElement | undefined> ) => { const visible = ref(false) const closed = ref(false) const rendered = ref(false) // when desctroyOnClose is true, we initialize it as false vise versa const zIndex = ref(props.zIndex || PopupManager.nextZIndex()) let openTimer: (() => void) | undefined = undefined let closeTimer: (() => void) | undefined = undefined const normalizeWidth = computed(() => isNumber(props.width) ? `${props.width}px` : props.width ) const style = computed<CSSProperties>(() => { const style: CSSProperties = {} const varPrefix = `--el-dialog` if (!props.fullscreen) { if (props.top) { style[`${varPrefix}-margin-top`] = props.top } if (props.width) { style[`${varPrefix}-width`] = normalizeWidth.value } } return style }) function afterEnter() { emit('opened') } function afterLeave() { emit('closed') emit(UPDATE_MODEL_EVENT, false) if (props.destroyOnClose) { rendered.value = false } } function beforeLeave() { emit('close') } function open() { closeTimer?.() openTimer?.() if (props.openDelay && props.openDelay > 0) { ;({ stop: openTimer } = useTimeoutFn(() => doOpen(), props.openDelay)) } else { doOpen() } } function close() { // if (this.willClose && !this.willClose()) return; openTimer?.() closeTimer?.() if (props.closeDelay && props.closeDelay > 0) { ;({ stop: closeTimer } = useTimeoutFn(() => doClose(), props.closeDelay)) } else { doClose() } } function hide(shouldCancel: boolean) { if (shouldCancel) return closed.value = true visible.value = false } function handleClose() { if (props.beforeClose) { props.beforeClose(hide) } else { close() } } function onModalClick() { if (props.closeOnClickModal) { handleClose() } } function doOpen() { if (isServer) { return } // if (props.willOpen?.()) { // return // } visible.value = true } function doClose() { visible.value = false } if (props.lockScroll) { useLockScreen(visible) } if (props.closeOnPressEscape) { useModal( { handleClose, }, visible ) } useRestoreActive(visible) watch( () => props.modelValue, (val) => { if (val) { closed.value = false open() rendered.value = true // enables lazy rendering emit('open') zIndex.value = props.zIndex ? zIndex.value++ : PopupManager.nextZIndex() // this.$el.addEventListener('scroll', this.updatePopper) nextTick(() => { if (targetRef.value) { targetRef.value.scrollTop = 0 } }) } else { // this.$el.removeEventListener('scroll', this.updatePopper if (visible.value) { close() } } } ) onMounted(() => { if (props.modelValue) { visible.value = true rendered.value = true // enables lazy rendering open() } }) return { afterEnter, afterLeave, beforeLeave, handleClose, onModalClick, closed, style, rendered, visible, zIndex, } }