import { Tooltip } from 'bootstrap'; import { Prop, toNative } from 'vue-facing-decorator'; import TsxComponent, { Component } from '../../app/vuetsx'; import { isNullOrEmpty } from '../../common/utils/is-null-or-empty'; import { PortalUtils } from '../../common/utils/utils'; interface TooltipContainerArgs { renderAsSpan?: boolean; cssClass?: string; tooltipCssClass?: string; tooltip: string; isHtml?: boolean; trigger?: 'click' | 'hover' | 'focus' | 'manual' | 'click hover' | 'click focus' | 'hover focus' | 'click hover focus'; textAlign?: 'left' | 'middle' | 'right'; arrowPosition?: 'left' | 'middle' | 'right'; } let counter = 0; @Component class TooltipContainerComponent extends TsxComponent implements TooltipContainerArgs { @Prop() renderAsSpan!: boolean; @Prop() cssClass!: string; @Prop() tooltipCssClass?: string; @Prop() tooltip: string; @Prop() isHtml?: boolean; @Prop() trigger?: 'click' | 'hover' | 'focus' | 'manual' | 'click hover' | 'click focus' | 'hover focus' | 'click hover focus'; @Prop() textAlign?: 'left' | 'middle' | 'right'; @Prop() arrowPosition: 'left' | 'middle' | 'right'; uuid: string = null; mounted() { if (this.uuid == null) { this.uuid = `${PortalUtils.randomString(8)}-${counter++}`; } this.$nextTick(() => { this.ensureTooltip(); }); } updated() { this.$nextTick(() => { const el = this.$el as HTMLElement; el.setAttribute('data-original-title', this.tooltip); el.setAttribute('data-bs-original-title', this.tooltip); }); } getInnerStyleAttribute(): string { if (!isNullOrEmpty(this.textAlign)) { return `style="text:align: ${this.textAlign} !important;"`; } return ''; } ensureTooltip() { this.$nextTick(() => { const target = this.$el as HTMLElement; if (!target.classList.contains('tooltip-bound')) { target.classList.add('tooltip-bound'); // Bootstrap's Tooltip registers itself on the element via its // constructor; we don't need to keep a reference around — the // element holds it via `_tooltip` and is reachable through // `Tooltip.getInstance(el)` if ever needed. // eslint-disable-next-line no-new new Tooltip(this.$el, { html: this.isHtml == true, trigger: this.trigger || 'hover', template: ``, }); } }); } getCssClass(): string { return `tooltip-container ${this.cssClass || ''}`; } beforeUnmount() { const visibleTooltip = document.getElementById(`tt-uuid-${this.uuid}`); visibleTooltip?.parentElement?.remove(); } render(h) { if (this.renderAsSpan != true) { return (
{this.$slots.default?.()}
); } return ( {this.$slots.default?.()} ); } } const TooltipContainer = toNative(TooltipContainerComponent); export default TooltipContainer;