1
1
<script setup lang="ts">
2
- import { computed , nextTick , onBeforeUnmount , onMounted , ref , toRef , useAttrs , watch } from ' vue'
2
+ import { computed , getCurrentInstance , nextTick , onBeforeUnmount , onMounted , ref , toRef , useAttrs , watch } from ' vue'
3
3
import { vueFinalModalProps } from ' ./VueFinalModalProps'
4
4
import { useTransition } from ' ./useTransition'
5
5
import { useToClose } from ' ./useToClose'
@@ -8,10 +8,11 @@ import { useFocusTrap } from './useFocusTrap'
8
8
import { useLockScroll } from ' ./useBodyScrollLock'
9
9
import { useZIndex } from ' ./useZIndex'
10
10
import { vVisible } from ' ./vVisible'
11
- import { noop , once } from ' ~/utils'
12
- import { type Modal } from ' ~/Modal'
11
+ import { arrayMoveItemToLast , arrayRemoveItem , noop , once } from ' ~/utils'
12
+ import { type ModalExposed } from ' ~/Modal'
13
13
import { useSwipeToClose } from ' ~/useSwipeToClose'
14
- import { useInternalVfm , useVfm } from ' ~/useApi'
14
+ import { useVfm } from ' ~/useApi'
15
+ import { getModalExposed } from ' ~/plugin'
15
16
16
17
export interface VueFinalModalEmits {
17
18
(e : ' update:modelValue' , modelValue : boolean ): void
@@ -26,30 +27,19 @@ export interface VueFinalModalEmits {
26
27
}
27
28
28
29
const props = defineProps (vueFinalModalProps )
29
-
30
30
const emit = defineEmits <VueFinalModalEmits >()
31
-
32
31
const attrs = useAttrs ()
33
32
34
- defineOptions ({
35
- inheritAttrs: false ,
36
- } )
33
+ defineOptions ({ inheritAttrs: false })
34
+
35
+ const instance = getCurrentInstance ( )
37
36
38
37
defineSlots <{
39
38
' default' (): void
40
39
' swipe-banner' (): void
41
40
}>()
42
41
43
- const { modals, openedModals } = useVfm ()
44
-
45
- const {
46
- openLastOverlay,
47
- moveToLastOpenedModals,
48
- deleteFromOpenedModals,
49
- moveToLastOpenedModalOverlays,
50
- deleteFromOpenedModalOverlays,
51
- deleteFromModals,
52
- } = useInternalVfm ()
42
+ const { modals, openedModals, openedModalOverlays } = useVfm ()
53
43
54
44
const vfmRootEl = ref <HTMLDivElement >()
55
45
const vfmContentEl = ref <HTMLDivElement >()
@@ -90,7 +80,7 @@ const {
90
80
resolveToggle (' opened' )
91
81
},
92
82
onLeave() {
93
- deleteFromOpenedModals ( getModalInstance () )
83
+ arrayRemoveItem ( openedModals , instance )
94
84
resetZIndex ()
95
85
enableBodyScroll ()
96
86
emit (' closed' )
@@ -106,36 +96,16 @@ const {
106
96
onTouchStartSwipeBanner,
107
97
} = useSwipeToClose (props , { vfmContentEl , modelValueLocal })
108
98
109
- const hideOverlay = toRef (props , ' hideOverlay' )
110
- const modalInstance = computed <Modal >(() => ({
111
- modalId: props .modalId ,
112
- hideOverlay ,
113
- overlayVisible ,
114
- focus ,
115
- toggle(show ? : boolean ): Promise <string > {
116
- return new Promise ((resolve ) => {
117
- resolveToggle = once ((res : string ) => resolve (res ))
118
-
119
- const value = typeof show === ' boolean' ? show : ! modelValueLocal .value
120
- modelValueLocal .value = value
121
- emit (' update:modelValue' , value )
122
- })
123
- },
124
- }))
125
-
126
- function getModalInstance() {
127
- return modalInstance
128
- }
129
-
130
- const index = computed (() => openedModals .indexOf (modalInstance ))
99
+ const index = computed (() => instance ? openedModals .indexOf (instance ) : - 1 )
131
100
132
101
watch ([() => props .zIndexFn , index ], () => {
133
- if (visible .value )
134
- refreshZIndex (index .value )
102
+ if (! visible .value )
103
+ return
104
+ refreshZIndex (index .value )
135
105
})
136
106
137
107
onMounted (() => {
138
- modals . push ( modalInstance )
108
+ arrayMoveItemToLast ( modals , instance )
139
109
})
140
110
141
111
if (props .modelValue )
@@ -146,9 +116,8 @@ function open(): boolean {
146
116
emit (' beforeOpen' , { stop : () => shouldStop = true })
147
117
if (shouldStop )
148
118
return false
149
- moveToLastOpenedModals (modalInstance )
150
- moveToLastOpenedModalOverlays (modalInstance )
151
- refreshZIndex (index .value )
119
+ arrayMoveItemToLast (openedModals , instance )
120
+ arrayMoveItemToLast (openedModalOverlays , instance )
152
121
openLastOverlay ()
153
122
enterTransition ()
154
123
return true
@@ -159,7 +128,7 @@ function close(): boolean {
159
128
emit (' beforeClose' , { stop : () => shouldStop = true })
160
129
if (shouldStop )
161
130
return false
162
- deleteFromOpenedModalOverlays ( getModalInstance () )
131
+ arrayRemoveItem ( openedModalOverlays , instance )
163
132
openLastOverlay ()
164
133
blur ()
165
134
leaveTransition ()
@@ -168,12 +137,49 @@ function close(): boolean {
168
137
169
138
onBeforeUnmount (() => {
170
139
enableBodyScroll ()
171
- deleteFromModals (modalInstance )
172
- deleteFromOpenedModals (modalInstance )
173
- deleteFromOpenedModalOverlays (modalInstance )
140
+ arrayRemoveItem (modals , instance )
141
+ arrayRemoveItem (openedModals , instance )
174
142
blur ()
175
143
openLastOverlay ()
176
144
})
145
+
146
+ async function openLastOverlay() {
147
+ await nextTick ()
148
+ // Found the modals which has overlay and has `auto` overlayBehavior
149
+ const openedModalsOverlaysAuto = openedModalOverlays .filter ((modal ) => {
150
+ const modalExposed = getModalExposed (modal )
151
+ return modalExposed ?.value .overlayBehavior .value === ' auto' && ! modalExposed ?.value .hideOverlay ?.value
152
+ })
153
+ // Only keep the last overlay open
154
+ openedModalsOverlaysAuto .forEach ((modal , index ) => {
155
+ const modalExposed = getModalExposed (modal )
156
+ if (! modalExposed ?.value )
157
+ return
158
+ modalExposed .value .overlayVisible .value = index === openedModalsOverlaysAuto .length - 1
159
+ })
160
+ }
161
+
162
+ const modalId = toRef (props , ' modalId' )
163
+ const hideOverlay = toRef (props , ' hideOverlay' )
164
+ const overlayBehavior = toRef (props , ' overlayBehavior' )
165
+ const modalExposed = computed <ModalExposed >(() => ({
166
+ modalId ,
167
+ hideOverlay ,
168
+ overlayBehavior ,
169
+ overlayVisible ,
170
+ toggle(show ? : boolean ): Promise <string > {
171
+ return new Promise ((resolve ) => {
172
+ resolveToggle = once ((res : string ) => resolve (res ))
173
+
174
+ const value = typeof show === ' boolean' ? show : ! modelValueLocal .value
175
+ modelValueLocal .value = value
176
+ })
177
+ },
178
+ }))
179
+
180
+ defineExpose ({
181
+ modalExposed ,
182
+ })
177
183
</script >
178
184
179
185
<template >
@@ -193,7 +199,7 @@ onBeforeUnmount(() => {
193
199
@mouseup.self =" () => onMouseupRoot()"
194
200
@mousedown.self =" e => onMousedown(e)"
195
201
>
196
- <Transition v-if =" !hideOverlay" v-bind =" overlayTransition" :appear = " true " v-on =" overlayListeners" >
202
+ <Transition v-if =" !hideOverlay" v-bind =" overlayTransition as object " v-on =" overlayListeners" >
197
203
<div
198
204
v-if =" displayDirective !== 'if' || overlayVisible"
199
205
v-show =" displayDirective !== 'show' || overlayVisible"
@@ -204,7 +210,7 @@ onBeforeUnmount(() => {
204
210
aria-hidden =" true"
205
211
/>
206
212
</Transition >
207
- <Transition v-bind =" contentTransition" :appear = " true " v-on =" contentListeners" >
213
+ <Transition v-bind =" contentTransition as object " v-on =" contentListeners" >
208
214
<div
209
215
v-if =" displayDirective !== 'if' || contentVisible"
210
216
v-show =" displayDirective !== 'show' || contentVisible"
0 commit comments