UNPKG

@public-ui/components

Version:

Contains all web components that belong to KoliBri - The accessible HTML-Standard.

190 lines (189 loc) 6.67 kB
/*! * KoliBri - The accessible HTML-Standard */ import { autoUpdate } from "@floating-ui/dom"; import { getDocument } from "../../../schema"; import { alignFloatingElements } from "../../../utils/align-floating-elements"; import { hideOverlay, showOverlay } from "../../../utils/overlay"; import { tooltipClosed, tooltipOpened } from "../../../utils/tooltip-open-tracking"; import { alignProp, badgeTextProp, idProp, labelProp } from "../../props"; import { BaseController } from "../base-controller"; import { tooltipPropsConfig } from "./api"; export class TooltipController extends BaseController { constructor(stateAccess) { super(stateAccess, tooltipPropsConfig); this.hasFocusIn = false; this.hasMouseIn = false; this.isHiddenForCurrentVisit = false; this.setTooltipElementRef = (el) => { this.tooltipElement = el; if (this.tooltipElement) { this.addListeners(this.tooltipElement); } }; this.hideTooltipByEscape = (event) => { if (event.key === 'Escape') { this.hideTooltip(); } }; this.handleMouseEnter = () => { const isNewVisit = this.isNewVisit(); this.hasMouseIn = true; if (isNewVisit) { this.isHiddenForCurrentVisit = false; } this.showOrHideTooltip(); }; this.handleMouseLeave = () => { this.hasMouseIn = false; this.resetHideFlag(); this.showOrHideTooltip(); }; this.handleFocusIn = () => { const isNewVisit = this.isNewVisit(); this.hasFocusIn = true; if (isNewVisit) { this.isHiddenForCurrentVisit = false; } this.showOrHideTooltip(); }; this.handleFocusOut = () => { this.hasFocusIn = false; this.resetHideFlag(); this.showOrHideTooltip(); }; } componentWillLoad(props) { this.watchLabel(props.label); this.watchAlign(props.align); this.watchBadgeText(props.badgeText); this.watchId(props.id); } watchLabel(value) { labelProp.apply(value, (v) => { this.setRenderProp('label', v); }); } watchAlign(value) { alignProp.apply(value, (v) => { this.setRenderProp('align', v); }); } watchBadgeText(value) { badgeTextProp.apply(value, (v) => { this.setRenderProp('badgeText', v); }); } watchId(value) { idProp.apply(value, (v) => { this.setRenderProp('id', v); }); } initContext(previousSibling) { this.previousSibling = previousSibling; } syncListeners(last, next, replacePreviousSibling = false) { if (last) { this.removeListeners(last); } if (next) { if (replacePreviousSibling) { this.previousSibling = next; } this.addListeners(next); } } handleEventListeners(host) { const nextSibling = host.previousElementSibling; this.syncListeners(this.previousSibling, nextSibling, true); } hideTooltip() { this.isHiddenForCurrentVisit = true; if (this.tooltipElement) { hideOverlay(this.tooltipElement); tooltipClosed(); this.tooltipElement.classList.remove('show'); this.tooltipElement.classList.add('hide'); if (this.cleanupAutoPositioning) { this.cleanupAutoPositioning(); this.cleanupAutoPositioning = undefined; } } getDocument().removeEventListener('keyup', this.hideTooltipByEscape); } destroy() { clearTimeout(this.overFocusTimeout); if (this.previousSibling) { this.removeListeners(this.previousSibling); this.previousSibling = undefined; } if (this.tooltipElement) { this.removeListeners(this.tooltipElement); } if (this.cleanupAutoPositioning) { this.cleanupAutoPositioning(); this.cleanupAutoPositioning = undefined; } getDocument().removeEventListener('keyup', this.hideTooltipByEscape); } isNewVisit() { return !this.hasMouseIn && !this.hasFocusIn; } resetHideFlag() { if (this.isNewVisit()) { this.isHiddenForCurrentVisit = false; } } async alignTooltip() { if (this.tooltipElement && this.previousSibling) { await alignFloatingElements({ align: this.getRenderProp('align'), arrowElement: this.tooltipElement.querySelector('.kol-tooltip__arrow'), floatingElement: this.tooltipElement, referenceElement: this.previousSibling, }); } } showTooltip() { if (this.isHiddenForCurrentVisit) { return; } if (this.previousSibling && this.tooltipElement) { showOverlay(this.tooltipElement); tooltipOpened(); this.tooltipElement.classList.remove('hide'); this.tooltipElement.classList.add('show'); this.tooltipElement.style.setProperty('display', 'block'); getDocument().addEventListener('keyup', this.hideTooltipByEscape, { once: true }); const target = this.previousSibling; const tooltipEl = this.tooltipElement; this.cleanupAutoPositioning = autoUpdate(target, tooltipEl, () => { void this.alignTooltip(); }); } } showOrHideTooltip() { clearTimeout(this.overFocusTimeout); this.overFocusTimeout = setTimeout(() => { if (this.hasMouseIn || this.hasFocusIn) { this.showTooltip(); } else { this.hideTooltip(); } }, 300); } addListeners(el) { el.addEventListener('mouseover', this.handleMouseEnter); el.addEventListener('mouseout', this.handleMouseLeave); el.addEventListener('focusin', this.handleFocusIn); el.addEventListener('focusout', this.handleFocusOut); } removeListeners(el) { el.removeEventListener('mouseover', this.handleMouseEnter); el.removeEventListener('mouseout', this.handleMouseLeave); el.removeEventListener('focusin', this.handleFocusIn); el.removeEventListener('focusout', this.handleFocusOut); } } //# sourceMappingURL=controller.js.map