@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
148 lines (142 loc) • 4.42 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import { createPopper } from '@popperjs/core';
import { bind } from 'bind-event-listener';
const startingOffset = {
name: 'offset',
options: {
offset: [0, 4]
}
};
const endingOffset = {
name: 'offset',
options: {
offset: [0, 8]
}
};
/**
* A tooltip component similar to "@atlaskit/tooltip" but built for vanilla scenarios
*
* Uses Popover API for accessibility + stacking context: https://developer.mozilla.org/en-US/docs/Web/API/Popover_API
* Uses popperJS for positioning
*/
export class VanillaTooltip {
constructor(button, content,
/**
* Id associated to the tooltip - must be unique.
*/
id,
/**
* Class Name – used for styling.
*/
className, timeout = 300) {
_defineProperty(this, "listeners", []);
_defineProperty(this, "shouldHidePopover", false);
_defineProperty(this, "isDisplayed", false);
this.button = button;
this.timeout = timeout;
const tooltip = document.createElement('span');
tooltip.role = 'tooltip';
tooltip.popover = 'hint';
tooltip.className = className;
tooltip.id = id;
tooltip.textContent = content;
this.tooltip = tooltip;
// Button preparation
button.appendChild(tooltip);
// Prepare the button to have the popover target and accessibility properties
button.setAttribute('popovertarget', tooltip.id);
button.setAttribute('aria-describedby', tooltip.id);
const showEvents = ['mouseenter', 'focus'];
const hideEvents = ['mouseleave', 'blur'];
showEvents.forEach(event => {
this.listeners.push(bind(button, {
type: event,
listener: () => this.show()
}));
});
hideEvents.forEach(event => {
this.listeners.push(bind(button, {
type: event,
listener: () => this.hide()
}));
});
this.listeners.push(bind(window, {
type: 'keydown',
listener: e => {
if (e.key === 'Escape') {
this.hide(true);
}
}
}));
// Hide the tooltip if the hide transition has completed
this.tooltip.ontransitionend = () => {
if (this.shouldHidePopover) {
this.tooltip.hidePopover();
}
};
}
createPopperInstance() {
this.popperInstance = createPopper(this.button, this.tooltip, {
placement: 'top',
modifiers: [startingOffset]
});
}
destroy() {
var _this$popperInstance;
(_this$popperInstance = this.popperInstance) === null || _this$popperInstance === void 0 ? void 0 : _this$popperInstance.destroy();
this.listeners.forEach(listener => {
listener();
});
}
hide(immediate = false) {
clearTimeout(this.currentTimeoutId);
this.shouldHidePopover = true;
// Disable the event listeners
this.currentTimeoutId = setTimeout(() => {
var _this$popperInstance2;
(_this$popperInstance2 = this.popperInstance) === null || _this$popperInstance2 === void 0 ? void 0 : _this$popperInstance2.setOptions(options => ({
...options,
modifiers: [startingOffset, {
name: 'eventListeners',
enabled: false
}]
}));
this.tooltip.style.opacity = '0';
this.isDisplayed = false;
// If transition animations are disabled immediately hide the popover
if (this.tooltip.style.transition === 'none') {
this.tooltip.hidePopover();
}
}, immediate ? 0 : this.timeout);
}
show() {
if (this.isDisplayed) {
return;
}
clearTimeout(this.currentTimeoutId);
this.shouldHidePopover = false;
// Make the tooltip visible - but hide until
this.tooltip.style.visibility = 'hidden';
this.tooltip.showPopover();
// Update its position
if (!this.popperInstance) {
this.createPopperInstance();
} else {
this.popperInstance.update();
}
// Enable the event listeners
this.currentTimeoutId = setTimeout(() => {
var _this$popperInstance3;
this.tooltip.style.opacity = '1';
this.tooltip.style.visibility = 'visible';
(_this$popperInstance3 = this.popperInstance) === null || _this$popperInstance3 === void 0 ? void 0 : _this$popperInstance3.setOptions(options => ({
...options,
modifiers: [endingOffset, {
name: 'eventListeners',
enabled: true
}]
}));
this.isDisplayed = true;
}, this.timeout);
}
}