Skip to content

Commit 8ee2021

Browse files
committed
fix: add activeVfm (inspire by pinia)
1 parent 58b6fe5 commit 8ee2021

File tree

4 files changed

+37
-28
lines changed

4 files changed

+37
-28
lines changed

packages/nuxt/playground/components/PlainCssConfirmModalPreview.vue

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
<script setup lang="ts">
2-
import { ModalsContainer, useVfm } from 'vue-final-modal'
2+
import { ModalsContainer } from 'vue-final-modal'
33
import { showConfirmModal } from './showConfirmModal'
4-
5-
const vfm = useVfm()
64
</script>
75

86
<template>
9-
<button @click="() => showConfirmModal(vfm)">
7+
<button @click="() => showConfirmModal()">
108
Open Modal
119
</button>
1210

packages/nuxt/playground/components/showConfirmModal.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
1-
import type { Vfm } from 'vue-final-modal'
21
import { useModal } from 'vue-final-modal'
32
import PlainCssConfirmModal from './PlainCssConfirmModal.vue'
43

5-
export function showConfirmModal(vfm: Vfm) {
6-
const { open, close, destroy } = useModal({
7-
context: vfm,
4+
export function showConfirmModal() {
5+
const { open, close } = useModal({
86
component: PlainCssConfirmModal,
97
attrs: {
108
title: 'Hello World!',
119
onConfirm() {
1210
close()
1311
},
14-
onClosed() {
15-
destroy()
16-
},
1712
},
1813
slots: {
1914
default: '<p>The content of the modal</p>',

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
import type { App, ComputedRef } from 'vue'
2-
import { markRaw, nextTick, ref, shallowReactive } from 'vue'
2+
import { getCurrentInstance, inject, markRaw, nextTick, ref, shallowReactive } from 'vue'
33
import { internalVfmSymbol, vfmSymbol } from './injectionSymbols'
44
import type { InternalVfm, Modal, ModalId, UseModalOptions, UseModalOptionsPrivate, Vfm } from './Modal'
55

6+
// eslint-disable-next-line import/no-mutable-exports
7+
export let activeVfm: Vfm | undefined
8+
9+
export const setActiveVfm = (vfm: Vfm | undefined) =>
10+
(activeVfm = vfm)
11+
12+
export const getActiveVfm = () =>
13+
(getCurrentInstance() && inject(vfmSymbol)) || activeVfm
14+
615
export function createVfm() {
716
const modals: ComputedRef<Modal>[] = shallowReactive([])
817
const openedModals: ComputedRef<Modal>[] = shallowReactive([])
@@ -12,6 +21,8 @@ export function createVfm() {
1221

1322
const vfm: Vfm = markRaw({
1423
install(app: App) {
24+
setActiveVfm(vfm)
25+
1526
app.provide(vfmSymbol, vfm)
1627
app.config.globalProperties.$vfm = vfm
1728

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

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ import type CoreModal from './components/CoreModal/CoreModal.vue'
66
import { internalVfmSymbol, vfmSymbol } from './injectionSymbols'
77

88
import type { ComponentProps, Constructor, InternalVfm, ModalSlot, ModalSlotOptions, RawProps, UseModalOptions, UseModalOptionsPrivate, UseModalReturnType, Vfm } from './Modal'
9+
import { activeVfm, getActiveVfm, setActiveVfm } from './plugin'
910

1011
/**
1112
* Returns the vfm instance. Equivalent to using `$vfm` inside
1213
* templates.
1314
*/
1415
export function useVfm(): Vfm {
15-
return inject(vfmSymbol)!
16+
return getActiveVfm()!
1617
}
1718

1819
/**
@@ -52,23 +53,31 @@ function withMarkRaw<P>(options: Partial<UseModalOptions<P>>, DefaultComponent:
5253
* Create a dynamic modal.
5354
*/
5455
export function useModal<P = InstanceType<typeof VueFinalModal>['$props']>(_options: UseModalOptions<P>): UseModalReturnType<P> {
56+
const currentInstance = getCurrentInstance()
57+
let vfm = _options.context || (currentInstance && inject(vfmSymbol))
58+
if (vfm)
59+
setActiveVfm(vfm)
60+
61+
if (__DEV__ && !activeVfm) {
62+
throw new Error(
63+
'[🍍]: getActiveVfm was called with no active Vfm. Did you forget to install vfm?\n'
64+
+ '\tconst vfm = createVfm()\n'
65+
+ '\tapp.use(vfm)\n'
66+
+ 'This will fail in production.',
67+
)
68+
}
69+
70+
vfm = activeVfm
71+
5572
const options = reactive({
5673
id: Symbol('useModal'),
74+
context: vfm,
5775
modelValue: !!_options?.defaultModelValue,
5876
resolveOpened: () => { },
5977
resolveClosed: () => { },
6078
attrs: {},
6179
...withMarkRaw<P>(_options),
6280
}) as UseModalOptions<P> & UseModalOptionsPrivate
63-
64-
if (!options.context) {
65-
const currentInstance = getCurrentInstance()
66-
if (currentInstance)
67-
options.context = useVfm()
68-
else if (__DEV__)
69-
console.warn('[Vue Final Modal warn] useModal() can only be used inside setup() or functional components.')
70-
}
71-
7281
tryOnUnmounted(() => {
7382
if (!options.keepAlive)
7483
destroy()
@@ -77,17 +86,13 @@ export function useModal<P = InstanceType<typeof VueFinalModal>['$props']>(_opti
7786
if (options.modelValue === true)
7887
options.context?.dynamicModals.push(options)
7988

80-
function open(opt?: { context: Vfm }): Promise<string> {
81-
if (opt?.context)
82-
options.context = opt.context
83-
if (!options?.context)
84-
return Promise.resolve('[Vue Final Modal] options.context is not exist.')
89+
function open(): Promise<string> {
8590
if (options.modelValue)
8691
return Promise.resolve('[Vue Final Modal] modal is already opened.')
8792

8893
destroy()
8994
options.modelValue = true
90-
options.context.dynamicModals.push(options)
95+
options.context?.dynamicModals.push(options)
9196

9297
return new Promise((resolve) => {
9398
options.resolveOpened = () => resolve('opened')

0 commit comments

Comments
 (0)