@gravity-ui/graph
Version:
Modern graph editor component
120 lines (119 loc) • 4.96 kB
JavaScript
import { batch } from "@preact/signals-core";
import { selectBlockById } from "../store/block/selectors";
import { selectConnectionById } from "../store/connection/selectors";
import { getUsableRectByBlockIds, startAnimation } from "../utils/functions";
import { ESelectionStrategy } from "../utils/types/types";
export class PublicGraphApi {
constructor(graph) {
this.graph = graph;
// noop
}
zoomToBlocks(blockIds, zoomConfig) {
const blocksRect = getUsableRectByBlockIds(this.graph.rootStore.blocksList.$blocks.value, blockIds);
this.zoomToRect(blocksRect, zoomConfig);
}
/**
* Zooms to fit all blocks in the viewport. This method is asynchronous and waits
* for the usableRect to be ready before performing the zoom operation.
*
* @param zoomConfig - Configuration for zoom transition and padding
* @returns Promise that resolves when zoom operation is complete
*/
zoomToViewPort(zoomConfig) {
this.graph.hitTest.waitUsableRectUpdate((rect) => {
this.zoomToRect(rect, zoomConfig);
});
}
zoomToRect(rect, zoomConfig) {
const transition = zoomConfig?.transition || 0;
const padding = zoomConfig?.padding || 0;
const cameraRectInit = this.graph.cameraService.getCameraRect();
const cameraScaleInit = this.graph.cameraService.getCameraScale();
const endScale = this.graph.cameraService.getScaleRelativeDimensions(rect.width + padding * 2, rect.height + padding * 2);
const xyPosition = this.graph.cameraService.getXYRelativeCenterDimensions({
x: rect.x - padding,
y: rect.y - padding,
width: rect.width + padding * 2,
height: rect.height + padding * 2,
}, endScale);
if (!transition) {
this.graph.cameraService.set({ ...xyPosition, scale: endScale });
return;
}
startAnimation(transition, (progress) => {
const x = cameraRectInit.x + (xyPosition.x - cameraRectInit.x) * progress;
const y = cameraRectInit.y + (xyPosition.y - cameraRectInit.y) * progress;
const scale = cameraScaleInit + (endScale - cameraScaleInit) * progress;
this.graph.cameraService.set({ x, y, scale });
});
}
getGraphColors() {
return this.graph.graphColors;
}
updateGraphColors(colors) {
this.graph.setColors(colors);
}
getGraphConstants() {
return this.graph.graphConstants;
}
updateGraphConstants(constants) {
this.graph.setConstants(constants);
}
isGraphEmpty() {
return this.graph.rootStore.blocksList.$blocksMap.value.size === 0;
}
setSetting(flagPath, value) {
this.graph.rootStore.settings.setConfigFlag(flagPath, value);
}
setCurrentConfigurationName(newName) {
this.graph.rootStore.configurationName = newName;
}
deleteSelected() {
batch(() => {
this.graph.rootStore.connectionsList.deleteSelectedConnections();
this.graph.rootStore.blocksList.deleteSelectedBlocks();
});
}
selectBlocks(blockIds, selected, strategy = ESelectionStrategy.REPLACE) {
this.graph.rootStore.blocksList.updateBlocksSelection(blockIds, selected, strategy);
}
updateBlock(block) {
const blockStore = selectBlockById(this.graph, block.id);
blockStore?.updateBlock(block);
}
addBlock(block, selectionOptions) {
const newBlockId = this.graph.rootStore.blocksList.addBlock(block);
if (selectionOptions !== undefined) {
this.graph.rootStore.blocksList.updateBlocksSelection([newBlockId], selectionOptions.selected !== undefined ? selectionOptions.selected : true, selectionOptions.strategy);
}
return newBlockId;
}
setAnchorSelection(blockId, anchorId, selected) {
this.graph.rootStore.blocksList.setAnchorSelection(blockId, anchorId, selected);
}
selectConnections(connectionIds, selected, strategy = ESelectionStrategy.REPLACE) {
batch(() => {
this.graph.rootStore.connectionsList.setConnectionsSelection(connectionIds, selected, strategy);
});
}
updateConnection(id, connection) {
const connectionStore = selectConnectionById(this.graph, id);
connectionStore.updateConnection(connection);
}
addConnection(connection) {
return this.graph.rootStore.connectionsList.addConnection(connection);
}
getBlockById(blockId) {
return selectBlockById(this.graph, blockId)?.asTBlock();
}
getUsableRect() {
return this.graph.hitTest.getUsableRect();
}
unsetSelection() {
batch(() => {
this.graph.rootStore.blocksList.resetSelection();
this.graph.rootStore.groupsList.resetSelection();
this.graph.rootStore.connectionsList.resetSelection();
});
}
}