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"
|
|
|
|
:togglePopover="togglePopover"
|
|
|
|
:handleBlur="handleBlur"
|
|
|
|
></slot>
|
2019-11-22 00:50:30 +05:30
|
|
|
</div>
|
2021-12-30 14:43:28 +05:30
|
|
|
<div
|
|
|
|
ref="popover"
|
|
|
|
:class="popoverClass"
|
2022-02-07 13:53:23 +05:30
|
|
|
class="bg-white rounded border shadow-md popover-container relative z-10"
|
2021-12-30 14:43:28 +05:30
|
|
|
v-show="isOpen"
|
|
|
|
>
|
|
|
|
<div v-if="!hideArrow" class="popover-arrow" ref="popover-arrow"></div>
|
|
|
|
<slot name="content" :togglePopover="togglePopover"></slot>
|
|
|
|
</div>
|
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-02-03 23:22:28 +05:30
|
|
|
hideArrow: {
|
|
|
|
type: Boolean,
|
2021-12-30 14:43:28 +05:30
|
|
|
default: false,
|
2020-02-03 23:22:28 +05:30
|
|
|
},
|
|
|
|
showPopup: {
|
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,
|
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
|
|
|
},
|
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-11-22 00:50:30 +05:30
|
|
|
data() {
|
|
|
|
return {
|
2021-12-30 14:43:28 +05:30
|
|
|
isOpen: false,
|
2019-11-22 00:50:30 +05:30
|
|
|
};
|
|
|
|
},
|
2019-12-11 14:35:46 +05:30
|
|
|
mounted() {
|
2021-12-30 14:43:28 +05:30
|
|
|
let 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();
|
|
|
|
};
|
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,
|
2020-02-03 23:22:28 +05:30
|
|
|
modifiers: !this.hideArrow
|
|
|
|
? [
|
|
|
|
{
|
|
|
|
name: 'arrow',
|
|
|
|
options: {
|
2021-12-30 14:43:28 +05:30
|
|
|
element: this.$refs['popover-arrow'],
|
|
|
|
},
|
2020-02-03 23:22:28 +05:30
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'offset',
|
|
|
|
options: {
|
2021-12-30 14:43:28 +05:30
|
|
|
offset: [0, 10],
|
|
|
|
},
|
|
|
|
},
|
2020-02-03 23:22:28 +05:30
|
|
|
]
|
2021-12-30 14:43:28 +05:30
|
|
|
: [],
|
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');
|
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>
|
2020-01-29 16:31:03 +05:30
|
|
|
<style scoped>
|
|
|
|
.popover-arrow,
|
|
|
|
.popover-arrow::after {
|
|
|
|
position: absolute;
|
2020-02-03 19:17:44 +05:30
|
|
|
width: theme('spacing.4');
|
|
|
|
height: theme('spacing.4');
|
2020-01-29 16:31:03 +05:30
|
|
|
z-index: -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
.popover-arrow::after {
|
|
|
|
content: '';
|
|
|
|
background: white;
|
|
|
|
transform: rotate(45deg);
|
|
|
|
}
|
|
|
|
|
|
|
|
.popover-container[data-popper-placement^='top'] > .popover-arrow {
|
2020-02-03 19:17:44 +05:30
|
|
|
bottom: calc(theme('spacing.2') * -1);
|
2020-01-29 16:31:03 +05:30
|
|
|
}
|
|
|
|
|
2020-04-30 16:43:24 +05:30
|
|
|
.popover-container[data-popper-placement^='top'] > .popover-arrow::after {
|
|
|
|
border-bottom: 1px solid theme('borderColor.gray.400');
|
|
|
|
border-right: 1px solid theme('borderColor.gray.400');
|
|
|
|
border-bottom-right-radius: 6px;
|
|
|
|
}
|
|
|
|
|
2020-01-29 16:31:03 +05:30
|
|
|
.popover-container[data-popper-placement^='bottom'] > .popover-arrow {
|
2020-02-03 19:17:44 +05:30
|
|
|
top: calc(theme('spacing.2') * -1);
|
2020-01-29 16:31:03 +05:30
|
|
|
}
|
|
|
|
|
2020-04-30 16:43:24 +05:30
|
|
|
.popover-container[data-popper-placement^='bottom'] > .popover-arrow::after {
|
|
|
|
border-top: 1px solid theme('borderColor.gray.400');
|
|
|
|
border-left: 1px solid theme('borderColor.gray.400');
|
|
|
|
border-top-left-radius: 6px;
|
|
|
|
}
|
|
|
|
|
2020-01-29 16:31:03 +05:30
|
|
|
.popover-container[data-popper-placement^='left'] > .popover-arrow {
|
2020-02-03 19:17:44 +05:30
|
|
|
right: calc(theme('spacing.2') * -1);
|
2020-01-29 16:31:03 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
.popover-container[data-popper-placement^='right'] > .popover-arrow {
|
2020-02-03 19:17:44 +05:30
|
|
|
left: calc(theme('spacing.2') * -1);
|
2020-01-29 16:31:03 +05:30
|
|
|
}
|
|
|
|
</style>
|