UNPKG

@gravity-ui/graph

Version:

Modern graph editor component

102 lines (101 loc) 2.81 kB
import debounce from "lodash/debounce"; import { Component } from "../lib/Component"; import { Emitter } from "../utils/Emitter"; export class Layers extends Emitter { constructor($root) { super(); this.$root = $root; this.attached = false; this.rootSize = { width: 0, height: 0 }; this.layers = new Set(); this.resizeObserver = new ResizeObserver(() => { this.handleRootResize(); }); this.handleRootResize = debounce(() => { this.updateSize(); }, 16); this.updateSize = () => { if (!this.rootSize) { return; } this.updateRootSize(); const { width, height } = this.rootSize; this.layers.forEach((layer) => { layer.updateSize(width, height); }); this.emit("update-size", this.rootSize); }; } createLayer(layerCtor, props) { const layer = Component.mount(layerCtor, { root: this.$root, ...props, }); this.layers.add(layer); if (this.attached) { const { width, height } = this.rootSize; layer.updateSize(width, height); layer.attachLayer(this.$root); } return layer; } detachLayer(layer) { this.layers.delete(layer); layer.detachLayer(); } getRootSize() { return this.rootSize; } getLayers() { return Array.from(this.layers); } attach(root = this.$root) { this.$root = root; this.layers.forEach((layer) => { layer.attachLayer(this.$root); }); } start(root = this.$root) { if (this.attached) { return; } this.attach(root); if (!this.$root) { throw new Error("Root not specified"); } this.updateSize(); this.resizeObserver.observe(this.$root, { box: "border-box" }); this.attached = true; } detach(full = false) { if (this.attached) { this.layers.forEach((layer) => { layer.detachLayer(); }); this.attached = false; } this.handleRootResize.cancel(); this.resizeObserver.disconnect(); if (full) { this.$root = undefined; } } unmount() { this.detach(true); this.destroy(); } destroy() { this.detach(); this.destroyLayers(); this.off(); } destroyLayers() { this.layers.forEach((layer) => { Component.unmount(layer); }); } updateRootSize() { this.rootSize.width = this.$root.clientWidth; this.rootSize.height = this.$root.clientHeight; } }