Skip to content

Commit bbd57eb

Browse files
committed
refactor: rename type Modal to ModalExposed
1 parent dafa559 commit bbd57eb

File tree

4 files changed

+70
-49
lines changed

4 files changed

+70
-49
lines changed

packages/vue-final-modal/src/Modal.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { App, CSSProperties, ComputedRef, FunctionalComponent, Raw, Ref } from 'vue'
1+
import type { App, CSSProperties, ComponentInternalInstance, FunctionalComponent, Raw, Ref } from 'vue'
22

33
export type ModalId = number | string | symbol
44
export type StyleValue = string | CSSProperties | (string | CSSProperties)[]
@@ -52,22 +52,22 @@ export interface UseModalReturnType<T extends ComponentType> {
5252

5353
export type Vfm = {
5454
install(app: App): void
55-
modals: ComputedRef<Modal>[]
56-
openedModals: ComputedRef<Modal>[]
57-
openedModalOverlays: ComputedRef<Modal>[]
55+
modals: ComponentInternalInstance[]
56+
openedModals: ComponentInternalInstance[]
57+
openedModalOverlays: ComponentInternalInstance[]
5858
dynamicModals: (UseModalOptions<any> & UseModalOptionsPrivate)[]
5959
modalsContainers: Ref<symbol[]>
60-
get: (modalId: ModalId) => undefined | ComputedRef<Modal>
60+
get: (modalId: ModalId) => undefined | ComponentInternalInstance
6161
toggle: (modalId: ModalId, show?: boolean) => undefined | Promise<string>
6262
open: (modalId: ModalId) => undefined | Promise<string>
6363
close: (modalId: ModalId) => undefined | Promise<string>
6464
closeAll: () => Promise<PromiseSettledResult<string>[]>
6565
}
6666

67-
export type Modal = {
67+
export type ModalExposed = {
6868
modalId?: ModalId
69-
hideOverlay: Ref<boolean | undefined> | undefined
70-
overlayBehavior: Ref<'auto' | 'persist'>
71-
overlayVisible: Ref<boolean>
69+
hideOverlay?: boolean
70+
overlayBehavior: 'auto' | 'persist'
71+
overlayVisible: boolean
7272
toggle: (show?: boolean) => Promise<string>
7373
}

packages/vue-final-modal/src/components/VueFinalModal/VueFinalModal.vue

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { computed, nextTick, onBeforeUnmount, onMounted, ref, toRef, useAttrs, watch } from 'vue'
2+
import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, ref, useAttrs, watch } from 'vue'
33
import { vueFinalModalProps } from './VueFinalModalProps'
44
import { useTransition } from './useTransition'
55
import { useToClose } from './useToClose'
@@ -9,9 +9,10 @@ import { useLockScroll } from './useBodyScrollLock'
99
import { useZIndex } from './useZIndex'
1010
import { vVisible } from './vVisible'
1111
import { arrayMoveItemToLast, arrayRemoveItem, noop, once } from '~/utils'
12-
import { type Modal } from '~/Modal'
12+
import { type ModalExposed } from '~/Modal'
1313
import { useSwipeToClose } from '~/useSwipeToClose'
1414
import { useVfm } from '~/useApi'
15+
import { getModalExposed } from '~/plugin'
1516
1617
export interface VueFinalModalEmits {
1718
(e: 'update:modelValue', modelValue: boolean): void
@@ -31,6 +32,8 @@ const attrs = useAttrs()
3132
3233
defineOptions({ inheritAttrs: false })
3334
35+
const instance = getCurrentInstance()
36+
3437
defineSlots<{
3538
'default'(): void
3639
'swipe-banner'(): void
@@ -77,7 +80,7 @@ const {
7780
resolveToggle('opened')
7881
},
7982
onLeave() {
80-
arrayRemoveItem(openedModals, modalInstance)
83+
arrayRemoveItem(openedModals, instance)
8184
resetZIndex()
8285
enableBodyScroll()
8386
emit('closed')
@@ -93,24 +96,7 @@ const {
9396
onTouchStartSwipeBanner,
9497
} = useSwipeToClose(props, { vfmContentEl, modelValueLocal })
9598
96-
const hideOverlay = toRef(props, 'hideOverlay')
97-
const overlayBehavior = toRef(props, 'overlayBehavior')
98-
const modalInstance = computed<Modal>(() => ({
99-
modalId: props.modalId,
100-
hideOverlay,
101-
overlayBehavior,
102-
overlayVisible,
103-
toggle(show?: boolean): Promise<string> {
104-
return new Promise((resolve) => {
105-
resolveToggle = once((res: string) => resolve(res))
106-
107-
const value = typeof show === 'boolean' ? show : !modelValueLocal.value
108-
modelValueLocal.value = value
109-
})
110-
},
111-
}))
112-
113-
const index = computed(() => openedModals.indexOf(modalInstance))
99+
const index = computed(() => instance ? openedModals.indexOf(instance) : -1)
114100
115101
watch([() => props.zIndexFn, index], () => {
116102
if (!visible.value)
@@ -119,7 +105,7 @@ watch([() => props.zIndexFn, index], () => {
119105
})
120106
121107
onMounted(() => {
122-
arrayMoveItemToLast(modals, modalInstance)
108+
arrayMoveItemToLast(modals, instance)
123109
})
124110
125111
if (props.modelValue)
@@ -130,8 +116,8 @@ function open(): boolean {
130116
emit('beforeOpen', { stop: () => shouldStop = true })
131117
if (shouldStop)
132118
return false
133-
arrayMoveItemToLast(openedModals, modalInstance)
134-
arrayMoveItemToLast(openedModalOverlays, modalInstance)
119+
arrayMoveItemToLast(openedModals, instance)
120+
arrayMoveItemToLast(openedModalOverlays, instance)
135121
openLastOverlay()
136122
enterTransition()
137123
return true
@@ -142,7 +128,7 @@ function close(): boolean {
142128
emit('beforeClose', { stop: () => shouldStop = true })
143129
if (shouldStop)
144130
return false
145-
arrayRemoveItem(openedModalOverlays, modalInstance)
131+
arrayRemoveItem(openedModalOverlays, instance)
146132
openLastOverlay()
147133
blur()
148134
leaveTransition()
@@ -151,21 +137,46 @@ function close(): boolean {
151137
152138
onBeforeUnmount(() => {
153139
enableBodyScroll()
154-
arrayRemoveItem(modals, modalInstance)
155-
arrayRemoveItem(openedModals, modalInstance)
140+
arrayRemoveItem(modals, instance)
141+
arrayRemoveItem(openedModals, instance)
156142
blur()
157143
openLastOverlay()
158144
})
159145
160146
async function openLastOverlay() {
161147
await nextTick()
162148
// Found the modals which has overlay and has `auto` overlayBehavior
163-
const openedModalsOverlaysAuto = openedModalOverlays.filter(modal => modal.value.overlayBehavior.value === 'auto' && !modal.value.hideOverlay?.value)
149+
const openedModalsOverlaysAuto = openedModalOverlays.filter((modal) => {
150+
const modalExposed = getModalExposed(modal)
151+
return modalExposed?.value.overlayBehavior === 'auto' && !modalExposed?.value.hideOverlay
152+
})
164153
// Only keep the last overlay open
165154
openedModalsOverlaysAuto.forEach((modal, index) => {
166-
modal.value.overlayVisible.value = index === openedModalsOverlaysAuto.length - 1
155+
const modalExposed = getModalExposed(modal)
156+
if (!modalExposed?.value)
157+
return
158+
modalExposed.value.overlayVisible = index === openedModalsOverlaysAuto.length - 1
167159
})
168160
}
161+
162+
const modalExposed = computed<ModalExposed>(() => ({
163+
modalId: props.modalId,
164+
hideOverlay: props.hideOverlay,
165+
overlayBehavior: props.overlayBehavior,
166+
overlayVisible: overlayVisible.value,
167+
toggle(show?: boolean): Promise<string> {
168+
return new Promise((resolve) => {
169+
resolveToggle = once((res: string) => resolve(res))
170+
171+
const value = typeof show === 'boolean' ? show : !modelValueLocal.value
172+
modelValueLocal.value = value
173+
})
174+
},
175+
}))
176+
177+
defineExpose({
178+
modalExposed,
179+
})
169180
</script>
170181

171182
<template>
@@ -185,7 +196,7 @@ async function openLastOverlay() {
185196
@mouseup.self="() => onMouseupRoot()"
186197
@mousedown.self="e => onMousedown(e)"
187198
>
188-
<Transition v-if="!hideOverlay" v-bind="(overlayTransition as object)" v-on="overlayListeners">
199+
<Transition v-if="!hideOverlay" v-bind="overlayTransition as object" v-on="overlayListeners">
189200
<div
190201
v-if="displayDirective !== 'if' || overlayVisible"
191202
v-show="displayDirective !== 'show' || overlayVisible"
@@ -196,7 +207,7 @@ async function openLastOverlay() {
196207
aria-hidden="true"
197208
/>
198209
</Transition>
199-
<Transition v-bind="(contentTransition as object)" v-on="contentListeners">
210+
<Transition v-bind="contentTransition as object" v-on="contentListeners">
200211
<div
201212
v-if="displayDirective !== 'if' || contentVisible"
202213
v-show="displayDirective !== 'show' || contentVisible"

packages/vue-final-modal/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type { Vfm } from './Modal'
77
export * from './Modal'
88

99
/** Plugin */
10-
export * from './plugin'
10+
export { createVfm, getModalExposed } from './plugin'
1111

1212
/** Components */
1313
export {

packages/vue-final-modal/src/plugin.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import type { App, ComputedRef } from 'vue'
1+
import type { App, ComponentInternalInstance, ComputedRef } from 'vue'
22
import { getCurrentInstance, inject, markRaw, ref, shallowReactive } from 'vue'
33
import { vfmSymbol } from './injectionSymbols'
4-
import type { Modal, ModalId, UseModalOptions, UseModalOptionsPrivate, Vfm } from './Modal'
4+
import type { ModalExposed, ModalId, UseModalOptions, UseModalOptionsPrivate, Vfm } from './Modal'
55
import { noop } from './utils'
66

77
// eslint-disable-next-line import/no-mutable-exports
@@ -28,9 +28,9 @@ export const getActiveVfm = () =>
2828
(getCurrentInstance() && inject(vfmSymbol, defaultVfm)) || activeVfm
2929

3030
export function createVfm() {
31-
const modals: ComputedRef<Modal>[] = shallowReactive([])
32-
const openedModals: ComputedRef<Modal>[] = shallowReactive([])
33-
const openedModalOverlays: ComputedRef<Modal>[] = shallowReactive([])
31+
const modals: ComponentInternalInstance[] = shallowReactive([])
32+
const openedModals: ComponentInternalInstance[] = shallowReactive([])
33+
const openedModalOverlays: ComponentInternalInstance[] = shallowReactive([])
3434
const dynamicModals: (UseModalOptions<any> & UseModalOptionsPrivate)[] = shallowReactive([])
3535
const modalsContainers = ref<symbol[]>([])
3636

@@ -45,11 +45,14 @@ export function createVfm() {
4545
dynamicModals,
4646
modalsContainers,
4747
get(modalId: ModalId) {
48-
return modals.find(modal => modal.value.modalId && modalId === modal.value.modalId)
48+
return modals.find((modal) => {
49+
const modalExposed = getModalExposed(modal)
50+
return modalExposed?.value.modalId && modalId === modalExposed?.value.modalId
51+
})
4952
},
5053
toggle(modalId: ModalId, show?: boolean) {
5154
const modal = vfm.get(modalId)
52-
return modal?.value.toggle(show)
55+
return getModalExposed(modal)?.value.toggle(show)
5356
},
5457
open(modalId: ModalId) {
5558
return vfm.toggle(modalId, true)
@@ -58,11 +61,18 @@ export function createVfm() {
5861
return vfm.toggle(modalId, false)
5962
},
6063
closeAll() {
61-
return Promise.allSettled(openedModals.map(modal => modal.value.toggle(false)))
64+
return Promise.allSettled(openedModals
65+
.map(modal => getModalExposed(modal))
66+
.filter((modal): modal is ComputedRef<ModalExposed> => !!modal)
67+
.map(modal => modal.value.toggle(false)))
6268
},
6369
})
6470

6571
setActiveVfm(vfm)
6672

6773
return vfm
6874
}
75+
76+
export function getModalExposed(componentInternalInstance: undefined | null | ComponentInternalInstance): null | ComputedRef<ModalExposed> {
77+
return componentInternalInstance?.exposed?.modalExposed || null
78+
}

0 commit comments

Comments
 (0)