Skip to content

Commit 0168ebb

Browse files
Merge pull request #351 from vue-final/fix/0309
Feat 4.1
2 parents 9485c6a + 8946d32 commit 0168ebb

File tree

20 files changed

+138
-201
lines changed

20 files changed

+138
-201
lines changed

.eslintignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
dist
22
node_modules
3-
.cache
4-
deprecated
3+
.cache
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
<script setup lang="ts">
2-
import { ModalsContainer } from 'vue-final-modal'
3-
import ModalDragResize from './ModalDragResize.vue'
2+
import { ModalsContainer, useModal } from 'vue-final-modal'
43
5-
const show = ref(false)
4+
const { open } = useModal({
5+
keepAlive: true,
6+
component: defineAsyncComponent(() => import('./ModalDragResize.vue')),
7+
})
68
</script>
79

810
<template>
9-
<VButton @click="show = true">
11+
<VButton @click="() => open()">
1012
Open Modal
1113
</VButton>
1214

13-
<ModalDragResize v-model="show" />
14-
1515
<ModalsContainer />
1616
</template>

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export type ModalSlot = string | Component | ModalSlotOptions
3232
```ts
3333
export type UseModalOptions<P> = {
3434
defaultModelValue?: boolean
35+
keepAlive?: boolean
3536
context?: Vfm
3637
component?: Constructor<P>
3738
attrs?: (RawProps & P) | ({} extends P ? null : never)
@@ -59,7 +60,7 @@ export interface UseModalReturnType<P> {
5960
options: UseModalOptions<P> & UseModalOptionsPrivate
6061
open: () => Promise<string>
6162
close: () => Promise<string>
62-
patchOptions: (options: Partial<Omit<UseModalOptions<P>, 'defaultModelValue' | 'context'>>) => void
63+
patchOptions: (options: Partial<UseModalOptions<P>>) => void
6364
destroy: () => void
6465
}
6566
```
@@ -71,6 +72,7 @@ export type Vfm = {
7172
install(app: App): void
7273
modals: ComputedRef<Modal>[]
7374
openedModals: ComputedRef<Modal>[]
75+
openedModalOverlays: ComputedRef<Modal>[]
7476
dynamicModals: (UseModalOptions<any> & UseModalOptionsPrivate)[]
7577
modalsContainers: Ref<symbol[]>
7678
get: (modalId: ModalId) => undefined | ComputedRef<Modal>
@@ -88,7 +90,6 @@ export type Modal = {
8890
modalId?: ModalId
8991
hideOverlay: Ref<boolean | undefined> | undefined
9092
overlayVisible: Ref<boolean>
91-
focus: () => void
9293
toggle: (show?: boolean) => Promise<string>
9394
}
9495
```

docs/content/3.api/2.composables/1.use-modal.md

Lines changed: 11 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,17 @@ import { ModalsContainer } from 'vue-final-modal'
2828
```ts
2929
import { VueFinalModal, useModal } from 'vue-final-modal'
3030

31-
const { open, close, options, patchOptions } = useModal({
32-
// `component` is optional and the default value is `<VueFinalModal>`.
33-
component: VueFinalModal,
31+
const { open, close, destroy, options, patchOptions } = useModal({
3432
// Open the modal or not when the modal was created, the default value is `false`.
3533
defaultModelValue: false,
34+
/**
35+
* If set `keepAlive` to `true`:
36+
* 1. The `displayDirective` will be set to `show` by default.
37+
* 2. The modal component will not be removed after the modal closed until you manually execute `destroy()`.
38+
*/
39+
keepAlive: false,
40+
// `component` is optional and the default value is `<VueFinalModal>`.
41+
component: VueFinalModal,
3642
attrs: {
3743
// Bind props to the modal component (VueFinalModal in this case).
3844
clickToClose: true,
@@ -49,6 +55,8 @@ const { open, close, options, patchOptions } = useModal({
4955
open().then(() => { /* Do something after modal opened */ })
5056
// Close the modal
5157
close().then(() => { /* Do something after modal closed */ })
58+
// Destroy the modal manually, it only be needed when the `keepAlive` is set to `true`
59+
destroy()
5260
// Checkout the modal options
5361
options // the state of the dynamic modal
5462

@@ -131,95 +139,6 @@ const modalInstance = useModal({
131139
`useModalSlot()` is a function that provides better DX for type checking. It just returns the same object you passed in.
132140
::
133141

134-
## Edge Usage
135-
136-
::alert{type=danger}
137-
❗️ If you really need to call `useModal()`{lang=ts} outside of `<script setup>`, there is a way to approach it but you must use it carefully.
138-
::
139-
140-
There is a optional property that is `options.context`{lang=ts}, it accept a vfm instance. If given a vfm instance to `options.context`{lang=ts}, `useModal()`{lang=ts} will use the vfm instance internally instead of the injected vfm instance. This will allow you to use `useModal()`{lang=ts} outside out `<script setup>`.
141-
142-
You have to manually calling `modalInstance.destroy()`{lang=ts} whenever you no longer need the dynamic modal instance anymore. Here are some key points that you need to know about `modalInstance.destroy()`{lang=ts} and `modalInstance.close()`{lang=ts}:
143-
144-
- Calling `modalInstance.destroy()`{lang=ts} will delete the modal instance inside of `vfm.dynamicModals`. So if you have an opened modal, the modal will be closed if you calling `modalInstance.destroy()` without calling `modalInstance.close()`{lang=ts}.
145-
- Calling `modalInstance.close()`{lang=ts} will not delete the modal instance inside of `vfm.dynamicModals`. So if you keep calling the `useModal()`{lang=ts}, the length of `vfm.dynamicModals` will keep growing until you have memory leak (see [#277](https://github.com/vue-final/vue-final-modal/issues/277)). This is the reason why you have to manually call `modalInstance.destroy()`{lang=ts} whenever you no longer need the dynamic modal instance anymore (usually in `onClosed` hook).
146-
- Without calling `modalInstance.destroy()`{lang=ts} correctly, the memory leak might occur both on server side (Nuxt 3) and on client side (Vue 3 SPA).
147-
148-
### Vue 3
149-
150-
- You have to create a plugin that export the `vfm` instance:
151-
```ts [@/plugins/vue-final-modal.ts]
152-
import { createVfm } from 'vue-final-modal'
153-
154-
export const vfm = createVfm()
155-
```
156-
- Then you have to import the `vfm` instance in your `main.ts` file and register it as a Vue plugin:
157-
```ts [main.ts]
158-
import { createApp } from 'vue'
159-
import App from './App.vue'
160-
import { vfm } from '@/plugins/vue-final-modal'
161-
162-
const app = createApp(App)
163-
164-
app.use(vfm).mount('#app')
165-
```
166-
- Then you can using `useModal()`{lang=ts} everywhere by given the same `vfm` instance to `options.context`{lang=ts}:
167-
```ts
168-
// Anywhere outside out script setup
169-
import { VueFinalModal, useModal } from 'vue-final-modal'
170-
import { vfm } from '@/plugins/vue-final-modal'
171-
172-
export function openModalConfirm() {
173-
const modalInstance = useModal({
174-
context: vfm,
175-
component: ModalConfirm,
176-
attrs: {
177-
onClosed() {
178-
modalInstance.destroy()
179-
},
180-
},
181-
slots: { default: '<p>The content of the modal</p>' }
182-
})
183-
184-
modalInstance.open()
185-
}
186-
```
187-
188-
### Nuxt 3
189-
190-
- You have to create a plugin that export the `vfm` instance and register it as a Vue plugin:
191-
```ts [@/plugins/vue-final-modal.ts]
192-
import { createVfm } from 'vue-final-modal'
193-
import { defineNuxtPlugin } from '#app'
194-
195-
export const vfm = createVfm() as any
196-
197-
export default defineNuxtPlugin((nuxtApp) => {
198-
nuxtApp.vueApp.use(vfm)
199-
})
200-
```
201-
- Then you can using `useModal()`{lang=ts} everywhere by given the same `vfm` instance to `options.context`{lang=ts}:
202-
```ts
203-
// Anywhere outside out script setup
204-
import { VueFinalModal, useModal } from 'vue-final-modal'
205-
import { vfm } from '@/plugins/vue-final-modal'
206-
207-
export function openModalConfirm() {
208-
const modalInstance = useModal({
209-
context: vfm,
210-
component: ModalConfirm,
211-
attrs: {
212-
onClosed() {
213-
modalInstance.destroy()
214-
},
215-
},
216-
slots: { default: '<p>The content of the modal</p>' }
217-
})
218-
219-
modalInstance.open()
220-
}
221-
```
222-
223142
## Type Declarations
224143

225144
::alert{type=info}

docs/content/4.use-cases/8.modal-drag-resize.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ Here is a basic drag and resize modal example that using [vue3-drag-resize](http
1818

1919
```vue [Preview.vue]
2020
<script setup lang="ts">
21-
import { ModalsContainer } from 'vue-final-modal'
22-
import ModalDragResize from './ModalDragResize.vue'
21+
import { ModalsContainer, useModal } from 'vue-final-modal'
2322
24-
const show = ref(false)
23+
const { open } = useModal({
24+
keepAlive: true,
25+
component: defineAsyncComponent(() => import('./ModalDragResize.vue')),
26+
})
2527
</script>
2628
2729
<template>
28-
<VButton @click="show = true">
30+
<VButton @click="() => open()">
2931
Open Modal
3032
</VButton>
3133
32-
<ModalDragResize v-model="show" />
33-
3434
<ModalsContainer />
3535
</template>
3636
```

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/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11

22

3+
# [4.1.0](https://github.com/vue-final/vue-final-modal/compare/v4.0.11...v4.1.0) (2023-03-28)
4+
5+
6+
### Bug Fixes
7+
8+
* **transition:** only set transition appear when displayDirective is set to `if`, because of the focusTrap should be activated until the modal transition end ([7e38512](https://github.com/vue-final/vue-final-modal/commit/7e38512e0f52bc530c2694b45b805aef702f3a96))
9+
* type ([c820c02](https://github.com/vue-final/vue-final-modal/commit/c820c0221b94fc4ce4e7dc3114ff2fb6faeccea8))
10+
11+
12+
### Features
13+
14+
* Add activeVfm (inspire by pinia), so we don't need to pass down `vfm` instance anymore. We can use `useVfm()` and `useModal()` out of setup script ([8ee2021](https://github.com/vue-final/vue-final-modal/commit/8ee2021adc5e97fdcb626c79824c4e8090dcf7c0))
15+
* Destroy dynamic modal onClosed by default and add `keepAlive` option for keeping modal instance alive after `modal.close()` ([f2cb5bf](https://github.com/vue-final/vue-final-modal/commit/f2cb5bf58d0ba6248018621b079d0e0e7037c472))
16+
317
## [4.0.11](https://github.com/vue-final/vue-final-modal/compare/v4.0.10...v4.0.11) (2023-03-08)
418

519

packages/vue-final-modal/cypress.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { defineConfig } from 'cypress'
22

33
export default defineConfig({
44
component: {
5+
video: false,
6+
screenshotOnRunFailure: false,
57
specPattern: 'cypress/components/**/*.spec.ts',
68
devServer: {
79
framework: 'vue',
Binary file not shown.

0 commit comments

Comments
 (0)