@public-ui/components
Version:
Contains all web components that belong to KoliBri - The accessible HTML-Standard.
190 lines (189 loc) • 6.67 kB
JavaScript
/*!
* 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