@gravity-ui/graph
Version:
Modern graph editor component
90 lines (89 loc) • 2.69 kB
JavaScript
import { Component } from "../../../lib/Component";
const listeners = new WeakMap();
export class EventedComponent extends Component {
constructor(props, parent) {
super({
...props,
interactive: props.interactive ?? true,
}, parent);
this.evented = true;
}
isInteractive() {
return this.props.interactive;
}
setInteractive(interactive) {
this.setProps({ interactive });
}
get events() {
if (!listeners.has(this)) {
listeners.set(this, new Map());
}
return listeners.get(this);
}
unmount() {
listeners.delete(this);
super.unmount();
}
handleEvent(_) {
// noop
}
listenEvents(events, cbOrObject = this) {
const unsubs = events.map((eventName) => {
return this.addEventListener(eventName, cbOrObject);
});
return unsubs;
}
addEventListener(type, cbOrObject) {
const cbs = this.events.get(type) || new Set();
cbs.add(cbOrObject);
this.events.set(type, cbs);
return () => this.removeEventListener(type, cbOrObject);
}
removeEventListener(type, cbOrObject) {
const cbs = this.events.get(type);
if (cbs) {
cbs.delete(cbOrObject);
}
}
_fireEvent(cmp, event) {
if (cmp instanceof EventedComponent && !cmp.isInteractive?.()) {
return;
}
const handlers = listeners.get(cmp)?.get?.(event.type);
handlers?.forEach((cb) => {
if (typeof cb === "function") {
return cb(event);
}
else if (cb instanceof Component && "handleEvent" in cb && typeof cb.handleEvent === "function") {
return cb.handleEvent?.(event);
}
return undefined;
});
}
dispatchEvent(event) {
return this._dipping(this, event);
}
_dipping(startParent, event) {
let stopPropagation = false;
let parent = startParent;
event.stopPropagation = () => {
stopPropagation = true;
};
do {
if ((parent instanceof EventedComponent && !parent.isInteractive?.()) ||
!this._hasListener(parent, event.type)) {
parent = parent.getParent();
continue;
}
this._fireEvent(parent, event);
if (stopPropagation) {
return false;
}
parent = parent.getParent();
} while (parent);
return true;
}
_hasListener(comp, type) {
return listeners.get(comp)?.has?.(type);
}
}