Skip to content

Commit 62e758c

Browse files
committed
refactor: extract useInternalExposed and cleanup useZIndex
1 parent a481ed1 commit 62e758c

File tree

13 files changed

+137
-110
lines changed

13 files changed

+137
-110
lines changed

docs/content/2.get-started/1.guide/4.types.md

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@ The exported types in VueFinalModal.
88
export type ModalId = number | string | symbol
99
```
1010
11-
## StyleValue
12-
13-
```ts
14-
export type StyleValue = string | CSSProperties | (string | CSSProperties)[]
15-
```
16-
1711
## C2VOptions
1812
1913
```ts
@@ -32,7 +26,12 @@ export type C2VOptions<T extends Component> = {
3226
export type UseModalOptions<T extends Component> = {
3327
defaultModelValue?: boolean
3428
keepAlive?: boolean
35-
} & C2VOptions<T>
29+
component?: T
30+
attrs?: ComponentProps<T>
31+
slots?: {
32+
[K in keyof ComponentSlots<T>]?: string | Component | C2VOptions<Component>
33+
}
34+
}
3635
```
3736
3837
## UseModalOptionsPrivate
@@ -63,15 +62,27 @@ export interface UseModalReturnType<T extends Component> {
6362
```ts
6463
export type Vfm = {
6564
install(app: App): void
66-
modals: ComponentInternalInstance[]
67-
openedModals: ComponentInternalInstance[]
68-
openedModalOverlays: ComponentInternalInstance[]
69-
dynamicModals: VNode[]
70-
modalsContainers: Ref<symbol[]>
71-
get: (modalId: ModalId) => undefined | ComponentInternalInstance
65+
modals: ComputedRef<ModalExposed>[]
66+
openedModals: ComputedRef<ModalExposed>[]
67+
openedModalOverlays: ComputedRef<ModalExposed>[]
68+
vNodesContainer: VNodesContainer
69+
get: (modalId: ModalId) => undefined | ComputedRef<ModalExposed>
7270
toggle: (modalId: ModalId, show?: boolean) => undefined | Promise<string>
7371
open: (modalId: ModalId) => undefined | Promise<string>
7472
close: (modalId: ModalId) => undefined | Promise<string>
7573
closeAll: () => Promise<PromiseSettledResult<string>[]>
7674
}
7775
```
76+
77+
## ModalExposed
78+
79+
```ts
80+
export type ModalExposed = {
81+
modalId?: Ref<undefined | ModalId>
82+
hideOverlay?: Ref<undefined | boolean>
83+
overlayBehavior: Ref<'auto' | 'persist'>
84+
overlayVisible: Ref<boolean>
85+
toggle: (show?: boolean) => Promise<string>
86+
}
87+
88+
```

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { App, CSSProperties, Component, ComponentInternalInstance, Ref } from 'vue'
1+
import type { App, CSSProperties, Component, ComputedRef, Ref } from 'vue'
22
import type { ComponentProps, ComponentSlots } from './Component'
33
import type { VNodesContainer } from './useVNodesContainer'
44

@@ -40,21 +40,21 @@ export interface UseModalReturnType<T extends Component> {
4040

4141
export type Vfm = {
4242
install(app: App): void
43-
modals: ComponentInternalInstance[]
44-
openedModals: ComponentInternalInstance[]
45-
openedModalOverlays: ComponentInternalInstance[]
43+
modals: ComputedRef<ModalExposed>[]
44+
openedModals: ComputedRef<ModalExposed>[]
45+
openedModalOverlays: ComputedRef<ModalExposed>[]
4646
vNodesContainer: VNodesContainer
47-
get: (modalId: ModalId) => undefined | ComponentInternalInstance
47+
get: (modalId: ModalId) => undefined | ComputedRef<ModalExposed>
4848
toggle: (modalId: ModalId, show?: boolean) => undefined | Promise<string>
4949
open: (modalId: ModalId) => undefined | Promise<string>
5050
close: (modalId: ModalId) => undefined | Promise<string>
5151
closeAll: () => Promise<PromiseSettledResult<string>[]>
5252
}
5353

5454
export type ModalExposed = {
55-
modalId?: Ref<undefined | ModalId>
56-
hideOverlay?: Ref<undefined | boolean>
57-
overlayBehavior: Ref<'auto' | 'persist'>
55+
modalId: Ref<undefined | ModalId>
56+
hideOverlay: Ref<undefined | boolean>
57+
overlayBehavior: Ref<undefined | 'auto' | 'persist'>
5858
overlayVisible: Ref<boolean>
5959
toggle: (show?: boolean) => Promise<string>
6060
}

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

Lines changed: 22 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, ref, toRef, useAttrs, watch } from 'vue'
2+
import { nextTick, onBeforeUnmount, onMounted, ref, useAttrs } from 'vue'
33
import { vueFinalModalProps } from './VueFinalModalProps'
44
import { useTransition } from './useTransition'
55
import { useToClose } from './useToClose'
@@ -8,11 +8,10 @@ import { useFocusTrap } from './useFocusTrap'
88
import { useScrollLock } from './useScrollLock'
99
import { useZIndex } from './useZIndex'
1010
import { vVisible } from './vVisible'
11-
import { arrayMoveItemToLast, arrayRemoveItem, noop, once } from '~/utils'
12-
import { type ModalExposed } from '~/Modal'
11+
import { useInternalExposed } from './useInternalExposed'
12+
import { arrayMoveItemToLast, arrayRemoveItem } from '~/utils'
1313
import { useSwipeToClose } from '~/useSwipeToClose'
1414
import { useVfm } from '~/useVfm'
15-
import { getModalExposed } from '~/plugin'
1615
1716
export interface VueFinalModalEmits {
1817
(e: 'update:modelValue', modelValue: boolean): void
@@ -35,8 +34,6 @@ const props = defineProps(vueFinalModalProps)
3534
const emit = defineEmits<VueFinalModalEmits>()
3635
const attrs = useAttrs()
3736
38-
const instance = getCurrentInstance()
39-
4037
defineSlots<{
4138
'default'?(props: { close: () => boolean }): void
4239
'swipe-banner'?(): void
@@ -48,15 +45,12 @@ const vfmRootEl = ref<HTMLDivElement>()
4845
const vfmContentEl = ref<HTMLDivElement>()
4946
5047
const { focus, blur } = useFocusTrap(props, { focusEl: vfmRootEl })
51-
const { zIndex, refreshZIndex, resetZIndex } = useZIndex(props)
5248
const { modelValueLocal } = useModelValue(props, emit, { open, close })
5349
const { disablePageScroll, enablePageScroll } = useScrollLock(props, {
5450
lockScrollEl: vfmRootEl,
5551
modelValueLocal,
5652
})
5753
58-
let resolveToggle: (res: string) => void = (noop)
59-
6054
const {
6155
visible,
6256
@@ -85,7 +79,7 @@ const {
8579
resolveToggle('opened')
8680
},
8781
onLeave() {
88-
arrayRemoveItem(openedModals, instance)
82+
arrayRemoveItem(openedModals, modalExposed)
8983
resetZIndex()
9084
enablePageScroll()
9185
emit('closed')
@@ -95,36 +89,33 @@ const {
9589
},
9690
})
9791
92+
const { modalExposed, resolveToggle } = useInternalExposed(props, { modelValueLocal, overlayVisible })
93+
const { zIndex, resetZIndex } = useZIndex(props, { visible, modalExposed, openedModals })
9894
const { onEsc, onMouseupRoot, onMousedown } = useToClose(props, emit, { vfmRootEl, vfmContentEl, visible, modelValueLocal })
95+
const { swipeBannerEl, bindSwipe, onTouchStartSwipeBanner } = useSwipeToClose(props, { vfmContentEl, modelValueLocal })
9996
100-
const {
101-
swipeBannerEl,
102-
bindSwipe,
103-
onTouchStartSwipeBanner,
104-
} = useSwipeToClose(props, { vfmContentEl, modelValueLocal })
105-
106-
const index = computed(() => instance ? openedModals.indexOf(instance) : -1)
107-
108-
watch([() => props.zIndexFn, index], () => {
109-
if (!visible.value)
110-
return
111-
refreshZIndex(index.value)
112-
})
97+
if (props.modelValue)
98+
modelValueLocal.value = true
11399
114100
onMounted(() => {
115-
arrayMoveItemToLast(modals, instance)
101+
arrayMoveItemToLast(modals, modalExposed)
116102
})
117103
118-
if (props.modelValue)
119-
modelValueLocal.value = true
104+
onBeforeUnmount(() => {
105+
enablePageScroll()
106+
arrayRemoveItem(modals, modalExposed)
107+
arrayRemoveItem(openedModals, modalExposed)
108+
blur()
109+
openLastOverlay()
110+
})
120111
121112
function open(): boolean {
122113
let shouldStop = false
123114
emit('beforeOpen', { stop: () => shouldStop = true })
124115
if (shouldStop)
125116
return false
126-
arrayMoveItemToLast(openedModals, instance)
127-
arrayMoveItemToLast(openedModalOverlays, instance)
117+
arrayMoveItemToLast(openedModals, modalExposed)
118+
arrayMoveItemToLast(openedModalOverlays, modalExposed)
128119
openLastOverlay()
129120
enterTransition()
130121
return true
@@ -135,58 +126,24 @@ function close(): boolean {
135126
emit('beforeClose', { stop: () => shouldStop = true })
136127
if (shouldStop)
137128
return false
138-
arrayRemoveItem(openedModalOverlays, instance)
129+
arrayRemoveItem(openedModalOverlays, modalExposed)
139130
openLastOverlay()
140131
blur()
141132
leaveTransition()
142133
return true
143134
}
144135
145-
onBeforeUnmount(() => {
146-
enablePageScroll()
147-
arrayRemoveItem(modals, instance)
148-
arrayRemoveItem(openedModals, instance)
149-
blur()
150-
openLastOverlay()
151-
})
152-
153136
async function openLastOverlay() {
154137
await nextTick()
155138
// Found the modals which has overlay and has `auto` overlayBehavior
156139
const openedModalsOverlaysAuto = openedModalOverlays.filter((modal) => {
157-
const modalExposed = getModalExposed(modal)
158-
return modalExposed?.value.overlayBehavior.value === 'auto' && !modalExposed?.value.hideOverlay?.value
140+
return modal.value.overlayBehavior.value === 'auto' && !modal.value.hideOverlay?.value
159141
})
160142
// Only keep the last overlay open
161143
openedModalsOverlaysAuto.forEach((modal, index) => {
162-
const modalExposed = getModalExposed(modal)
163-
if (!modalExposed?.value)
164-
return
165-
modalExposed.value.overlayVisible.value = index === openedModalsOverlaysAuto.length - 1
144+
modal.value.overlayVisible.value = index === openedModalsOverlaysAuto.length - 1
166145
})
167146
}
168-
169-
const modalId = toRef(() => props.modalId)
170-
const hideOverlay = toRef(() => props.hideOverlay)
171-
const overlayBehavior = toRef(() => props.overlayBehavior)
172-
const modalExposed = computed<ModalExposed>(() => ({
173-
modalId,
174-
hideOverlay,
175-
overlayBehavior,
176-
overlayVisible,
177-
toggle(show?: boolean): Promise<string> {
178-
return new Promise((resolve) => {
179-
resolveToggle = once((res: string) => resolve(res))
180-
181-
const value = typeof show === 'boolean' ? show : !modelValueLocal.value
182-
modelValueLocal.value = value
183-
})
184-
},
185-
}))
186-
187-
defineExpose({
188-
modalExposed,
189-
})
190147
</script>
191148

192149
<script lang="ts">

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import type { Ref } from 'vue'
22
import { useFocusTrap as _useFocusTrap } from '@vueuse/integrations/useFocusTrap'
33
import type VueFinalModal from './VueFinalModal.vue'
4+
import type { ComponentProps } from '~/Component'
45

56
export function useFocusTrap(
6-
props: InstanceType<typeof VueFinalModal>['$props'],
7+
props: ComponentProps<typeof VueFinalModal>,
78
options: {
89
focusEl: Ref<undefined | HTMLDivElement>
910
},
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import type { Ref } from 'vue'
2+
import { computed, toRef } from 'vue'
3+
import type { ComponentProps, ModalExposed, VueFinalModal } from '~/index'
4+
import { noop, once } from '~/utils'
5+
6+
export const useInternalExposed = function (
7+
props: ComponentProps<typeof VueFinalModal>,
8+
options: {
9+
overlayVisible: Ref<boolean>
10+
modelValueLocal: Ref<boolean>
11+
},
12+
) {
13+
const { overlayVisible, modelValueLocal } = options
14+
15+
const modalId = toRef(() => props.modalId)
16+
const hideOverlay = toRef(() => props.hideOverlay)
17+
const overlayBehavior = toRef(() => props.overlayBehavior)
18+
19+
let resolveToggle: (res: string) => void = noop
20+
21+
function toggle(show?: boolean): Promise<string> {
22+
return new Promise((resolve) => {
23+
resolveToggle = once((res: string) => resolve(res))
24+
25+
const value = typeof show === 'boolean' ? show : !modelValueLocal.value
26+
modelValueLocal.value = value
27+
})
28+
}
29+
30+
const modalExposed = computed<ModalExposed>(() => ({
31+
modalId,
32+
hideOverlay,
33+
overlayBehavior,
34+
overlayVisible,
35+
toggle,
36+
}))
37+
38+
return {
39+
resolveToggle,
40+
modalExposed,
41+
}
42+
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { nextTick, ref, watch } from 'vue'
22
import type { Ref } from 'vue'
33
import type VueFinalModal from './VueFinalModal.vue'
4+
import type { ComponentEmit, ComponentProps } from '~/Component'
45

56
export function useModelValue(
6-
props: InstanceType<typeof VueFinalModal>['$props'],
7-
emit: InstanceType<typeof VueFinalModal>['$emit'],
7+
props: ComponentProps<typeof VueFinalModal>,
8+
emit: ComponentEmit<typeof VueFinalModal>,
89
options: {
910
open: () => boolean
1011
close: () => boolean

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import type { Ref } from 'vue'
33
import { onBeforeUnmount, watch } from 'vue'
44
import type VueFinalModal from './VueFinalModal.vue'
55
import { noop, once } from '~/utils'
6+
import type { ComponentProps } from '~/Component'
67

7-
export function useScrollLock(props: InstanceType<typeof VueFinalModal>['$props'], options: {
8+
export function useScrollLock(props: ComponentProps<typeof VueFinalModal>, options: {
89
lockScrollEl: Ref<undefined | HTMLElement>
910
modelValueLocal: Ref<boolean>
1011
}) {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import type { Ref } from 'vue'
22
import { ref } from 'vue'
33
import type VueFinalModal from './VueFinalModal.vue'
4+
import type { ComponentEmit, ComponentProps } from '~/Component'
45

56
export function useToClose(
6-
props: InstanceType<typeof VueFinalModal>['$props'],
7-
emit: InstanceType<typeof VueFinalModal>['$emit'],
7+
props: ComponentProps<typeof VueFinalModal>,
8+
emit: ComponentEmit<typeof VueFinalModal>,
89
options: {
910
vfmRootEl: Ref<HTMLDivElement | undefined>
1011
vfmContentEl: Ref<HTMLDivElement | undefined>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { ComputedRef, Ref, TransitionProps } from 'vue'
22
import { computed, nextTick, ref, watch } from 'vue'
33
import type VueFinalModal from './VueFinalModal.vue'
4+
import type { ComponentProps } from '~/Component'
45

56
export enum TransitionState {
67
Enter,
@@ -31,7 +32,7 @@ function useTransitionState(_visible = false): [Ref<boolean>, Ref<undefined | Tr
3132
}
3233

3334
export function useTransition(
34-
props: InstanceType<typeof VueFinalModal>['$props'],
35+
props: ComponentProps<typeof VueFinalModal>,
3536
options: {
3637
modelValueLocal: Ref<boolean>
3738
onEntering?: () => void

0 commit comments

Comments
 (0)