refactor(svelte/react): use edge layouting vanilla helpers

This commit is contained in:
moklick
2023-06-08 15:46:35 +02:00
parent 4707a07c8b
commit c1e2499028
21 changed files with 392 additions and 436 deletions
@@ -0,0 +1,88 @@
import { derived } from 'svelte/store';
import { groupEdgesByZLevel, isEdgeVisible, getEdgePosition, type OnError } from '@xyflow/system';
import type { EdgeLayouted } from '$lib/types';
import type { SvelteFlowStoreState } from './types';
export function getEdgeTree(store: SvelteFlowStoreState, onError: OnError) {
const visibleEdges = derived(
[
store.edges,
store.nodes,
store.onlyRenderVisibleElements,
store.transform,
store.width,
store.height
],
([edges, nodes, onlyRenderVisibleElements, transform, width, height]) => {
const visibleEdges = onlyRenderVisibleElements
? edges.filter((edge) => {
const sourceNode = nodes.find((node) => node.id === edge.source);
const targetNode = nodes.find((node) => node.id === edge.target);
return (
sourceNode?.width &&
sourceNode?.height &&
targetNode?.width &&
targetNode?.height &&
isEdgeVisible({
sourcePos: sourceNode.positionAbsolute || { x: 0, y: 0 },
targetPos: targetNode.positionAbsolute || { x: 0, y: 0 },
sourceWidth: sourceNode.width,
sourceHeight: sourceNode.height,
targetWidth: targetNode.width,
targetHeight: targetNode.height,
width,
height,
transform
})
);
})
: edges;
return visibleEdges;
}
);
return derived(
[visibleEdges, store.nodes, store.connectionMode],
([visibleEdges, nodes, connectionMode]) => {
const layoutedEdges = visibleEdges.reduce<EdgeLayouted[]>((res, edge) => {
const sourceNode = nodes.find((node) => node.id === edge.source);
const targetNode = nodes.find((node) => node.id === edge.target);
if (!sourceNode || !targetNode) {
return res;
}
const edgePosition = getEdgePosition({
id: edge.id,
sourceNode,
targetNode,
sourceHandle: edge.sourceHandle || null,
targetHandle: edge.targetHandle || null,
connectionMode,
onError
});
if (edgePosition) {
res.push({
...edge,
sourceX: edgePosition.sourceX,
sourceY: edgePosition.sourceY,
targetX: edgePosition.targetX,
targetY: edgePosition.targetY,
sourcePosition: edgePosition.sourcePosition,
targetPosition: edgePosition.targetPosition
});
}
return res;
}, []);
const groupedEdges = groupEdgesByZLevel<EdgeLayouted>(layoutedEdges, nodes, false);
return groupedEdges;
}
);
}
@@ -1,69 +0,0 @@
import { derived } from 'svelte/store';
import { Position, getHandle } from '@xyflow/system';
import { getEdgePositions, getNodeData } from '$lib/container/EdgeRenderer/utils';
import type { EdgeLayouted } from '$lib/types';
import type { SvelteFlowStoreState } from './types';
export function getEdgesLayouted(store: SvelteFlowStoreState) {
return derived(
[store.edges, store.nodes, store.elementsSelectable],
([edges, nodes, elementsSelectable]) => {
return edges.reduce<EdgeLayouted[]>((res, edge) => {
const sourceNode = nodes.find((node) => node.id === edge.source);
const targetNode = nodes.find((node) => node.id === edge.target);
const [sourceNodeRect, sourceHandleBounds, sourceIsValid] = getNodeData(sourceNode);
const [targetNodeRect, targetHandleBounds, targetIsValid] = getNodeData(targetNode);
if (!sourceIsValid || !targetIsValid) {
return res;
}
const edgeType = edge.type || 'default';
const targetNodeHandles = targetHandleBounds!.target;
const sourceHandle = getHandle(sourceHandleBounds!.source!, edge.sourceHandle);
const targetHandle = getHandle(targetNodeHandles!, edge.targetHandle);
const sourcePosition = sourceHandle?.position || Position.Bottom;
const targetPosition = targetHandle?.position || Position.Top;
if (!sourceHandle || !targetHandle) {
return res;
}
const { sourceX, sourceY, targetX, targetY } = getEdgePositions(
sourceNodeRect,
sourceHandle,
sourcePosition,
targetNodeRect,
targetHandle,
targetPosition
);
// we nee to do this to match the types
const sourceHandleId = edge.sourceHandle;
const targetHandleId = edge.targetHandle;
const selectable = !!(
edge.selectable ||
(elementsSelectable && typeof edge.selectable === 'undefined')
);
res.push({
...edge,
selectable,
type: edgeType,
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
sourceHandleId,
targetHandleId
} as EdgeLayouted);
return res;
}, []);
}
);
}
+8 -3
View File
@@ -19,7 +19,6 @@ import {
import { addEdge as addEdgeUtil } from '$lib/utils';
import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions } from '$lib/types';
import { getEdgesLayouted } from './edges-layouted';
import { getConnectionPath } from './connection-path';
import {
initConnectionData,
@@ -29,6 +28,7 @@ import {
} from './initial-store';
import type { SvelteFlowStore } from './types';
import { syncNodeStores, syncEdgeStores } from './utils';
import { getEdgeTree } from './edge-tree';
export const key = Symbol();
@@ -332,12 +332,16 @@ export function createStore(): SvelteFlowStore {
cancelConnection();
}
function onError(id: string, msg: string) {
console.log(msg);
}
return {
// state
...store,
// derived state
edgesLayouted: getEdgesLayouted(store),
edgeTree: getEdgeTree(store, onError),
connectionPath: getConnectionPath(store),
markers: derived(
[store.edges, store.defaultMarkerColor, store.flowId],
@@ -364,7 +368,8 @@ export function createStore(): SvelteFlowStore {
panBy,
updateConnection,
cancelConnection,
reset
reset,
onError
};
}
@@ -10,7 +10,8 @@ import {
type MarkerProps,
type PanZoomInstance,
type CoordinateExtent,
type IsValidConnection
type IsValidConnection,
type GroupedEdges
} from '@xyflow/system';
import DefaultNode from '$lib/components/nodes/DefaultNode.svelte';
@@ -47,7 +48,7 @@ export const getInitialStore = () => ({
flowId: writable<string | null>(null),
nodes: createNodes([]),
edges: createEdges([]),
edgesLayouted: readable<EdgeLayouted[]>([]),
edgeTree: readable<GroupedEdges<EdgeLayouted>[]>([]),
height: writable<number>(500),
width: writable<number>(500),
minZoom: writable<number>(0.5),
@@ -82,5 +83,6 @@ export const getInitialStore = () => ({
selectNodesOnDrag: writable<boolean>(true),
markers: readable<MarkerProps[]>([]),
defaultMarkerColor: writable<string>('#b1b1b7'),
lib: readable<string>('svelte')
lib: readable<string>('svelte'),
onlyRenderVisibleElements: writable<boolean>(false)
});
+3 -1
View File
@@ -6,7 +6,8 @@ import type {
Connection,
UpdateNodePositions,
CoordinateExtent,
UpdateConnection
UpdateConnection,
OnError
} from '@xyflow/system';
import type { getInitialStore } from './initial-store';
@@ -33,6 +34,7 @@ export type SvelteFlowStoreActions = {
updateConnection: UpdateConnection;
cancelConnection: () => void;
reset(): void;
onError: OnError;
};
export type SvelteFlowStoreState = ReturnType<typeof getInitialStore>;