refactor: EdgeRenderer (#53)
This commit is contained in:
@@ -3,7 +3,7 @@ import React, { memo, SVGAttributes } from 'react';
|
|||||||
import { useStoreState } from '../../store/hooks';
|
import { useStoreState } from '../../store/hooks';
|
||||||
import ConnectionLine from '../../components/ConnectionLine/index';
|
import ConnectionLine from '../../components/ConnectionLine/index';
|
||||||
import { isEdge } from '../../utils/graph';
|
import { isEdge } from '../../utils/graph';
|
||||||
import { XYPosition, Position, Edge, Node, ElementId, Transform, HandleElement } from '../../types';
|
import { XYPosition, Position, Edge, Node, ElementId, HandleElement, Elements } from '../../types';
|
||||||
|
|
||||||
interface EdgeRendererProps {
|
interface EdgeRendererProps {
|
||||||
width: number;
|
width: number;
|
||||||
@@ -14,15 +14,6 @@ interface EdgeRendererProps {
|
|||||||
onElementClick?: () => void;
|
onElementClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EdgeRendererState {
|
|
||||||
nodes: Node[];
|
|
||||||
edges: Edge[];
|
|
||||||
transform: Transform;
|
|
||||||
selectedElements: any;
|
|
||||||
connectionSourceId: ElementId | null;
|
|
||||||
position: XYPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EdgePositions {
|
interface EdgePositions {
|
||||||
sourceX: number;
|
sourceX: number;
|
||||||
sourceY: number;
|
sourceY: number;
|
||||||
@@ -122,20 +113,12 @@ function getEdgePositions(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderEdge(edge: Edge, props: EdgeRendererProps, state: EdgeRendererState) {
|
function renderEdge(edge: Edge, props: EdgeRendererProps, nodes: Node[], selectedElements: Elements) {
|
||||||
const edgeType = edge.type || 'default';
|
const [sourceId, sourceHandleId] = edge.source.split('__');
|
||||||
|
const [targetId, targetHandleId] = edge.target.split('__');
|
||||||
|
|
||||||
const hasSourceHandleId = edge.source.includes('__');
|
const sourceNode = nodes.find(n => n.id === sourceId);
|
||||||
const hasTargetHandleId = edge.target.includes('__');
|
const targetNode = nodes.find(n => n.id === targetId);
|
||||||
|
|
||||||
const sourceId = hasSourceHandleId ? edge.source.split('__')[0] : edge.source;
|
|
||||||
const targetId = hasTargetHandleId ? edge.target.split('__')[0] : edge.target;
|
|
||||||
|
|
||||||
const sourceHandleId = hasSourceHandleId ? edge.source.split('__')[1] : null;
|
|
||||||
const targetHandleId = hasTargetHandleId ? edge.target.split('__')[1] : null;
|
|
||||||
|
|
||||||
const sourceNode = state.nodes.find(n => n.id === sourceId);
|
|
||||||
const targetNode = state.nodes.find(n => n.id === targetId);
|
|
||||||
|
|
||||||
if (!sourceNode) {
|
if (!sourceNode) {
|
||||||
throw new Error(`couldn't create edge for source id: ${sourceId}`);
|
throw new Error(`couldn't create edge for source id: ${sourceId}`);
|
||||||
@@ -144,7 +127,7 @@ function renderEdge(edge: Edge, props: EdgeRendererProps, state: EdgeRendererSta
|
|||||||
if (!targetNode) {
|
if (!targetNode) {
|
||||||
throw new Error(`couldn't create edge for target id: ${targetId}`);
|
throw new Error(`couldn't create edge for target id: ${targetId}`);
|
||||||
}
|
}
|
||||||
|
const edgeType = edge.type || 'default';
|
||||||
const EdgeComponent = props.edgeTypes[edgeType] || props.edgeTypes.default;
|
const EdgeComponent = props.edgeTypes[edgeType] || props.edgeTypes.default;
|
||||||
const sourceHandle = getHandle(sourceNode.__rg.handleBounds.source, sourceHandleId);
|
const sourceHandle = getHandle(sourceNode.__rg.handleBounds.source, sourceHandleId);
|
||||||
const targetHandle = getHandle(targetNode.__rg.handleBounds.target, targetHandleId);
|
const targetHandle = getHandle(targetNode.__rg.handleBounds.target, targetHandleId);
|
||||||
@@ -159,9 +142,10 @@ function renderEdge(edge: Edge, props: EdgeRendererProps, state: EdgeRendererSta
|
|||||||
targetHandle,
|
targetHandle,
|
||||||
targetPosition
|
targetPosition
|
||||||
);
|
);
|
||||||
const selected = state.selectedElements
|
|
||||||
.filter(isEdge)
|
const isSelected = (selectedElements as Edge[]).some(
|
||||||
.find((elm: Edge) => elm.source === sourceId && elm.target === targetId);
|
elm => isEdge(elm) && elm.source === sourceId && elm.target === targetId
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EdgeComponent
|
<EdgeComponent
|
||||||
@@ -169,7 +153,7 @@ function renderEdge(edge: Edge, props: EdgeRendererProps, state: EdgeRendererSta
|
|||||||
id={edge.id}
|
id={edge.id}
|
||||||
type={edge.type}
|
type={edge.type}
|
||||||
onClick={props.onElementClick}
|
onClick={props.onElementClick}
|
||||||
selected={selected}
|
selected={isSelected}
|
||||||
animated={edge.animated}
|
animated={edge.animated}
|
||||||
style={edge.style}
|
style={edge.style}
|
||||||
source={sourceId}
|
source={sourceId}
|
||||||
@@ -186,44 +170,35 @@ function renderEdge(edge: Edge, props: EdgeRendererProps, state: EdgeRendererSta
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const EdgeRenderer = memo(({ width, height, connectionLineStyle, connectionLineType, ...rest }: EdgeRendererProps) => {
|
const EdgeRenderer = memo((props: EdgeRendererProps) => {
|
||||||
const state: EdgeRendererState = useStoreState(s => ({
|
const {
|
||||||
nodes: s.nodes,
|
transform,
|
||||||
edges: s.edges,
|
edges,
|
||||||
transform: s.transform,
|
nodes,
|
||||||
selectedElements: s.selectedElements,
|
connectionSourceId,
|
||||||
connectionSourceId: s.connectionSourceId,
|
connectionPosition: { x, y },
|
||||||
position: s.connectionPosition,
|
selectedElements,
|
||||||
}));
|
} = useStoreState(s => s);
|
||||||
|
|
||||||
|
const { width, height, connectionLineStyle, connectionLineType } = props;
|
||||||
|
|
||||||
if (!width) {
|
if (!width) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { transform, edges, nodes, connectionSourceId, position } = state;
|
const [tx, ty, tScale] = transform;
|
||||||
const transformStyle = `translate(${transform[0]},${transform[1]}) scale(${transform[2]})`;
|
const transformStyle = `translate(${tx},${ty}) scale(${tScale})`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg width={width} height={height} className="react-flow__edges">
|
<svg width={width} height={height} className="react-flow__edges">
|
||||||
<g transform={transformStyle}>
|
<g transform={transformStyle}>
|
||||||
{edges.map((e: Edge) =>
|
{edges.map((e: Edge) => renderEdge(e, props, nodes, selectedElements))}
|
||||||
renderEdge(
|
|
||||||
e,
|
|
||||||
{
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
connectionLineStyle,
|
|
||||||
connectionLineType,
|
|
||||||
...rest,
|
|
||||||
},
|
|
||||||
state
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
{connectionSourceId && (
|
{connectionSourceId && (
|
||||||
<ConnectionLine
|
<ConnectionLine
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
connectionSourceId={connectionSourceId}
|
connectionSourceId={connectionSourceId}
|
||||||
connectionPositionX={position.x}
|
connectionPositionX={x}
|
||||||
connectionPositionY={position.y}
|
connectionPositionY={y}
|
||||||
transform={transform}
|
transform={transform}
|
||||||
connectionLineStyle={connectionLineStyle}
|
connectionLineStyle={connectionLineStyle}
|
||||||
connectionLineType={connectionLineType}
|
connectionLineType={connectionLineType}
|
||||||
|
|||||||
Reference in New Issue
Block a user