2
0
mirror of https://github.com/frappe/books.git synced 2025-02-06 05:58:35 +00:00
books/src/components/Popover.vue

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

147 lines
2.9 KiB
Vue
Raw Normal View History

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