|
import type { Directive, DirectiveBinding } from 'vue' |
|
import tippy, { type Instance, type Placement } from 'tippy.js' |
|
|
|
import './tooltip.scss' |
|
|
|
const TOOLTIP_INSTANCE = 'TOOLTIP_INSTANCE' |
|
|
|
interface CustomHTMLElement extends HTMLElement { |
|
[TOOLTIP_INSTANCE]?: Instance |
|
} |
|
|
|
type Delay = number | [number | null, number | null] |
|
|
|
interface BindingValue { |
|
content: string |
|
placement?: Placement |
|
delay?: Delay |
|
} |
|
|
|
const TooltipDirective: Directive = { |
|
mounted(el: CustomHTMLElement, binding: DirectiveBinding<BindingValue | string>) { |
|
let content = '' |
|
let placement: Placement = 'top' |
|
let delay: Delay = [300, 0] |
|
|
|
if (typeof binding.value === 'string') { |
|
content = binding.value |
|
} |
|
else { |
|
content = binding.value.content |
|
if (binding.value.placement !== undefined) placement = binding.value.placement |
|
if (binding.value.delay !== undefined) delay = binding.value.delay |
|
} |
|
|
|
el[TOOLTIP_INSTANCE] = tippy(el, { |
|
content, |
|
theme: 'tooltip', |
|
duration: 100, |
|
animation: 'scale', |
|
allowHTML: true, |
|
placement, |
|
delay, |
|
}) |
|
}, |
|
|
|
updated(el: CustomHTMLElement, binding: DirectiveBinding<BindingValue | string>) { |
|
let content = '' |
|
if (typeof binding.value === 'string') { |
|
content = binding.value |
|
} |
|
else { |
|
content = binding.value.content |
|
} |
|
if (el[TOOLTIP_INSTANCE]) el[TOOLTIP_INSTANCE].setContent(content) |
|
}, |
|
|
|
unmounted(el: CustomHTMLElement) { |
|
if (el[TOOLTIP_INSTANCE]) el[TOOLTIP_INSTANCE].destroy() |
|
}, |
|
} |
|
|
|
export default TooltipDirective |