@gravity-ui/graph
Version:
Modern graph editor component
98 lines (97 loc) • 3.57 kB
JavaScript
import { Signal, computed } from "@preact/signals-core";
import { Layer } from "../../../services/Layer";
import { getUsableRectByBlockIds } from "../../../utils/functions";
import { Group } from "./Group";
export class BlockGroups extends Layer {
static withBlockGrouping({ groupingFn, mapToGroups, }) {
return class BlockGroupWithGrouping extends BlockGroups {
constructor() {
super(...arguments);
this.$groupsBlocksMap = computed(() => {
const blocks = this.props.graph.rootStore.blocksList.$blocks.value;
return groupingFn(blocks);
});
}
afterInit() {
this.onSignal(computed(() => {
const groupedBlocks = this.$groupsBlocksMap.value;
return Object.entries(groupedBlocks).map(([key, blocks]) => mapToGroups(key, { blocks, rect: getUsableRectByBlockIds(blocks) }));
}), (groups) => {
this.setGroups(groups);
});
super.afterInit();
}
};
}
constructor(props) {
super({
canvas: {
zIndex: 1,
classNames: ["no-user-select"],
transformByCameraPosition: true,
...props.canvas,
},
...props,
});
this.$groupsBlocksMap = new Signal({});
this.$groupsSource = this.props.graph.rootStore.groupsList.$groups;
this.updateBlocks = (groupId, { diffX, diffY }) => {
if (this.props.updateBlocksOnDrag) {
const blocks = this.$groupsBlocksMap.value[groupId];
if (blocks) {
blocks.forEach((block) => {
block.updateXY(block.x - diffX, block.y - diffY, true);
});
}
}
};
const canvas = this.getCanvas();
this.setContext({
canvas,
ctx: canvas.getContext("2d"),
root: this.props.root,
camera: this.props.camera,
constants: this.props.graph.graphConstants,
colors: this.props.graph.graphColors,
graph: this.props.graph,
ownerDocument: this.props.root,
});
}
afterInit() {
this.onSignal(this.$groupsSource, (groups) => {
this.shouldUpdateChildren = true;
this.shouldRenderChildren = true;
this.setState({ groups });
});
super.afterInit();
}
getParent() {
/*
* Override parent to delegate click events to camera.
* This allows camera movement when mouse button is held down.
*/
return this.props.graph.getGraphLayer().$.camera;
}
setGroups(groups) {
this.props.graph.rootStore.groupsList.setGroups(groups);
}
updateGroups(groups) {
this.props.graph.rootStore.groupsList.updateGroups(groups);
}
unmountLayer() {
this.props.graph.rootStore.groupsList.reset();
super.unmountLayer();
}
getGroupComponent(group) {
return group.$state.value.component || this.props.groupComponent || Group;
}
updateChildren() {
return this.state.groups?.map((group) => {
return this.getGroupComponent(group).create({
id: group.id,
onDragUpdate: this.updateBlocks,
draggable: this.props.draggable || false,
}, { key: group.id });
});
}
}