2019-11-22 00:50:30 +05:30
|
|
|
<template>
|
2019-12-11 14:35:46 +05:30
|
|
|
<div ref="reference">
|
2019-11-22 00:50:30 +05:30
|
|
|
<div class="h-full">
|
2022-01-12 13:28:33 +05:30
|
|
|
<slot
|
|
|
|
name="target"
|
2023-06-23 12:35:44 +05:30
|
|
|
:toggle-popover="togglePopover"
|
|
|
|
:handle-blur="handleBlur"
|
2022-01-12 13:28:33 +05:30
|
|
|
></slot>
|
2019-11-22 00:50:30 +05:30
|
|
|
</div>
|
2023-04-18 10:03:29 +05:30
|
|
|
<Transition>
|
|
|
|
<div
|
2023-06-23 12:35:44 +05:30
|
|
|
v-show="isOpen"
|
2023-04-18 10:03:29 +05:30
|
|
|
ref="popover"
|
|
|
|
:class="popoverClass"
|
|
|
|
class="
|
|
|
|
bg-white
|
|
|
|
rounded-md
|
|
|
|
border
|
2023-04-18 10:44:09 +05:30
|
|
|
shadow-lg
|
2023-04-18 10:03:29 +05:30
|
|
|
popover-container
|
|
|
|
relative
|
|
|
|
z-10
|
|
|
|
"
|
|
|
|
:style="{ 'transition-delay': `${isOpen ? entryDelay : exitDelay}ms` }"
|
|
|
|
>
|
2023-06-23 12:35:44 +05:30
|
|
|
<slot name="content" :toggle-popover="togglePopover"></slot>
|
2023-04-18 10:03:29 +05:30
|
|
|
</div>
|
|
|
|
</Transition>
|
2019-11-22 00:50:30 +05:30
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
2020-01-29 16:31:03 +05:30
|
|
|
import { createPopper } from '@popperjs/core';
|
2022-05-01 13:09:03 +05:30
|
|
|
import { nextTick } from 'vue';
|
2019-12-11 14:35:46 +05:30
|
|
|
|
2019-11-22 00:50:30 +05:30
|
|
|
export default {
|
|
|
|
name: 'Popover',
|
2019-12-11 14:35:46 +05:30
|
|
|
props: {
|
2020-02-03 23:22:28 +05:30
|
|
|
showPopup: {
|
2023-03-20 11:10:07 +05:30
|
|
|
type: [Boolean, null],
|
2021-12-30 14:43:28 +05:30
|
|
|
default: null,
|
2020-01-29 16:31:03 +05:30
|
|
|
},
|
2019-12-11 14:35:46 +05:30
|
|
|
right: Boolean,
|
2023-04-18 10:03:29 +05:30
|
|
|
entryDelay: { type: Number, default: 0 },
|
|
|
|
exitDelay: { type: Number, default: 0 },
|
2020-01-29 16:31:03 +05:30
|
|
|
placement: {
|
|
|
|
type: String,
|
2021-12-30 14:43:28 +05:30
|
|
|
default: 'bottom-start',
|
2020-01-29 16:31:03 +05:30
|
|
|
},
|
2021-12-30 14:43:28 +05:30
|
|
|
popoverClass: [String, Object, Array],
|
2019-12-11 14:35:46 +05:30
|
|
|
},
|
2023-06-23 12:35:44 +05:30
|
|
|
emits: ['open', 'close'],
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
isOpen: false,
|
|
|
|
};
|
|
|
|
},
|
2020-01-29 16:31:03 +05:30
|
|
|
watch: {
|
2020-02-03 23:22:28 +05:30
|
|
|
showPopup(value) {
|
2020-01-29 16:31:03 +05:30
|
|
|
if (value === true) {
|
|
|
|
this.open();
|
|
|
|
}
|
|
|
|
if (value === false) {
|
|
|
|
this.close();
|
|
|
|
}
|
2021-12-30 14:43:28 +05:30
|
|
|
},
|
2020-01-29 16:31:03 +05:30
|
|
|
},
|
2019-12-11 14:35:46 +05:30
|
|
|
mounted() {
|
2022-02-10 12:11:51 +05:30
|
|
|
this.listener = (e) => {
|
2019-12-11 14:35:46 +05:30
|
|
|
let $els = [this.$refs.reference, this.$refs.popover];
|
|
|
|
let insideClick = $els.some(
|
2021-12-30 14:43:28 +05:30
|
|
|
($el) => $el && (e.target === $el || $el.contains(e.target))
|
2019-12-11 14:35:46 +05:30
|
|
|
);
|
|
|
|
if (insideClick) {
|
|
|
|
return;
|
2019-11-22 00:50:30 +05:30
|
|
|
}
|
2019-12-11 14:35:46 +05:30
|
|
|
this.close();
|
|
|
|
};
|
2022-02-10 12:11:51 +05:30
|
|
|
|
2020-01-29 16:31:03 +05:30
|
|
|
if (this.show == null) {
|
2022-02-10 12:11:51 +05:30
|
|
|
document.addEventListener('click', this.listener);
|
2020-01-29 16:31:03 +05:30
|
|
|
}
|
2019-12-11 14:35:46 +05:30
|
|
|
},
|
2022-02-10 14:40:30 +05:30
|
|
|
beforeUnmount() {
|
2019-12-12 23:10:34 +05:30
|
|
|
this.popper && this.popper.destroy();
|
2022-02-10 12:11:51 +05:30
|
|
|
if (this.listener) {
|
|
|
|
document.removeEventListener('click', this.listener);
|
|
|
|
delete this.listener;
|
|
|
|
}
|
2019-11-22 00:50:30 +05:30
|
|
|
},
|
|
|
|
methods: {
|
2019-12-11 14:35:46 +05:30
|
|
|
setupPopper() {
|
|
|
|
if (!this.popper) {
|
2020-01-29 16:31:03 +05:30
|
|
|
this.popper = createPopper(this.$refs.reference, this.$refs.popover, {
|
|
|
|
placement: this.placement,
|
2022-10-12 01:50:15 +05:30
|
|
|
modifiers: [{ name: 'offset', options: { offset: [0, 8] } }],
|
2019-12-11 14:35:46 +05:30
|
|
|
});
|
|
|
|
} else {
|
2020-01-29 16:31:03 +05:30
|
|
|
this.popper.update();
|
2019-12-11 14:35:46 +05:30
|
|
|
}
|
|
|
|
},
|
2020-01-28 18:32:05 +05:30
|
|
|
togglePopover(flag) {
|
2019-11-22 00:50:30 +05:30
|
|
|
if (flag == null) {
|
2019-12-11 14:35:46 +05:30
|
|
|
flag = !this.isOpen;
|
|
|
|
}
|
|
|
|
flag = Boolean(flag);
|
|
|
|
if (flag) {
|
|
|
|
this.open();
|
|
|
|
} else {
|
|
|
|
this.close();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
open() {
|
|
|
|
if (this.isOpen) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.isOpen = true;
|
2022-05-01 13:09:03 +05:30
|
|
|
nextTick(() => {
|
2019-12-11 14:35:46 +05:30
|
|
|
this.setupPopper();
|
|
|
|
});
|
|
|
|
this.$emit('open');
|
|
|
|
},
|
|
|
|
close() {
|
|
|
|
if (!this.isOpen) {
|
|
|
|
return;
|
2019-11-22 00:50:30 +05:30
|
|
|
}
|
2019-12-11 14:35:46 +05:30
|
|
|
this.isOpen = false;
|
|
|
|
this.$emit('close');
|
2021-12-30 14:43:28 +05:30
|
|
|
},
|
2022-01-12 13:28:33 +05:30
|
|
|
handleBlur({ relatedTarget }) {
|
|
|
|
relatedTarget && this.close();
|
|
|
|
},
|
2021-12-30 14:43:28 +05:30
|
|
|
},
|
2019-11-22 00:50:30 +05:30
|
|
|
};
|
|
|
|
</script>
|
2023-04-18 10:03:29 +05:30
|
|
|
<style scoped>
|
|
|
|
.v-enter-active,
|
|
|
|
.v-leave-active {
|
|
|
|
transition: opacity 150ms ease-out;
|
|
|
|
}
|
|
|
|
|
|
|
|
.v-enter-from,
|
|
|
|
.v-leave-to {
|
|
|
|
opacity: 0;
|
|
|
|
}
|
|
|
|
</style>
|