mirror of
https://github.com/stan-smith/FossFLOW.git
synced 2025-12-24 06:58:48 -05:00
feat: implements connectors
This commit is contained in:
40
package-lock.json
generated
40
package-lock.json
generated
@@ -18,6 +18,7 @@
|
||||
"gsap": "^3.11.4",
|
||||
"immer": "^10.0.2",
|
||||
"paper": "^0.12.17",
|
||||
"pathfinding": "^0.4.18",
|
||||
"react-hook-form": "^7.43.2",
|
||||
"react-quill": "^2.0.0",
|
||||
"react-router-dom": "^6.8.1",
|
||||
@@ -32,6 +33,7 @@
|
||||
"@types/chroma-js": "^2.4.0",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/jsdom": "^21.1.0",
|
||||
"@types/pathfinding": "^0.0.6",
|
||||
"@types/react": "^18.0.28",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/uuid": "^9.0.2",
|
||||
@@ -2725,6 +2727,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
|
||||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
|
||||
},
|
||||
"node_modules/@types/pathfinding": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/pathfinding/-/pathfinding-0.0.6.tgz",
|
||||
"integrity": "sha512-yk2LRAKAOW6m1g/4le8tk8go6wjNmCq2EA1l6Rw3tkBautda3FkBzgCLdSNUPiTZPkjxI/OYBwHmJWoYUSk7RQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/prettier": {
|
||||
"version": "2.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz",
|
||||
@@ -7087,6 +7095,11 @@
|
||||
"he": "bin/he"
|
||||
}
|
||||
},
|
||||
"node_modules/heap": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/heap/-/heap-0.2.5.tgz",
|
||||
"integrity": "sha512-G7HLD+WKcrOyJP5VQwYZNC3Z6FcQ7YYjEFiFoIj8PfEr73mu421o8B1N5DKUcc8K37EsJ2XXWA8DtrDz/2dReg=="
|
||||
},
|
||||
"node_modules/hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||
@@ -11167,6 +11180,14 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/pathfinding": {
|
||||
"version": "0.4.18",
|
||||
"resolved": "https://registry.npmjs.org/pathfinding/-/pathfinding-0.4.18.tgz",
|
||||
"integrity": "sha512-R0TGEQ9GRcFCDvAWlJAWC+KGJ9SLbW4c0nuZRcioVlXVTlw+F5RvXQ8SQgSqI9KXWC1ew95vgmIiyaWTlCe9Ag==",
|
||||
"dependencies": {
|
||||
"heap": "0.2.5"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
@@ -16136,6 +16157,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
|
||||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
|
||||
},
|
||||
"@types/pathfinding": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/pathfinding/-/pathfinding-0.0.6.tgz",
|
||||
"integrity": "sha512-yk2LRAKAOW6m1g/4le8tk8go6wjNmCq2EA1l6Rw3tkBautda3FkBzgCLdSNUPiTZPkjxI/OYBwHmJWoYUSk7RQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/prettier": {
|
||||
"version": "2.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz",
|
||||
@@ -19397,6 +19424,11 @@
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
||||
"dev": true
|
||||
},
|
||||
"heap": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/heap/-/heap-0.2.5.tgz",
|
||||
"integrity": "sha512-G7HLD+WKcrOyJP5VQwYZNC3Z6FcQ7YYjEFiFoIj8PfEr73mu421o8B1N5DKUcc8K37EsJ2XXWA8DtrDz/2dReg=="
|
||||
},
|
||||
"hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||
@@ -22427,6 +22459,14 @@
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="
|
||||
},
|
||||
"pathfinding": {
|
||||
"version": "0.4.18",
|
||||
"resolved": "https://registry.npmjs.org/pathfinding/-/pathfinding-0.4.18.tgz",
|
||||
"integrity": "sha512-R0TGEQ9GRcFCDvAWlJAWC+KGJ9SLbW4c0nuZRcioVlXVTlw+F5RvXQ8SQgSqI9KXWC1ew95vgmIiyaWTlCe9Ag==",
|
||||
"requires": {
|
||||
"heap": "0.2.5"
|
||||
}
|
||||
},
|
||||
"picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"@types/chroma-js": "^2.4.0",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/jsdom": "^21.1.0",
|
||||
"@types/pathfinding": "^0.0.6",
|
||||
"@types/react": "^18.0.28",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/uuid": "^9.0.2",
|
||||
@@ -67,6 +68,7 @@
|
||||
"gsap": "^3.11.4",
|
||||
"immer": "^10.0.2",
|
||||
"paper": "^0.12.17",
|
||||
"pathfinding": "^0.4.18",
|
||||
"react-hook-form": "^7.43.2",
|
||||
"react-quill": "^2.0.0",
|
||||
"react-router-dom": "^6.8.1",
|
||||
|
||||
@@ -5,9 +5,10 @@ import ReactDOM from 'react-dom/client';
|
||||
import GlobalStyles from '@mui/material/GlobalStyles';
|
||||
import type {
|
||||
SceneInput,
|
||||
NodeInput,
|
||||
ConnectorInput,
|
||||
IconInput,
|
||||
GroupInput,
|
||||
NodeInput
|
||||
GroupInput
|
||||
} from 'src/validation/SceneInput';
|
||||
import Isoflow, { useIsoflow } from './App';
|
||||
|
||||
@@ -61,6 +62,15 @@ const icons: IconInput[] = [
|
||||
}
|
||||
];
|
||||
|
||||
const connectors: ConnectorInput[] = [
|
||||
{
|
||||
id: 'Connector1',
|
||||
label: 'Connector 1',
|
||||
from: 'Node1',
|
||||
to: 'Node2'
|
||||
}
|
||||
];
|
||||
|
||||
const groups: GroupInput[] = [
|
||||
{
|
||||
id: 'Group1',
|
||||
@@ -124,7 +134,7 @@ const DataLayer = () => {
|
||||
initialScene={{
|
||||
icons,
|
||||
nodes,
|
||||
connectors: [],
|
||||
connectors,
|
||||
groups,
|
||||
gridSize: {
|
||||
width: 51,
|
||||
|
||||
@@ -37,8 +37,8 @@ export const useInteractionManager = () => {
|
||||
const uiStateActions = useUiStateStore((state) => {
|
||||
return state.actions;
|
||||
});
|
||||
const scene = useSceneStore(({ nodes, groups }) => {
|
||||
return { nodes, groups };
|
||||
const scene = useSceneStore(({ nodes, connectors, groups }) => {
|
||||
return { nodes, connectors, groups };
|
||||
});
|
||||
const gridSize = useSceneStore((state) => {
|
||||
return state.gridSize;
|
||||
|
||||
@@ -11,13 +11,14 @@ import { Node } from './components/Node/Node';
|
||||
import { getTilePosition } from './utils/gridHelpers';
|
||||
import { ContextMenuLayer } from './components/ContextMenuLayer/ContextMenuLayer';
|
||||
import { Lasso } from './components/Lasso/Lasso';
|
||||
import { Connector } from './components/Connector/Connector';
|
||||
import { Group } from './components/Group/Group';
|
||||
|
||||
const InitialisedRenderer = () => {
|
||||
const renderer = useRenderer();
|
||||
const [isReady, setIsReady] = useState(false);
|
||||
const scene = useSceneStore(({ nodes, groups }) => {
|
||||
return { nodes, groups };
|
||||
const scene = useSceneStore(({ nodes, connectors, groups }) => {
|
||||
return { nodes, connectors, groups };
|
||||
});
|
||||
const gridSize = useSceneStore((state) => {
|
||||
return state.gridSize;
|
||||
@@ -107,12 +108,21 @@ const InitialisedRenderer = () => {
|
||||
endTile={mode.selection.endTile}
|
||||
/>
|
||||
)}
|
||||
{scene.connectors.map((connector) => {
|
||||
return (
|
||||
<Connector
|
||||
key={connector.id}
|
||||
connector={connector}
|
||||
parentContainer={renderer.connectorManager.container as paper.Group}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{scene.groups.map((group) => {
|
||||
return (
|
||||
<Group
|
||||
key={group.id}
|
||||
group={group}
|
||||
parentContainer={renderer.groupManager.container as paper.Group}
|
||||
group={group}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
47
src/renderer/components/Connector/Connector.tsx
Normal file
47
src/renderer/components/Connector/Connector.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { useEffect } from 'react';
|
||||
import {
|
||||
Connector as ConnectorInterface,
|
||||
useSceneStore
|
||||
} from 'src/stores/useSceneStore';
|
||||
import { useConnector } from './useConnector';
|
||||
|
||||
interface ConnectorProps {
|
||||
connector: ConnectorInterface;
|
||||
parentContainer: paper.Group;
|
||||
}
|
||||
|
||||
export const Connector = ({ parentContainer, connector }: ConnectorProps) => {
|
||||
const { init, updateFromTo, updateColor } = useConnector();
|
||||
const gridSize = useSceneStore((state) => {
|
||||
return state.gridSize;
|
||||
});
|
||||
const nodes = useSceneStore((state) => {
|
||||
return state.nodes;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const container = init();
|
||||
|
||||
parentContainer.addChild(container);
|
||||
}, [parentContainer, init]);
|
||||
|
||||
useEffect(() => {
|
||||
updateColor(connector.color);
|
||||
}, [connector, updateColor]);
|
||||
|
||||
useEffect(() => {
|
||||
const fromNode = nodes.find((node) => {
|
||||
return node.id === connector.from;
|
||||
});
|
||||
|
||||
const toNode = nodes.find((node) => {
|
||||
return node.id === connector.to;
|
||||
});
|
||||
|
||||
if (!fromNode || !toNode) return;
|
||||
|
||||
updateFromTo(gridSize, fromNode.position, toNode.position);
|
||||
}, [gridSize, nodes, connector, updateFromTo]);
|
||||
|
||||
return null;
|
||||
};
|
||||
54
src/renderer/components/Connector/useConnector.ts
Normal file
54
src/renderer/components/Connector/useConnector.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { Group, Path } from 'paper';
|
||||
import { pathfinder } from 'src/renderer/utils/pathfinder';
|
||||
import { Coords } from 'src/utils/Coords';
|
||||
import { getTileBounds } from 'src/renderer/utils/gridHelpers';
|
||||
|
||||
export const useConnector = () => {
|
||||
const containerRef = useRef(new Group());
|
||||
const pathRef = useRef<paper.Path>();
|
||||
|
||||
const updateColor = useCallback((color: string) => {
|
||||
if (!pathRef.current) return;
|
||||
|
||||
pathRef.current.set({
|
||||
strokeColor: color
|
||||
});
|
||||
}, []);
|
||||
|
||||
const updateFromTo = useCallback(
|
||||
(gridSize: Coords, from: Coords, to: Coords) => {
|
||||
if (!pathRef.current) return;
|
||||
|
||||
const { findPath } = pathfinder(gridSize);
|
||||
const path = findPath([from, to]);
|
||||
|
||||
const points = path.map((tile) => {
|
||||
return getTileBounds(tile).center;
|
||||
});
|
||||
|
||||
pathRef.current.set({
|
||||
segments: points
|
||||
});
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const init = useCallback(() => {
|
||||
containerRef.current.removeChildren();
|
||||
|
||||
pathRef.current = new Path({
|
||||
strokeWidth: 5
|
||||
});
|
||||
|
||||
containerRef.current.addChild(pathRef.current);
|
||||
|
||||
return containerRef.current;
|
||||
}, []);
|
||||
|
||||
return {
|
||||
init,
|
||||
updateColor,
|
||||
updateFromTo
|
||||
};
|
||||
};
|
||||
10
src/renderer/useConnectorManager.ts
Normal file
10
src/renderer/useConnectorManager.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { useRef } from 'react';
|
||||
import { Group } from 'paper';
|
||||
|
||||
export const useConnectorManager = () => {
|
||||
const containerRef = useRef(new Group());
|
||||
|
||||
return {
|
||||
container: containerRef.current
|
||||
};
|
||||
};
|
||||
@@ -6,6 +6,7 @@ import { useGrid } from './components/Grid/useGrid';
|
||||
import { useNodeManager } from './useNodeManager';
|
||||
import { useCursor } from './components/Cursor/useCursor';
|
||||
import { useGroupManager } from './useGroupManager';
|
||||
import { useConnectorManager } from './useConnectorManager';
|
||||
|
||||
export const useRenderer = () => {
|
||||
const container = useRef(new Group());
|
||||
@@ -14,6 +15,7 @@ export const useRenderer = () => {
|
||||
const lassoContainer = useRef(new Group());
|
||||
const grid = useGrid();
|
||||
const nodeManager = useNodeManager();
|
||||
const connectorManager = useConnectorManager();
|
||||
const groupManager = useGroupManager();
|
||||
const cursor = useCursor();
|
||||
const uiStateActions = useUiStateStore((state) => {
|
||||
@@ -30,6 +32,8 @@ export const useRenderer = () => {
|
||||
|
||||
const init = useCallback(
|
||||
(gridSize: Coords) => {
|
||||
// TODO: Grid and Cursor should be initialised in their JSX components (create if they don't exist)
|
||||
// to be inline with other initialisation patterns
|
||||
const gridContainer = initGrid(gridSize);
|
||||
const cursorContainer = initCursor();
|
||||
|
||||
@@ -37,6 +41,7 @@ export const useRenderer = () => {
|
||||
innerContainer.current.addChild(groupManager.container);
|
||||
innerContainer.current.addChild(cursorContainer);
|
||||
innerContainer.current.addChild(lassoContainer.current);
|
||||
innerContainer.current.addChild(connectorManager.container);
|
||||
innerContainer.current.addChild(nodeManager.container);
|
||||
container.current.addChild(innerContainer.current);
|
||||
container.current.set({ position: [0, 0] });
|
||||
@@ -46,7 +51,13 @@ export const useRenderer = () => {
|
||||
offset: new Coords(0, 0)
|
||||
});
|
||||
},
|
||||
[initGrid, initCursor, setScroll, nodeManager.container]
|
||||
[
|
||||
initGrid,
|
||||
initCursor,
|
||||
setScroll,
|
||||
nodeManager.container,
|
||||
groupManager.container
|
||||
]
|
||||
);
|
||||
|
||||
const scrollTo = useCallback((to: Coords) => {
|
||||
@@ -68,7 +79,8 @@ export const useRenderer = () => {
|
||||
scrollTo,
|
||||
nodeManager,
|
||||
groupManager,
|
||||
cursor,
|
||||
lassoContainer
|
||||
lassoContainer,
|
||||
connectorManager,
|
||||
cursor
|
||||
};
|
||||
};
|
||||
|
||||
67
src/renderer/utils/pathfinder.ts
Normal file
67
src/renderer/utils/pathfinder.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import PF from 'pathfinding';
|
||||
import { Coords } from 'src/utils/Coords';
|
||||
|
||||
// TODO1: This file is a mess, refactor it
|
||||
// TODO: Have one single place for utils
|
||||
export const pathfinder = (gridSize: Coords) => {
|
||||
const grid = new PF.Grid(gridSize.x, gridSize.y);
|
||||
const finder = new PF.AStarFinder({
|
||||
heuristic: PF.Heuristic.manhattan,
|
||||
diagonalMovement: PF.DiagonalMovement.Always
|
||||
});
|
||||
|
||||
const convertToGridXY = ({ x, y }: Coords) => {
|
||||
return new Coords(
|
||||
x + Math.floor(gridSize.x * 0.5),
|
||||
y + Math.floor(gridSize.y * 0.5)
|
||||
);
|
||||
};
|
||||
|
||||
const convertToSceneXY = ({ x, y }: Coords) => {
|
||||
return new Coords(
|
||||
x - Math.floor(gridSize.x * 0.5),
|
||||
y - Math.floor(gridSize.y * 0.5)
|
||||
);
|
||||
};
|
||||
|
||||
const setWalkableAt = (coords: Coords, isWalkable: boolean) => {
|
||||
const { x, y } = convertToGridXY(coords);
|
||||
grid.setWalkableAt(x, y, isWalkable);
|
||||
};
|
||||
|
||||
const findPath = (tiles: Coords[]) => {
|
||||
const normalisedRoute = tiles.map((tile) => {
|
||||
return convertToGridXY(tile);
|
||||
});
|
||||
|
||||
const path = normalisedRoute.reduce((acc, stop, i) => {
|
||||
if (i === 0) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
const workingGrid = grid.clone();
|
||||
workingGrid.setWalkableAt(stop.x, stop.y, true);
|
||||
|
||||
const prevStop = normalisedRoute[i - 1];
|
||||
|
||||
const segment = finder.findPath(
|
||||
prevStop.x,
|
||||
prevStop.y,
|
||||
stop.x,
|
||||
stop.y,
|
||||
workingGrid
|
||||
);
|
||||
|
||||
return [...acc, ...(i > 1 ? segment.slice(1) : segment)];
|
||||
}, [] as number[][]);
|
||||
|
||||
return path.map((tile) => {
|
||||
return convertToSceneXY(new Coords(tile[0], tile[1]));
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
setWalkableAt,
|
||||
findPath
|
||||
};
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Matrix, Point } from 'paper';
|
||||
|
||||
export const getProjectionMatrix = (x: number, y: number) =>
|
||||
new Matrix([
|
||||
export const getProjectionMatrix = (x: number, y: number) => {
|
||||
return new Matrix([
|
||||
Math.sqrt(2) / 2,
|
||||
Math.sqrt(6) / 6,
|
||||
-(Math.sqrt(2) / 2),
|
||||
@@ -9,6 +9,7 @@ export const getProjectionMatrix = (x: number, y: number) =>
|
||||
x - (Math.sqrt(2) / 2) * (x - y),
|
||||
y - (Math.sqrt(6) / 6) * (x + y - 2)
|
||||
]);
|
||||
};
|
||||
|
||||
export const applyProjectionMatrix = (
|
||||
item: paper.Item,
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Coords } from '../utils/Coords';
|
||||
// TODO: Move all types into a types file for easier access and less mental load over where to look
|
||||
export enum SceneItemTypeEnum {
|
||||
NODE = 'NODE',
|
||||
CONNECTOR = 'CONNECTOR',
|
||||
GROUP = 'GROUP'
|
||||
}
|
||||
|
||||
@@ -23,6 +24,14 @@ export interface Node {
|
||||
isSelected: boolean;
|
||||
}
|
||||
|
||||
export interface Connector {
|
||||
type: SceneItemTypeEnum.CONNECTOR;
|
||||
id: string;
|
||||
color: string;
|
||||
from: string;
|
||||
to: string;
|
||||
}
|
||||
|
||||
export interface Group {
|
||||
type: SceneItemTypeEnum.GROUP;
|
||||
id: string;
|
||||
@@ -41,6 +50,7 @@ export interface SortedSceneItems {
|
||||
// TODO: Decide on whether to make a Map instead of an array for easier lookup
|
||||
nodes: Node[];
|
||||
groups: Group[];
|
||||
connectors: Connector[];
|
||||
}
|
||||
|
||||
// TODO: This typing is super confusing to work with
|
||||
@@ -64,6 +74,7 @@ export type UseSceneStore = Scene & {
|
||||
export const useSceneStore = create<UseSceneStore>((set, get) => {
|
||||
return {
|
||||
nodes: [],
|
||||
connectors: [],
|
||||
groups: [],
|
||||
icons: [],
|
||||
gridSize: new Coords(51, 51),
|
||||
|
||||
@@ -3,6 +3,10 @@ import { customVars } from '../styles/theme';
|
||||
|
||||
export const DEFAULT_COLOR = customVars.diagramPalette.blue;
|
||||
|
||||
export const CONNECTOR_DEFAULTS = {
|
||||
width: 4
|
||||
};
|
||||
|
||||
export const GRID_DEFAULTS = {
|
||||
size: {
|
||||
x: 51,
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import gsap from 'gsap';
|
||||
import { Coords } from 'src/utils/Coords';
|
||||
import { customVars } from 'src/styles/theme';
|
||||
import chroma from 'chroma-js';
|
||||
import type {
|
||||
NodeInput,
|
||||
SceneInput,
|
||||
NodeInput,
|
||||
ConnectorInput,
|
||||
GroupInput
|
||||
} from 'src/validation/SceneInput';
|
||||
import {
|
||||
Node,
|
||||
Group,
|
||||
SceneItemTypeEnum,
|
||||
Scene
|
||||
Scene,
|
||||
Node,
|
||||
Connector,
|
||||
Group
|
||||
} from 'src/stores/useSceneStore';
|
||||
import { NODE_DEFAULTS, GRID_DEFAULTS } from 'src/utils/defaults';
|
||||
|
||||
@@ -79,6 +82,18 @@ export const groupInputToGroup = (groupInput: GroupInput): Group => {
|
||||
};
|
||||
};
|
||||
|
||||
export const connectorInputToConnector = (
|
||||
connectorInput: ConnectorInput
|
||||
): Connector => {
|
||||
return {
|
||||
type: SceneItemTypeEnum.CONNECTOR,
|
||||
id: connectorInput.id,
|
||||
color: connectorInput.color ?? customVars.diagramPalette.blue,
|
||||
from: connectorInput.from,
|
||||
to: connectorInput.to
|
||||
};
|
||||
};
|
||||
|
||||
export const sceneInputtoScene = (sceneInput: SceneInput) => {
|
||||
const nodes = sceneInput.nodes.map((nodeInput) => {
|
||||
return nodeInputToNode(nodeInput);
|
||||
@@ -88,10 +103,15 @@ export const sceneInputtoScene = (sceneInput: SceneInput) => {
|
||||
return groupInputToGroup(groupInput);
|
||||
});
|
||||
|
||||
const connectors = sceneInput.connectors.map((connectorInput) => {
|
||||
return connectorInputToConnector(connectorInput);
|
||||
});
|
||||
|
||||
const scene = {
|
||||
...sceneInput,
|
||||
nodes,
|
||||
groups,
|
||||
connectors,
|
||||
icons: sceneInput.icons,
|
||||
gridSize: sceneInput.gridSize
|
||||
? new Coords(sceneInput.gridSize.width, sceneInput.gridSize.height)
|
||||
|
||||
@@ -23,6 +23,7 @@ export const nodeInput = z.object({
|
||||
export const connectorInput = z.object({
|
||||
id: z.string(),
|
||||
label: z.string().nullable(),
|
||||
color: z.string().optional(),
|
||||
from: z.string(),
|
||||
to: z.string()
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user