123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- <template>
- <div class="ui-popover inline-block" :class="{ hidden: to }">
- <div
- ref="targetEl"
- :class="triggerClass"
- class="ui-popover__trigger h-full inline-block"
- >
- <slot name="trigger" v-bind="{ isShow }"></slot>
- </div>
- <div
- ref="content"
- class="ui-popover__content bg-white dark:bg-gray-800 rounded-lg shadow-xl border"
- :class="[padding]"
- >
- <slot v-bind="{ isShow }"></slot>
- </div>
- </div>
- </template>
- <script>
- import { ref, onMounted, watch, shallowRef, onUnmounted } from 'vue';
- import createTippy from '@/lib/tippy';
- export default {
- props: {
- placement: {
- type: String,
- default: 'bottom',
- },
- trigger: {
- type: String,
- default: 'click',
- },
- padding: {
- type: String,
- default: 'p-4',
- },
- to: {
- type: [String, Object, HTMLElement],
- default: '',
- },
- options: {
- type: Object,
- default: () => ({}),
- },
- disabled: {
- type: Boolean,
- default: false,
- },
- triggerWidth: {
- type: Boolean,
- default: false,
- },
- modelValue: {
- type: Boolean,
- default: false,
- },
- triggerClass: {
- type: String,
- default: null,
- },
- },
- emits: ['show', 'trigger', 'close', 'update:modelValue'],
- setup(props, { emit }) {
- const targetEl = ref(null);
- const content = ref(null);
- const isShow = ref(false);
- const instance = shallowRef(null);
- watch(
- () => props.options,
- (value) => {
- instance.value.setProps(value);
- },
- { deep: true }
- );
- watch(
- () => props.disabled,
- (value) => {
- if (value) {
- instance.value.enable();
- } else {
- instance.value.hide();
- instance.value.disable();
- }
- }
- );
- watch(
- () => props.modelValue,
- (value) => {
- if (value === isShow.value) return;
- isShow.value = value;
- /* eslint-disable-next-line */
- value ? instance.value.show() : instance.value.hide();
- }
- );
- onMounted(() => {
- /* eslint-disable-next-line */
- const target = props.to
- ? typeof to === 'string'
- ? document.querySelector(props.to)
- : props.to
- : targetEl.value;
- instance.value = createTippy(target, {
- role: 'popover',
- theme: null,
- content: content.value,
- placement: props.placement,
- trigger: props.trigger,
- interactive: true,
- appendTo: () => document.body,
- onShow: (event) => {
- if (props.triggerWidth) {
- event.popper.style.width = `${
- event.reference.getBoundingClientRect().width
- }px`;
- }
- emit('show', event);
- isShow.value = true;
- },
- onHide: () => {
- emit('close');
- emit('update:modelValue', false);
- isShow.value = false;
- },
- onTrigger: () => emit('trigger'),
- ...props.options,
- });
- });
- onUnmounted(() => {
- instance.value.destroy();
- });
- return {
- isShow,
- content,
- targetEl,
- };
- },
- };
- </script>
|