diff --git a/README.md b/README.md
index 01f9e87e..d4521011 100644
--- a/README.md
+++ b/README.md
@@ -123,6 +123,7 @@ const BasicFlow = () => ;
#### Connection Line Options
- `connectionLineType`: connection line type = `default` (bezier), `straight`, `step`, `smoothstep`
- `connectionLineStyle`: connection style as svg attributes
+- `connectionLineComponent`: [custom connection line component](/example/src/CustomConnectionLin/index.js)
#### Keys
- `deleteKeyCode`: default: `8` (delete)
diff --git a/example/src/CustomConnectionLine/ConnectionLine.js b/example/src/CustomConnectionLine/ConnectionLine.js
new file mode 100644
index 00000000..e48fafb3
--- /dev/null
+++ b/example/src/CustomConnectionLine/ConnectionLine.js
@@ -0,0 +1,25 @@
+import React from 'react';
+
+export default ({
+ sourceX,
+ sourceY,
+ sourcePosition,
+ targetX,
+ targetY,
+ targetPosition,
+ connectionLineType,
+ connectionLineStyle,
+}) => {
+ return (
+
+
+
+
+ );
+};
diff --git a/example/src/CustomConnectionLine/index.js b/example/src/CustomConnectionLine/index.js
new file mode 100644
index 00000000..d1663843
--- /dev/null
+++ b/example/src/CustomConnectionLine/index.js
@@ -0,0 +1,25 @@
+import React, { useState } from 'react';
+import ReactFlow, { removeElements, addEdge, Background } from 'react-flow-renderer';
+
+import ConnectionLine from './ConnectionLine';
+
+const initialElements = [{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } }];
+
+const ConnectionLineFlow = () => {
+ const [elements, setElements] = useState(initialElements);
+ const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
+ const onConnect = (params) => setElements((els) => addEdge(params, els));
+
+ return (
+
+
+
+ );
+};
+
+export default ConnectionLineFlow;
diff --git a/example/src/index.js b/example/src/index.js
index 51b9c00f..49e54ccf 100644
--- a/example/src/index.js
+++ b/example/src/index.js
@@ -14,6 +14,7 @@ import Horizontal from './Horizontal';
import Provider from './Provider';
import Hidden from './Hidden';
import EdgeTypes from './EdgeTypes';
+import CustomConnectionLine from './CustomConnectionLine';
import './index.css';
@@ -74,6 +75,10 @@ const routes = [
path: '/edge-types',
component: EdgeTypes,
},
+ {
+ path: '/custom-connectionline',
+ component: CustomConnectionLine,
+ },
];
const navLinks = routes.filter((route) => route.label);
diff --git a/src/components/ConnectionLine/index.tsx b/src/components/ConnectionLine/index.tsx
index 4d010e2f..05d942e3 100644
--- a/src/components/ConnectionLine/index.tsx
+++ b/src/components/ConnectionLine/index.tsx
@@ -1,9 +1,17 @@
import React, { useEffect, useState, CSSProperties } from 'react';
-import cc from 'classcat';
import { getBezierPath } from '../Edges/BezierEdge';
import { getSmoothStepPath } from '../Edges/SmoothStepEdge';
-import { ElementId, Node, Transform, HandleElement, Position, ConnectionLineType, HandleType } from '../../types';
+import {
+ ElementId,
+ Node,
+ Transform,
+ HandleElement,
+ Position,
+ ConnectionLineType,
+ ConnectionLineComponent,
+ HandleType,
+} from '../../types';
interface ConnectionLineProps {
connectionNodeId: ElementId;
@@ -15,7 +23,7 @@ interface ConnectionLineProps {
transform: Transform;
isConnectable: boolean;
connectionLineStyle?: CSSProperties;
- className?: string;
+ CustomConnectionLineComponent?: ConnectionLineComponent;
}
export default ({
@@ -26,9 +34,9 @@ export default ({
connectionPositionY,
connectionLineType = ConnectionLineType.Bezier,
nodes = [],
- className,
transform,
isConnectable,
+ CustomConnectionLineComponent,
}: ConnectionLineProps) => {
const [sourceNode, setSourceNode] = useState(null);
const hasHandleId = connectionNodeId.includes('__');
@@ -45,8 +53,6 @@ export default ({
return null;
}
- const connectionLineClasses: string = cc(['react-flow__connection', className]);
-
const sourceHandle = handleId
? sourceNode.__rf.handleBounds[connectionHandleType].find((d: HandleElement) => d.id === handleId)
: sourceNode.__rf.handleBounds[connectionHandleType][0];
@@ -55,14 +61,31 @@ export default ({
const sourceX = sourceNode.__rf.position.x + sourceHandleX;
const sourceY = sourceNode.__rf.position.y + sourceHandleY;
- const targetX = (connectionPositionX - transform[0]) * (1 / transform[2]);
- const targetY = (connectionPositionY - transform[1]) * (1 / transform[2]);
-
- let dAttr: string = '';
+ const targetX = (connectionPositionX - transform[0]) / transform[2];
+ const targetY = (connectionPositionY - transform[1]) / transform[2];
const isRightOrLeft = sourceHandle?.position === Position.Left || sourceHandle?.position === Position.Right;
const targetPosition = isRightOrLeft ? Position.Left : Position.Top;
+ if (CustomConnectionLineComponent) {
+ return (
+
+
+
+ );
+ }
+
+ let dAttr: string = '';
+
if (connectionLineType === ConnectionLineType.Bezier) {
dAttr = getBezierPath({
sourceX,
@@ -96,7 +119,7 @@ export default ({
}
return (
-
+
);
diff --git a/src/container/EdgeRenderer/index.tsx b/src/container/EdgeRenderer/index.tsx
index b84161a3..e3ba07bd 100644
--- a/src/container/EdgeRenderer/index.tsx
+++ b/src/container/EdgeRenderer/index.tsx
@@ -4,7 +4,17 @@ import { useStoreState } from '../../store/hooks';
import ConnectionLine from '../../components/ConnectionLine/index';
import { isEdge } from '../../utils/graph';
import MarkerDefinitions from './MarkerDefinitions';
-import { XYPosition, Position, Edge, Node, ElementId, HandleElement, Elements, ConnectionLineType } from '../../types';
+import {
+ XYPosition,
+ Position,
+ Edge,
+ Node,
+ ElementId,
+ HandleElement,
+ Elements,
+ ConnectionLineType,
+ ConnectionLineComponent,
+} from '../../types';
interface EdgeRendererProps {
edgeTypes: any;
@@ -13,6 +23,7 @@ interface EdgeRendererProps {
onElementClick?: (event: React.MouseEvent, element: Node | Edge) => void;
arrowHeadColor: string;
markerEndId?: string;
+ connectionLineComponent?: ConnectionLineComponent;
}
interface EdgePositions {
@@ -193,19 +204,19 @@ function renderEdge(
}
const EdgeRenderer = (props: EdgeRendererProps) => {
- const [tX, tY, tScale] = useStoreState((s) => s.transform);
- const edges = useStoreState((s) => s.edges);
- const nodes = useStoreState((s) => s.nodes);
- const connectionNodeId = useStoreState((s) => s.connectionNodeId);
- const connectionHandleType = useStoreState((s) => s.connectionHandleType);
- const connectionPosition = useStoreState((s) => s.connectionPosition);
- const selectedElements = useStoreState((s) => s.selectedElements);
- const nodesConnectable = useStoreState((s) => s.nodesConnectable);
- const elementsSelectable = useStoreState((s) => s.elementsSelectable);
+ const [tX, tY, tScale] = useStoreState((state) => state.transform);
+ const edges = useStoreState((state) => state.edges);
+ const nodes = useStoreState((state) => state.nodes);
+ const connectionNodeId = useStoreState((state) => state.connectionNodeId);
+ const connectionHandleType = useStoreState((state) => state.connectionHandleType);
+ const connectionPosition = useStoreState((state) => state.connectionPosition);
+ const selectedElements = useStoreState((state) => state.selectedElements);
+ const nodesConnectable = useStoreState((state) => state.nodesConnectable);
+ const elementsSelectable = useStoreState((state) => state.elementsSelectable);
const width = useStoreState((state) => state.width);
const height = useStoreState((state) => state.height);
- const { connectionLineStyle, connectionLineType, arrowHeadColor } = props;
+ const { connectionLineStyle, connectionLineType, arrowHeadColor, connectionLineComponent } = props;
if (!width) {
return null;
@@ -218,7 +229,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {