|
|
@@ -0,0 +1,81 @@
|
|
|
+import Vue from 'vue'
|
|
|
+import {computePosition, offset, flip, shift, arrow} from '@floating-ui/dom';
|
|
|
+
|
|
|
+Vue.directive('tooltip', {
|
|
|
+ bind: function (el, binding) {
|
|
|
+ if (!binding.value) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ let tooltipNode = null
|
|
|
+ el.addEventListener('mouseenter', function(e) {
|
|
|
+ tooltipNode = document.createElement('div')
|
|
|
+ tooltipNode.style.position = 'fixed'
|
|
|
+ tooltipNode.style.zIndex = 100
|
|
|
+ tooltipNode.style.backgroundColor = '#191A1C'
|
|
|
+ tooltipNode.style.border = '1px solid rgba(151, 151, 151, 0.2)'
|
|
|
+ tooltipNode.style.borderRadius = '3px'
|
|
|
+ tooltipNode.style.border = '1px solid rgba(151, 151, 151, 0.2)'
|
|
|
+ tooltipNode.style.boxShadow = '0px 2px 12px 0px rgba(0, 0, 0, 0.06)'
|
|
|
+ tooltipNode.style.padding = '8px 8px'
|
|
|
+ tooltipNode.style.fontSize = '12px'
|
|
|
+ tooltipNode.style.cursor = 'default'
|
|
|
+ tooltipNode.style.pointerEvents = 'none'
|
|
|
+ tooltipNode.style.wordBreak = 'keep-all'
|
|
|
+ tooltipNode.style.whiteSpace = 'pre'
|
|
|
+ tooltipNode.style.fontSize = '12px'
|
|
|
+ tooltipNode.style.lineHeight = '17px'
|
|
|
+ tooltipNode.style.color = 'rgba(255, 255, 255, 0.6)'
|
|
|
+ tooltipNode.innerText = binding.value
|
|
|
+
|
|
|
+ const arrowNode = document.createElement('div')
|
|
|
+ arrowNode.style.position = 'absolute'
|
|
|
+ arrowNode.style.backgroundColor = 'inherit'
|
|
|
+ arrowNode.style.boxSizing = 'border-box'
|
|
|
+ arrowNode.style.width = '12px'
|
|
|
+ arrowNode.style.height = '12px'
|
|
|
+ arrowNode.style.border = '1px solid transparent'
|
|
|
+ arrowNode.style.borderRight = 'inherit'
|
|
|
+ arrowNode.style.borderBottom = 'inherit'
|
|
|
+ arrowNode.style.transform = 'rotate(45deg)'
|
|
|
+
|
|
|
+ tooltipNode.appendChild(arrowNode)
|
|
|
+ document.body.appendChild(tooltipNode)
|
|
|
+
|
|
|
+ computePosition(el, tooltipNode, {
|
|
|
+ placement: 'top',
|
|
|
+ middleware: [
|
|
|
+ offset(13),
|
|
|
+ flip(),
|
|
|
+ shift({padding: 12}),
|
|
|
+ arrow({
|
|
|
+ element: arrowNode,
|
|
|
+ padding: 3,
|
|
|
+ }),
|
|
|
+ ],
|
|
|
+ }).then(({x, y, placement, middlewareData}) => {
|
|
|
+ Object.assign(tooltipNode.style, {
|
|
|
+ left: `${x}px`,
|
|
|
+ top: `${y}px`,
|
|
|
+ });
|
|
|
+
|
|
|
+ const {x: arrowX, y: arrowY} = middlewareData.arrow;
|
|
|
+ const staticSide = {
|
|
|
+ top: 'bottom',
|
|
|
+ right: 'left',
|
|
|
+ bottom: 'top',
|
|
|
+ left: 'right',
|
|
|
+ }[placement.split('-')[0]];
|
|
|
+
|
|
|
+ Object.assign(arrowNode.style, {
|
|
|
+ left: arrowX != null ? `${arrowX}px` : '',
|
|
|
+ [staticSide]: '-6px',
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }, {
|
|
|
+ passive: false,
|
|
|
+ })
|
|
|
+ el.addEventListener('mouseleave', function () {
|
|
|
+ document.body.removeChild(tooltipNode)
|
|
|
+ })
|
|
|
+ },
|
|
|
+})
|