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">
|
2020-01-28 18:32:05 +05:30
|
|
|
<slot name="target" :togglePopover="togglePopover"></slot>
|
2019-11-22 00:50:30 +05:30
|
|
|
</div>
|
2019-12-11 14:35:46 +05:30
|
|
|
<portal to="popovers">
|
|
|
|
<div
|
|
|
|
ref="popover"
|
|
|
|
:class="popoverClass"
|
2020-01-29 16:31:03 +05:30
|
|
|
class="bg-white rounded border min-w-40 shadow-md popover-container relative"
|
2019-12-11 14:35:46 +05:30
|
|
|
v-show="isOpen"
|
|
|
|
>
|
2020-01-29 16:31:03 +05:30
|
|
|
<div class="popover-arrow" ref="popover-arrow"></div>
|
2020-01-28 18:32:05 +05:30
|
|
|
<slot name="content" :togglePopover="togglePopover"></slot>
|
2019-12-11 14:35:46 +05:30
|
|
|
</div>
|
|
|
|
</portal>
|
2019-11-22 00:50:30 +05:30
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
2020-01-29 16:31:03 +05:30
|
|
|
import { createPopper } from '@popperjs/core';
|
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-01-29 16:31:03 +05:30
|
|
|
show: {
|
|
|
|
default: null
|
|
|
|
},
|
2019-12-11 14:35:46 +05:30
|
|
|
right: Boolean,
|
2020-01-29 16:31:03 +05:30
|
|
|
placement: {
|
|
|
|
type: String,
|
|
|
|
default: 'bottom-start'
|
|
|
|
},
|
2019-12-11 14:35:46 +05:30
|
|
|
popoverClass: [String, Object, Array]
|
|
|
|
},
|
2020-01-29 16:31:03 +05:30
|
|
|
watch: {
|
|
|
|
show(value) {
|
|
|
|
if (value === true) {
|
|
|
|
this.open();
|
|
|
|
}
|
|
|
|
if (value === false) {
|
|
|
|
this.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2019-11-22 00:50:30 +05:30
|
|
|
data() {
|
|
|
|
return {
|
2019-12-11 14:35:46 +05:30
|
|
|
isOpen: false
|
2019-11-22 00:50:30 +05:30
|
|
|
};
|
|
|
|
},
|
2019-12-11 14:35:46 +05:30
|
|
|
mounted() {
|
|
|
|
let 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
|
|
|
}
|
2019-12-11 14:35:46 +05:30
|
|
|
this.close();
|
|
|
|
};
|
2020-01-29 16:31:03 +05:30
|
|
|
if (this.show == null) {
|
|
|
|
document.addEventListener('click', listener);
|
|
|
|
this.$once('hook:beforeDestroy', () => {
|
|
|
|
document.removeEventListener('click', listener);
|
|
|
|
});
|
|
|
|
}
|
2019-12-11 14:35:46 +05:30
|
|
|
},
|
|
|
|
beforeDestroy() {
|
2019-12-12 23:10:34 +05:30
|
|
|
this.popper && this.popper.destroy();
|
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,
|
|
|
|
modifiers: [
|
|
|
|
{
|
|
|
|
name: 'arrow',
|
|
|
|
options: {
|
|
|
|
element: this.$refs['popover-arrow']
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'offset',
|
|
|
|
options: {
|
|
|
|
offset: [0, 10]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
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;
|
|
|
|
this.$nextTick(() => {
|
|
|
|
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');
|
2019-11-22 00:50:30 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
</script>
|
2020-01-29 16:31:03 +05:30
|
|
|
<style scoped>
|
|
|
|
.popover-arrow,
|
|
|
|
.popover-arrow::after {
|
|
|
|
position: absolute;
|
|
|
|
width: theme('spacing.3');
|
|
|
|
height: theme('spacing.3');
|
|
|
|
z-index: -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
.popover-arrow::after {
|
|
|
|
content: '';
|
|
|
|
background: white;
|
|
|
|
transform: rotate(45deg);
|
|
|
|
border-top: 1px solid theme('borderColor.gray.400');
|
|
|
|
border-left: 1px solid theme('borderColor.gray.400');
|
|
|
|
}
|
|
|
|
|
|
|
|
.popover-container[data-popper-placement^='top'] > .popover-arrow {
|
|
|
|
bottom: -6px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.popover-container[data-popper-placement^='bottom'] > .popover-arrow {
|
|
|
|
top: -6px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.popover-container[data-popper-placement^='left'] > .popover-arrow {
|
|
|
|
right: -6px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.popover-container[data-popper-placement^='right'] > .popover-arrow {
|
|
|
|
left: -6px;
|
|
|
|
}
|
|
|
|
</style>
|