refactor(svelte/react): use edge layouting vanilla helpers
This commit is contained in:
@@ -1,125 +1,11 @@
|
||||
import { useCallback } from 'react';
|
||||
import {
|
||||
BaseNode,
|
||||
internalsSymbol,
|
||||
isNumeric,
|
||||
errorMessages,
|
||||
ConnectionMode,
|
||||
Position,
|
||||
getHandle,
|
||||
OnError,
|
||||
} from '@xyflow/system';
|
||||
import { GroupedEdges, groupEdgesByZLevel, isEdgeVisible } from '@xyflow/system';
|
||||
|
||||
import { useStore } from '../hooks/useStore';
|
||||
import { getEdgePositions, getNodeData, isEdgeVisible } from '../container/EdgeRenderer/utils';
|
||||
import { type ReactFlowState, type NodeInternals, type Edge, EdgePosition } from '../types';
|
||||
import { Edge, type ReactFlowState } from '../types';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
const defaultEdgeTree = [{ level: 0, isMaxLevel: true, edges: [] }];
|
||||
|
||||
type GroupedEdges = {
|
||||
edges: Edge[];
|
||||
level: number;
|
||||
isMaxLevel: boolean;
|
||||
};
|
||||
|
||||
function groupEdgesByZLevel(edges: Edge[], nodeInternals: NodeInternals, elevateEdgesOnSelect = false): GroupedEdges[] {
|
||||
let maxLevel = -1;
|
||||
|
||||
const levelLookup = edges.reduce<Record<string, Edge[]>>((tree, edge) => {
|
||||
const hasZIndex = isNumeric(edge.zIndex);
|
||||
let z = hasZIndex ? edge.zIndex! : 0;
|
||||
|
||||
if (elevateEdgesOnSelect) {
|
||||
z = hasZIndex
|
||||
? edge.zIndex!
|
||||
: Math.max(
|
||||
nodeInternals.get(edge.source)?.[internalsSymbol]?.z || 0,
|
||||
nodeInternals.get(edge.target)?.[internalsSymbol]?.z || 0
|
||||
);
|
||||
}
|
||||
|
||||
if (tree[z]) {
|
||||
tree[z].push(edge);
|
||||
} else {
|
||||
tree[z] = [edge];
|
||||
}
|
||||
|
||||
maxLevel = z > maxLevel ? z : maxLevel;
|
||||
|
||||
return tree;
|
||||
}, {});
|
||||
|
||||
const edgeTree = Object.entries(levelLookup).map(([key, edges]) => {
|
||||
const level = +key;
|
||||
|
||||
return {
|
||||
edges,
|
||||
level,
|
||||
isMaxLevel: level === maxLevel,
|
||||
};
|
||||
});
|
||||
|
||||
if (edgeTree.length === 0) {
|
||||
return defaultEdgeTree;
|
||||
}
|
||||
|
||||
return edgeTree;
|
||||
}
|
||||
|
||||
type LayoutEdgeParams = {
|
||||
sourceNode: BaseNode;
|
||||
sourceHandle: string | null;
|
||||
targetNode: BaseNode;
|
||||
targetHandle: string | null;
|
||||
connectionMode: ConnectionMode;
|
||||
onError?: OnError;
|
||||
};
|
||||
|
||||
export function getEdgePosition(params: LayoutEdgeParams): EdgePosition | null {
|
||||
const [sourceNodeRect, sourceHandleBounds, sourceIsValid] = getNodeData(params.sourceNode);
|
||||
const [targetNodeRect, targetHandleBounds, targetIsValid] = getNodeData(params.targetNode);
|
||||
|
||||
if (!sourceIsValid || !targetIsValid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// when connection type is loose we can define all handles as sources and connect source -> source
|
||||
const targetNodeHandles =
|
||||
params.connectionMode === ConnectionMode.Strict
|
||||
? targetHandleBounds!.target
|
||||
: (targetHandleBounds!.target ?? []).concat(targetHandleBounds!.source ?? []);
|
||||
const sourceHandle = getHandle(sourceHandleBounds!.source!, params.sourceHandle);
|
||||
const targetHandle = getHandle(targetNodeHandles!, params.targetHandle);
|
||||
const sourcePosition = sourceHandle?.position || Position.Bottom;
|
||||
const targetPosition = targetHandle?.position || Position.Top;
|
||||
|
||||
if (!sourceHandle || !targetHandle) {
|
||||
params.onError?.('008', errorMessages['error008'](sourceHandle, {} as Edge));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const { sourceX, sourceY, targetX, targetY } = getEdgePositions(
|
||||
sourceNodeRect,
|
||||
sourceHandle,
|
||||
sourcePosition,
|
||||
targetNodeRect,
|
||||
targetHandle,
|
||||
targetPosition
|
||||
);
|
||||
|
||||
return {
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
targetY,
|
||||
sourcePosition,
|
||||
targetPosition,
|
||||
};
|
||||
}
|
||||
|
||||
function useVisibleEdges(onlyRenderVisible: boolean, elevateEdgesOnSelect: boolean): GroupedEdges[] {
|
||||
function useVisibleEdges(onlyRenderVisible: boolean, elevateEdgesOnSelect: boolean): GroupedEdges<Edge>[] {
|
||||
const edges = useStore(
|
||||
useCallback(
|
||||
(s: ReactFlowState) => {
|
||||
|
||||
Reference in New Issue
Block a user