@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
86 lines (85 loc) • 3.13 kB
JavaScript
/*!
* All material copyright ESRI, All Rights Reserved, unless otherwise specified.
* See https://github.com/Esri/calcite-components/blob/master/LICENSE.md for details.
* v1.5.0-next.4
*/
import { isPrimaryPointerButton } from "../../utils/dom";
import { isActivationKey } from "../../utils/key";
export default class PopoverManager {
constructor() {
// --------------------------------------------------------------------------
//
// Private Properties
//
// --------------------------------------------------------------------------
this.registeredElements = new Map();
this.registeredElementCount = 0;
// --------------------------------------------------------------------------
//
// Private Methods
//
// --------------------------------------------------------------------------
this.queryPopover = (composedPath) => {
const { registeredElements } = this;
const registeredElement = composedPath.find((pathEl) => registeredElements.has(pathEl));
return registeredElements.get(registeredElement);
};
this.togglePopovers = (event) => {
const composedPath = event.composedPath();
const togglePopover = this.queryPopover(composedPath);
if (togglePopover && !togglePopover.triggerDisabled) {
togglePopover.open = !togglePopover.open;
}
Array.from(this.registeredElements.values())
.filter((popover) => popover !== togglePopover && popover.autoClose && popover.open && !composedPath.includes(popover))
.forEach((popover) => (popover.open = false));
};
this.keyHandler = (event) => {
if (event.defaultPrevented) {
return;
}
if (event.key === "Escape") {
this.closeAllPopovers();
}
else if (isActivationKey(event.key)) {
this.togglePopovers(event);
}
};
this.clickHandler = (event) => {
if (isPrimaryPointerButton(event)) {
this.togglePopovers(event);
}
};
}
// --------------------------------------------------------------------------
//
// Public Methods
//
// --------------------------------------------------------------------------
registerElement(referenceEl, popover) {
this.registeredElementCount++;
this.registeredElements.set(referenceEl, popover);
if (this.registeredElementCount === 1) {
this.addListeners();
}
}
unregisterElement(referenceEl) {
if (this.registeredElements.delete(referenceEl)) {
this.registeredElementCount--;
}
if (this.registeredElementCount === 0) {
this.removeListeners();
}
}
closeAllPopovers() {
Array.from(this.registeredElements.values()).forEach((popover) => (popover.open = false));
}
addListeners() {
document.addEventListener("pointerdown", this.clickHandler, { capture: true });
document.addEventListener("keydown", this.keyHandler, { capture: true });
}
removeListeners() {
document.removeEventListener("pointerdown", this.clickHandler, { capture: true });
document.removeEventListener("keydown", this.keyHandler, { capture: true });
}
}