UNPKG

@gravity-ui/graph

Version:

Modern graph editor component

98 lines (97 loc) 3.59 kB
import { Signal, computed } from "@preact/signals-core"; import { Layer } from "../../../services/Layer"; import { getBlocksRect } 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: getBlocksRect(blocks.map((block) => block.asTBlock())) })); }), (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, { deltaX, deltaY }) => { if (this.props.updateBlocksOnDrag) { const blocks = this.$groupsBlocksMap.value[groupId]; if (blocks) { blocks.forEach((block) => { block.updateXY(block.x + deltaX, block.y + deltaY, 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 }); }); } }