From 7b99e6ad925d312f705f619a74dd5eed3cfe8ef1 Mon Sep 17 00:00:00 2001 From: Edmunds Kalnins Date: Thu, 23 May 2024 17:15:28 +0300 Subject: [PATCH] Patch from https://github.com/euvl/vue-js-modal/issues/814 --- src/Plugin.js | 19 ++++++++++--------- src/PluginCore.js | 28 +++++++++++++++++++--------- src/components/Dialog.vue | 3 ++- src/components/Modal.vue | 7 +++++-- src/components/ModalsContainer.vue | 1 + 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/Plugin.js b/src/Plugin.js index 5043c87a..3e0e7f7b 100644 --- a/src/Plugin.js +++ b/src/Plugin.js @@ -3,14 +3,14 @@ import Dialog from './components/Dialog.vue' import PluginCore from './PluginCore' const Plugin = { - install(Vue, options = {}) { - if (Vue.prototype.$modal) { + install(app, options = {}) { + if (app.config.globalProperties.$modal) { return } - const plugin = new PluginCore(Vue, options) + const plugin = PluginCore(app, options) - Object.defineProperty(Vue.prototype, '$modal', { + Object.defineProperty(app.config.globalProperties, '$modal', { get: function() { /** * The "this" scope is the scope of the component that calls this.$modal @@ -19,29 +19,30 @@ const Plugin = { /** * The this.$modal can be called only from inside the vue components so this check is not really needed... */ - if (caller instanceof Vue) { + // if (caller instanceof app) { const root = caller.$root if (!plugin.context.root) { - plugin.setDynamicModalContainer(root) + plugin.setDynamicModalContainer(root, app) } - } + // } return plugin } }) + app.provide('$modal', plugin) /** * Sets custom component name (if provided) */ - Vue.component(plugin.context.componentName, Modal) + app.component(plugin.context.componentName, Modal) /** * Registration of component */ if (options.dialog) { const componentName = options.dialogComponentName || 'VDialog'; - Vue.component(componentName, Dialog); + app.component(componentName, Dialog); } } } diff --git a/src/PluginCore.js b/src/PluginCore.js index bf0cd6c8..94460ce8 100644 --- a/src/PluginCore.js +++ b/src/PluginCore.js @@ -1,14 +1,24 @@ import { UNSUPPORTED_ARGUMENT_ERROR } from './utils/errors' import { createDivInBody } from './utils' import ModalsContainer from './components/ModalsContainer.vue' - -const PluginCore = (Vue, options = {}) => { - const subscription = new Vue() +import emitter from 'tiny-emitter/instance' +import {createVNode, render} from 'vue' + +const PluginCore = (app, options = {}) => { + const subscription = { + $on: (...args) => emitter.on(...args), + $once: (...args) => emitter.once(...args), + $off: (...args) => emitter.off(...args), + $emit: (...args) => emitter.emit(...args), + } const context = { root: null, componentName: options.componentName || 'Modal' } + subscription.$on('set-modal-container', container => { + context.root.__modalContainer = container + }) const showStaticModal = (name, params) => { subscription.$emit('toggle', name, true, params) @@ -37,17 +47,17 @@ const PluginCore = (Vue, options = {}) => { * Creates a container for modals in the root Vue component. * * @param {Vue} parent + * @param {Vue} app */ - const setDynamicModalContainer = parent => { + const setDynamicModalContainer = ((parent, app) => { context.root = parent const element = createDivInBody() - new Vue({ - parent, - render: h => h(ModalsContainer) - }).$mount(element) - } + const vnode = createVNode(ModalsContainer) + vnode.appContext = app._context + render(vnode, element) + }) const show = (...args) => { const [modal] = args diff --git a/src/components/Dialog.vue b/src/components/Dialog.vue index 7c3e784e..888bafb3 100644 --- a/src/components/Dialog.vue +++ b/src/components/Dialog.vue @@ -31,7 +31,7 @@ :key="index" v-html="button.title" @click.stop="click(index, $event)" - >{{ button.title }} + />
@@ -52,6 +52,7 @@ export default { type: String } }, + inject: ['$modal'], data() { return { params: {} diff --git a/src/components/Modal.vue b/src/components/Modal.vue index a36c9a5b..0b25a848 100644 --- a/src/components/Modal.vue +++ b/src/components/Modal.vue @@ -77,6 +77,7 @@ const TransitionState = { export default { name: 'VueJsModal', + inject: ['$modal'], props: { name: { required: true, @@ -263,7 +264,7 @@ export default { /** * Removes global listeners */ - beforeDestroy() { + beforeUnmount() { this.$modal.subscription.$off('toggle', this.onToggle) window.removeEventListener('resize', this.onWindowResize) @@ -498,7 +499,9 @@ export default { beforeModalTransitionLeave() { this.modalTransitionState = TransitionState.Leaving - this.resizeObserver.unobserve(this.$refs.modal) + if (this.$refs.modal) { + this.resizeObserver.unobserve(this.$refs.modal) + } if (this.$focusTrap.enabled()) { this.$focusTrap.disable() diff --git a/src/components/ModalsContainer.vue b/src/components/ModalsContainer.vue index a27cb6cd..d9467ad7 100644 --- a/src/components/ModalsContainer.vue +++ b/src/components/ModalsContainer.vue @@ -40,6 +40,7 @@ export default { * Register ModalContainer so that it was availiable inside the plugin */ this.$root.__modalContainer = this + this.$modal.subscription.$emit('set-modal-container', this) }, mounted() { this.$modal.subscription.$on('hide-all', () => {