From 8bfb1ecfda9a9626dba6677ead9b452a06968027 Mon Sep 17 00:00:00 2001 From: Georges KABBOUCHI Date: Wed, 26 Jun 2024 20:18:11 +0300 Subject: [PATCH] reactive singleton --- docs/content/en/flavor/composition-api.md | 4 +- package.json | 4 +- playground/pages/Index.vue | 940 +++++++++++----------- playground/pages/SingletonComponents.vue | 92 ++- src/components/TippySingleton.ts | 16 +- src/composables/useSingleton.ts | 21 +- src/composables/useTippy.ts | 23 +- yarn.lock | 124 ++- 8 files changed, 688 insertions(+), 536 deletions(-) diff --git a/docs/content/en/flavor/composition-api.md b/docs/content/en/flavor/composition-api.md index f219495..9b3ad52 100644 --- a/docs/content/en/flavor/composition-api.md +++ b/docs/content/en/flavor/composition-api.md @@ -91,8 +91,8 @@ useTippy(btn, { ```vue diff --git a/package.json b/package.json index f1a9ac4..42c7736 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-tippy", - "version": "6.4.1", + "version": "6.4.2", "main": "index.js", "module": "dist/vue-tippy.mjs", "unpkg": "dist/vue-tippy.iife.js", @@ -68,7 +68,7 @@ "ts-loader": "^8.0.2", "ts-node": "^8.10.2", "typescript": "^4.1.3", - "vue": "^3.2.0", + "vue": "3.2.47", "vue-loader": "^16.0.0-beta.8", "vue-router": "4", "webpack": "^4.44.1", diff --git a/playground/pages/Index.vue b/playground/pages/Index.vue index b53672d..426f48d 100644 --- a/playground/pages/Index.vue +++ b/playground/pages/Index.vue @@ -1,486 +1,502 @@ \ No newline at end of file + diff --git a/playground/pages/SingletonComponents.vue b/playground/pages/SingletonComponents.vue index 0bac76a..b4090e9 100644 --- a/playground/pages/SingletonComponents.vue +++ b/playground/pages/SingletonComponents.vue @@ -1,23 +1,79 @@ \ No newline at end of file + name: 'App', + setup() { + const tippyRefs = ref([]) + + useSingleton(tippyRefs, { + moveTransition: 'transform 0.2s ease-out', + delay: [250, 50], + placement: 'bottom', + }) + + watch(tippyRefs, () => { + console.log('tippyRefs', tippyRefs.value) + }) + + return { + tippyRefs, + log: console.log, + } + }, + data() { + return { + count: 10, + } + }, +} + diff --git a/src/components/TippySingleton.ts b/src/components/TippySingleton.ts index 0860420..98b2b7d 100644 --- a/src/components/TippySingleton.ts +++ b/src/components/TippySingleton.ts @@ -44,7 +44,6 @@ Object.keys(tippy.defaultProps).forEach((prop: string) => { } }) - const TippySingleton = defineComponent({ props, setup(props) { @@ -61,9 +60,20 @@ const TippySingleton = defineComponent({ this.instances = Array.from(elements) .map((el: any) => el._tippy) .filter(Boolean) - - this.singleton?.setInstances(this.instances) }, + + updated() { + const parent = this.$el?.parentElement + + if (parent) { + const elements = parent.querySelectorAll('[data-v-tippy]') + + this.instances = Array.from(elements) + .map((el: any) => el._tippy) + .filter(Boolean) + } + }, + render() { let slot = this.$slots.default ? this.$slots.default() : [] diff --git a/src/composables/useSingleton.ts b/src/composables/useSingleton.ts index 86b08f4..f2c731b 100644 --- a/src/composables/useSingleton.ts +++ b/src/composables/useSingleton.ts @@ -5,7 +5,7 @@ import { Instance, Props, } from 'tippy.js' -import { onMounted, ref } from 'vue' +import { onMounted, ref, watch } from 'vue' export function useSingleton( instances: TippyInstances, @@ -13,12 +13,12 @@ export function useSingleton( ) { const singleton = ref>() - onMounted(() => { + const getTippyInstances = () => { const pendingTippyInstances: TippyInstance[] = Array.isArray(instances) ? instances.map(i => i.value) : typeof instances === 'function' - ? instances() - : instances.value + ? instances() + : instances.value const tippyInstances: Instance[] = pendingTippyInstances .map((instance: TippyInstance) => { @@ -30,14 +30,25 @@ export function useSingleton( }) .filter(Boolean) + return tippyInstances + } + + onMounted(() => { singleton.value = createSingleton( - tippyInstances, + getTippyInstances(), optionalProps ? { allowHTML: true, ...optionalProps } : { allowHTML: true } ) }) + watch( + Array.isArray(instances) ? () => instances.map(i => i.value) : instances, + () => { + singleton.value?.setInstances(getTippyInstances()) + } + ) + return { singleton, } diff --git a/src/composables/useTippy.ts b/src/composables/useTippy.ts index bf0137c..f68c04e 100644 --- a/src/composables/useTippy.ts +++ b/src/composables/useTippy.ts @@ -28,11 +28,11 @@ export function useTippy( el: Element | (() => Element) | Ref | Ref, opts: TippyOptions = {}, settings: { - mount: boolean, - appName: string, + mount: boolean + appName: string } = { mount: true, appName: 'Tippy' } ) { - settings = Object.assign({ mount: true, appName: 'Tippy' }, settings); + settings = Object.assign({ mount: true, appName: 'Tippy' }, settings) const vm = getCurrentInstance() const instance = ref() @@ -62,13 +62,12 @@ export function useTippy( ? content.value : content - if (isVNode(unwrappedContent)) { if (!headlessApp.value) { headlessApp.value = createApp({ name: settings.appName, setup: () => { - return () => isRef(content) ? content.value : content + return () => (isRef(content) ? content.value : content) }, }) @@ -84,7 +83,7 @@ export function useTippy( headlessApp.value = createApp({ name: settings.appName, setup: () => { - return () => h(isRef(content) ? content.value : content as any) + return () => h(isRef(content) ? content.value : (content as any)) }, }) @@ -128,7 +127,9 @@ export function useTippy( options.plugins = [] } - options.plugins = options.plugins.filter((plugin: any) => plugin.name !== 'vueTippyReactiveState'); + options.plugins = options.plugins.filter( + (plugin: any) => plugin.name !== 'vueTippyReactiveState' + ) options.plugins.push({ name: 'vueTippyReactiveState', @@ -161,7 +162,7 @@ export function useTippy( state.value.isDestroyed = true }, } - } + }, }) return options as Props @@ -192,7 +193,7 @@ export function useTippy( try { //@ts-ignore // delete instance.value.reference.$tippy - } catch (error) { } + } catch (error) {} instance.value.destroy() instance.value = undefined @@ -212,12 +213,12 @@ export function useTippy( const disable = () => { instance.value?.disable() - state.value.isEnabled = false; + state.value.isEnabled = false } const enable = () => { instance.value?.enable() - state.value.isEnabled = true; + state.value.isEnabled = true } const unmount = () => { diff --git a/yarn.lock b/yarn.lock index c2987eb..4abf473 100644 --- a/yarn.lock +++ b/yarn.lock @@ -251,6 +251,16 @@ estree-walker "^2.0.2" source-map "^0.6.1" +"@vue/compiler-core@3.2.47": + version "3.2.47" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.47.tgz#3e07c684d74897ac9aa5922c520741f3029267f8" + integrity sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/shared" "3.2.47" + estree-walker "^2.0.2" + source-map "^0.6.1" + "@vue/compiler-dom@3.2.37": version "3.2.37" resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz#10d2427a789e7c707c872da9d678c82a0c6582b5" @@ -259,7 +269,31 @@ "@vue/compiler-core" "3.2.37" "@vue/shared" "3.2.37" -"@vue/compiler-sfc@3.2.37", "@vue/compiler-sfc@^3.2.0": +"@vue/compiler-dom@3.2.47": + version "3.2.47" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz#a0b06caf7ef7056939e563dcaa9cbde30794f305" + integrity sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ== + dependencies: + "@vue/compiler-core" "3.2.47" + "@vue/shared" "3.2.47" + +"@vue/compiler-sfc@3.2.47": + version "3.2.47" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz#1bdc36f6cdc1643f72e2c397eb1a398f5004ad3d" + integrity sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.47" + "@vue/compiler-dom" "3.2.47" + "@vue/compiler-ssr" "3.2.47" + "@vue/reactivity-transform" "3.2.47" + "@vue/shared" "3.2.47" + estree-walker "^2.0.2" + magic-string "^0.25.7" + postcss "^8.1.10" + source-map "^0.6.1" + +"@vue/compiler-sfc@^3.2.0": version "3.2.37" resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz#3103af3da2f40286edcd85ea495dcb35bc7f5ff4" integrity sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg== @@ -283,6 +317,14 @@ "@vue/compiler-dom" "3.2.37" "@vue/shared" "3.2.37" +"@vue/compiler-ssr@3.2.47": + version "3.2.47" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz#35872c01a273aac4d6070ab9d8da918ab13057ee" + integrity sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw== + dependencies: + "@vue/compiler-dom" "3.2.47" + "@vue/shared" "3.2.47" + "@vue/reactivity-transform@3.2.37": version "3.2.37" resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.37.tgz#0caa47c4344df4ae59f5a05dde2a8758829f8eca" @@ -294,43 +336,59 @@ estree-walker "^2.0.2" magic-string "^0.25.7" -"@vue/reactivity@3.2.37": - version "3.2.37" - resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.37.tgz#5bc3847ac58828e2b78526e08219e0a1089f8848" - integrity sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A== +"@vue/reactivity-transform@3.2.47": + version "3.2.47" + resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz#e45df4d06370f8abf29081a16afd25cffba6d84e" + integrity sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA== dependencies: - "@vue/shared" "3.2.37" + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.47" + "@vue/shared" "3.2.47" + estree-walker "^2.0.2" + magic-string "^0.25.7" -"@vue/runtime-core@3.2.37": - version "3.2.37" - resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.37.tgz#7ba7c54bb56e5d70edfc2f05766e1ca8519966e3" - integrity sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ== +"@vue/reactivity@3.2.47": + version "3.2.47" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.47.tgz#1d6399074eadfc3ed35c727e2fd707d6881140b6" + integrity sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ== dependencies: - "@vue/reactivity" "3.2.37" - "@vue/shared" "3.2.37" + "@vue/shared" "3.2.47" -"@vue/runtime-dom@3.2.37": - version "3.2.37" - resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.37.tgz#002bdc8228fa63949317756fb1e92cdd3f9f4bbd" - integrity sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw== +"@vue/runtime-core@3.2.47": + version "3.2.47" + resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.47.tgz#406ebade3d5551c00fc6409bbc1eeb10f32e121d" + integrity sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA== dependencies: - "@vue/runtime-core" "3.2.37" - "@vue/shared" "3.2.37" + "@vue/reactivity" "3.2.47" + "@vue/shared" "3.2.47" + +"@vue/runtime-dom@3.2.47": + version "3.2.47" + resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz#93e760eeaeab84dedfb7c3eaf3ed58d776299382" + integrity sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA== + dependencies: + "@vue/runtime-core" "3.2.47" + "@vue/shared" "3.2.47" csstype "^2.6.8" -"@vue/server-renderer@3.2.37": - version "3.2.37" - resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.37.tgz#840a29c8dcc29bddd9b5f5ffa22b95c0e72afdfc" - integrity sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA== +"@vue/server-renderer@3.2.47": + version "3.2.47" + resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.47.tgz#8aa1d1871fc4eb5a7851aa7f741f8f700e6de3c0" + integrity sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA== dependencies: - "@vue/compiler-ssr" "3.2.37" - "@vue/shared" "3.2.37" + "@vue/compiler-ssr" "3.2.47" + "@vue/shared" "3.2.47" "@vue/shared@3.2.37": version "3.2.37" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.37.tgz#8e6adc3f2759af52f0e85863dfb0b711ecc5c702" integrity sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw== +"@vue/shared@3.2.47": + version "3.2.47" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.47.tgz#e597ef75086c6e896ff5478a6bfc0a7aa4bbd14c" + integrity sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ== + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" @@ -5823,16 +5881,16 @@ vue-router@4: resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.0.3.tgz#8b26050c88b2dec7e27a88835f71046b365823ec" integrity sha512-AD1OjtVPyQHTSpoRsEGfPpxRQwhAhxcacOYO3zJ3KNkYP/r09mileSp6kdMQKhZWP2cFsPR3E2M3PZguSN5/ww== -vue@^3.2.0: - version "3.2.37" - resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.37.tgz#da220ccb618d78579d25b06c7c21498ca4e5452e" - integrity sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ== +vue@3.2.47: + version "3.2.47" + resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.47.tgz#3eb736cbc606fc87038dbba6a154707c8a34cff0" + integrity sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ== dependencies: - "@vue/compiler-dom" "3.2.37" - "@vue/compiler-sfc" "3.2.37" - "@vue/runtime-dom" "3.2.37" - "@vue/server-renderer" "3.2.37" - "@vue/shared" "3.2.37" + "@vue/compiler-dom" "3.2.47" + "@vue/compiler-sfc" "3.2.47" + "@vue/runtime-dom" "3.2.47" + "@vue/server-renderer" "3.2.47" + "@vue/shared" "3.2.47" watchpack-chokidar2@^2.0.1: version "2.0.1"