@gravity-ui/graph
Version:
Modern graph editor component
102 lines (101 loc) • 2.81 kB
JavaScript
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;
}
}