|
| 1 | +import type { Component } from 'vue-demi' |
| 2 | +import { computed, defineComponent, h, onBeforeUnmount } from 'vue-demi' |
| 3 | +import type { ModalSlotOptions } from '..' |
| 4 | +import { isModalSlotOptions, useVfm } from '~/useApi' |
| 5 | +import { isString, objectEntries } from '~/utils' |
| 6 | + |
| 7 | +export const ModalsContainer = defineComponent({ |
| 8 | + setup() { |
| 9 | + const { modalsContainers, dynamicModals } = useVfm() |
| 10 | + |
| 11 | + const uid = Symbol(__DEV__ ? 'ModalsContainer' : '') |
| 12 | + const shouldMount = computed(() => uid === modalsContainers.value?.[0]) |
| 13 | + |
| 14 | + modalsContainers.value.push(uid) |
| 15 | + onBeforeUnmount(() => { |
| 16 | + modalsContainers.value = modalsContainers.value.filter(i => i !== uid) |
| 17 | + }) |
| 18 | + |
| 19 | + function resolvedClosed(index: number) { |
| 20 | + dynamicModals[index]?.resolveClosed?.() |
| 21 | + if (!dynamicModals[index]?.keepAlive) |
| 22 | + dynamicModals.splice(index, 1) |
| 23 | + } |
| 24 | + |
| 25 | + function resolvedOpened(index: number) { |
| 26 | + dynamicModals[index]?.resolveOpened?.() |
| 27 | + } |
| 28 | + |
| 29 | + return () => { |
| 30 | + if (shouldMount.value) |
| 31 | + return null |
| 32 | + return dynamicModals.map((modal, index) => { |
| 33 | + if (!modal.component) |
| 34 | + return null |
| 35 | + const slots = objectEntries(modal.slots || {}).reduce((acc, cur) => { |
| 36 | + const slotName = cur[0] as string |
| 37 | + const slot = cur[1] as string | Component | ModalSlotOptions |
| 38 | + if (isString(slot)) |
| 39 | + acc[slotName] = () => h('div', { innerHTML: slot }) |
| 40 | + else if (isModalSlotOptions(slot)) |
| 41 | + acc[slotName] = () => h(slot.component, slot.attrs) |
| 42 | + else |
| 43 | + acc[slotName] = () => h(slot) |
| 44 | + return acc |
| 45 | + }, {} as any) |
| 46 | + |
| 47 | + return h(modal.component, { |
| 48 | + 'key': modal.id, |
| 49 | + 'modelValue': modal.modelValue, |
| 50 | + 'onUpdate:modelValue': (value: boolean) => modal.modelValue = value, |
| 51 | + 'displayDirective': modal?.keepAlive ? 'show' : undefined, |
| 52 | + ...(typeof modal.attrs === 'object' ? modal.attrs : {}), |
| 53 | + 'on_closed': () => resolvedClosed(index), |
| 54 | + 'on_opened': () => resolvedOpened(index), |
| 55 | + }, slots) |
| 56 | + }) |
| 57 | + } |
| 58 | + }, |
| 59 | +}) |
0 commit comments