UNPKG

@gravity-ui/graph

Version:

Modern graph editor component

90 lines (89 loc) 2.69 kB
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); } }