diff --git a/dev/serve.vue b/dev/serve.vue index c696606..f5a1e91 100644 --- a/dev/serve.vue +++ b/dev/serve.vue @@ -6,6 +6,24 @@
This is the content
+ + + + + + + + + + + + diff --git a/docs/guide/api.md b/docs/guide/api.md index 730a066..f252cb7 100755 --- a/docs/guide/api.md +++ b/docs/guide/api.md @@ -18,6 +18,7 @@ | `content` | `null` | If your content is just a simple string, you can pass it as a prop | | `show` | `null` | Control the Popper **manually**, other events (click, hover) are ignored if this is set to `true/false` | | `zIndex` | `9999` | The z-index of the Popper | +| `teleport` | `null` | Teleport Popper element to selector specified | ## Events diff --git a/package-lock.json b/package-lock.json index ce045be..b385dff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,6 @@ "requires": true, "packages": { "": { - "name": "vue3-popper", "version": "1.2.1", "license": "MIT", "dependencies": { diff --git a/src/component/Popper.vue b/src/component/Popper.vue index 16f9005..1808192 100644 --- a/src/component/Popper.vue +++ b/src/component/Popper.vue @@ -1,12 +1,12 @@ @@ -44,6 +48,7 @@ } from "vue"; import { usePopper, useContent } from "@/composables"; import clickAway from "@/directives"; + import PopperTeleportWrapper from './PopperTeleportWrapper.vue' /* Delay execution for a set amount of milliseconds */ const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); @@ -57,6 +62,9 @@ directives: { clickAway, }, + components: { + PopperTeleportWrapper, + }, props: { /** * Preferred placement (the "auto" placements will choose the side with most space.) @@ -175,6 +183,31 @@ type: String, default: null, }, + /** + * Teleport popper element to selector + */ + teleport: { + type: String, + default: null, + }, + }, + data() { + return { + isHovered: false, + } + }, + methods: { + mouseEnter() { + this.isHovered = true; + this.openPopper(); + }, + async mouseLeave() { + this.isHovered = false; + await delay(50); + if(!this.isHovered) { + this.closePopper(); + } + }, }, setup(props, { slots, emit }) { const children = slots.default(); diff --git a/src/component/PopperTeleportWrapper.vue b/src/component/PopperTeleportWrapper.vue new file mode 100644 index 0000000..646e630 --- /dev/null +++ b/src/component/PopperTeleportWrapper.vue @@ -0,0 +1,25 @@ + + + \ No newline at end of file diff --git a/src/directives/click-away.js b/src/directives/click-away.js index b950931..1bd216c 100644 --- a/src/directives/click-away.js +++ b/src/directives/click-away.js @@ -1,11 +1,21 @@ export default { beforeMount: (el, binding) => { el.clickAwayEvent = event => { + if(!binding.value.enabled) { + return; + } + + const allowedEls = [el]; + if(Array.isArray(binding.value.ignore)) { + binding.value.ignore.forEach((refName) => { + allowedEls.push(binding.instance.$refs[refName]); + }); + } + const safeClickedEl = allowedEls.find((element) => + element != null && (element == event.target || element.contains(event.target)) + ); // Clicked outside of the element and its children - if ( - !(el == event.target || el.contains(event.target)) && - binding.value.enabled - ) { + if (!safeClickedEl) { // Call the provided method binding.value.handler(); }