<template>
  <div ref="popTitle" :class="[popContainerClass, 'dsd-title-popover']" :style="popContainerStyle">
    <a-popover v-if="visible" ref="popover" v-bind="popoverConfig" :title="title" v-model="popVisible"
      :overlayStyle="overlayStyle">
      <template #content>
        <div class="popoverContent">
          {{ content }}
        </div>
      </template>
      <div ref="popTextContainer" :style="popTextStyle" class="dsd-pop-text cursor-pop">
        <slot></slot>
      </div>
    </a-popover>
    <div v-else ref="popTextContainer" :style="popTextStyle" class="dsd-pop-text">
      <slot></slot>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUpdated, onBeforeUnmount, computed } from 'vue';
const popVisible = ref(false)
const resizeObs = ref()
const visible = ref(true)
const popTitle = ref()
const popTextContainer = ref()
const overlayStyle = reactive({
  width: 'auto'
})
const props = defineProps({
  // 最外围box class
  popContainerClass: {
    type: [String, Array],
    default: null
  },
  // 最外围box style
  popContainerStyle: {
    type: Object,
    default: () => {
    }
  },
  // popover配置
  popConfig: {
    type: Object,
    default: () => {
    }
  },
  // 标题
  title: {
    type: String,
    default: ''
  },
  // 内容
  content: {
    type: String,
    default: ''
  },
  // 根据父节点定位
  positionByParent: {
    type: Boolean,
    default: false
  },
  // 主题
  theme: {
    type: String,
    default: 'lightTooltip' // darkTooltip | lightTooltip
  },
  // 定为节点
  positionNode: {
    type: Function,
    default: () => {
    }
  },
  // 悬浮框宽度,不指定默认与父节点同宽
  overlayWidth: {
    type: String,
    default: ''
  },
  // 文字插槽样式
  popTextStyle: {
    type: Object,
    default: () => {
    }
  }
})
onMounted(() => {
  const resizeObserver = new ResizeObserver(() => {
    sizeUpdate()
  })
  resizeObserver.observe(popTitle.value)
  resizeObs.value = resizeObserver
})
onUpdated(() => {
  sizeUpdate()
})
const popoverConfig = computed(() => {
  let config = props.popConfig
  config.overlayClassName = config.overlayClassName + ' ' + (props.theme === 'darkTooltip' ? props.theme : 'lightTooltip')
  return {
    ...config,
    getPopupContainer: (el) => getPopupContainer(el)
  }
})
const sizeUpdate = () => {
  visible.value = popTextContainer.value.offsetWidth < popTextContainer.value.scrollWidth
  // 悬浮宽度不超过节点
  if (!props.overlayWidth.length) {
    overlayStyle.width = popTextContainer.value.offsetWidth + 'px'
  } else if (props.overlayWidth === 'auto') {
    overlayStyle.width = 'auto'
  } else {
    overlayStyle.width = props.overlayWidth
  }
}
const getPopupContainer = (el) => {
  let positionNode = null
  if (!!props.positionNode(popTitle.value)) {
    positionNode = props.positionNode(popTitle.value)
  } else {
    positionNode = props.positionByParent ? el.parentNode : document.querySelector('#dsdApp')
  }
  return positionNode
}
onBeforeUnmount(() => {
  resizeObs.value.unobserve(popTitle.value)
})
</script>

<style lang="less" scoped>
.dsd-pop-text {
  // 防止文字溢出显示省略号与原本宽度一直导致tooltip不显示
  // width: 100.4%;
  // width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 17px;
}

.cursor-pop {
  cursor: pointer;
}

.popoverContent {
  word-break: break-all;
}

:deep(.dsd-popover) {

  .dsd-popover-inner-content,
  .dsd-popover-inner {
    border-radius: 2px;
  }
}
</style>
<style lang="less">
.darkTooltip {
  .dsd-popover-content {

    .dsd-popover-arrow-content {
      background: rgba(0, 0, 0, 0.7);
    }

    .dsd-popover-inner-content {
      background: rgba(0, 0, 0, 0.7);
      color: #fff;
    }
  }
}
</style>
Handlebars