feat(markers): implement more generic api for markerEnd and markerStart handling
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { EdgeProps, getBezierPath, getMarkerEnd } from 'react-flow-renderer';
|
import { EdgeProps, getBezierPath } from 'react-flow-renderer';
|
||||||
|
|
||||||
const CustomEdge: FC<EdgeProps> = ({
|
const CustomEdge: FC<EdgeProps> = ({
|
||||||
id,
|
id,
|
||||||
@@ -10,15 +10,12 @@ const CustomEdge: FC<EdgeProps> = ({
|
|||||||
sourcePosition,
|
sourcePosition,
|
||||||
targetPosition,
|
targetPosition,
|
||||||
data,
|
data,
|
||||||
arrowHeadType,
|
|
||||||
markerEndId,
|
|
||||||
}) => {
|
}) => {
|
||||||
const edgePath = getBezierPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition });
|
const edgePath = getBezierPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition });
|
||||||
const markerEnd = getMarkerEnd(arrowHeadType, markerEndId);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<path id={id} className="react-flow__edge-path" d={edgePath} markerEnd={markerEnd} />
|
<path id={id} className="react-flow__edge-path" d={edgePath} />
|
||||||
<text>
|
<text>
|
||||||
<textPath href={`#${id}`} style={{ fontSize: '12px' }} startOffset="50%" textAnchor="middle">
|
<textPath href={`#${id}`} style={{ fontSize: '12px' }} startOffset="50%" textAnchor="middle">
|
||||||
{data.text}
|
{data.text}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { EdgeProps, getBezierPath, getMarkerEnd, EdgeText, getEdgeCenter } from 'react-flow-renderer';
|
import { EdgeProps, getBezierPath, EdgeText, getEdgeCenter } from 'react-flow-renderer';
|
||||||
|
|
||||||
const CustomEdge: FC<EdgeProps> = ({
|
const CustomEdge: FC<EdgeProps> = ({
|
||||||
id,
|
id,
|
||||||
@@ -10,11 +10,8 @@ const CustomEdge: FC<EdgeProps> = ({
|
|||||||
sourcePosition,
|
sourcePosition,
|
||||||
targetPosition,
|
targetPosition,
|
||||||
data,
|
data,
|
||||||
arrowHeadType,
|
|
||||||
markerEndId,
|
|
||||||
}) => {
|
}) => {
|
||||||
const edgePath = getBezierPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition });
|
const edgePath = getBezierPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition });
|
||||||
const markerEnd = getMarkerEnd(arrowHeadType, markerEndId);
|
|
||||||
const [centerX, centerY] = getEdgeCenter({
|
const [centerX, centerY] = getEdgeCenter({
|
||||||
sourceX,
|
sourceX,
|
||||||
sourceY,
|
sourceY,
|
||||||
@@ -24,7 +21,7 @@ const CustomEdge: FC<EdgeProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<path id={id} className="react-flow__edge-path" d={edgePath} markerEnd={markerEnd} />
|
<path id={id} className="react-flow__edge-path" d={edgePath} />
|
||||||
<EdgeText
|
<EdgeText
|
||||||
x={centerX}
|
x={centerX}
|
||||||
y={centerY}
|
y={centerY}
|
||||||
|
|||||||
@@ -54,7 +54,14 @@ const initialElements: Elements = [
|
|||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
labelStyle: { fill: 'red', fontWeight: 700 },
|
labelStyle: { fill: 'red', fontWeight: 700 },
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
style: { stroke: '#ffcc00' },
|
||||||
|
markerEnd: {
|
||||||
|
type: ArrowHeadType.ArrowClosed,
|
||||||
|
},
|
||||||
|
markerStart: {
|
||||||
|
type: ArrowHeadType.Arrow,
|
||||||
|
color: '#FFCC00',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e5-7',
|
id: 'e5-7',
|
||||||
@@ -64,7 +71,10 @@ const initialElements: Elements = [
|
|||||||
labelBgPadding: [8, 4],
|
labelBgPadding: [8, 4],
|
||||||
labelBgBorderRadius: 4,
|
labelBgBorderRadius: 4,
|
||||||
labelBgStyle: { fill: '#FFCC00', color: '#fff', fillOpacity: 0.7 },
|
labelBgStyle: { fill: '#FFCC00', color: '#fff', fillOpacity: 0.7 },
|
||||||
arrowHeadType: ArrowHeadType.ArrowClosed,
|
markerEnd: {
|
||||||
|
type: ArrowHeadType.ArrowClosed,
|
||||||
|
color: '#FFCC00',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e5-8',
|
id: 'e5-8',
|
||||||
@@ -72,7 +82,6 @@ const initialElements: Elements = [
|
|||||||
target: '8',
|
target: '8',
|
||||||
type: 'custom',
|
type: 'custom',
|
||||||
data: { text: 'custom edge' },
|
data: { text: 'custom edge' },
|
||||||
arrowHeadType: ArrowHeadType.ArrowClosed,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e5-9',
|
id: 'e5-9',
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { FC, useMemo, CSSProperties } from 'react';
|
import { FC, useMemo, CSSProperties } from 'react';
|
||||||
import { EdgeProps, getMarkerEnd, useStoreState, getBezierPath } from 'react-flow-renderer';
|
import { EdgeProps, useStoreState, getBezierPath } from 'react-flow-renderer';
|
||||||
|
|
||||||
import { getEdgeParams } from './utils';
|
import { getEdgeParams } from './utils';
|
||||||
|
|
||||||
const FloatingEdge: FC<EdgeProps> = ({ id, source, target, arrowHeadType, markerEndId, style }) => {
|
const FloatingEdge: FC<EdgeProps> = ({ id, source, target, style }) => {
|
||||||
const nodes = useStoreState((state) => state.nodes);
|
const nodes = useStoreState((state) => state.nodes);
|
||||||
const markerEnd = getMarkerEnd(arrowHeadType, markerEndId);
|
|
||||||
|
|
||||||
const sourceNode = useMemo(() => nodes.find((n) => n.id === source), [source, nodes]);
|
const sourceNode = useMemo(() => nodes.find((n) => n.id === source), [source, nodes]);
|
||||||
const targetNode = useMemo(() => nodes.find((n) => n.id === target), [target, nodes]);
|
const targetNode = useMemo(() => nodes.find((n) => n.id === target), [target, nodes]);
|
||||||
@@ -27,7 +26,7 @@ const FloatingEdge: FC<EdgeProps> = ({ id, source, target, arrowHeadType, marker
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<g className="react-flow__connection">
|
<g className="react-flow__connection">
|
||||||
<path id={id} className="react-flow__edge-path" d={d} markerEnd={markerEnd} style={style as CSSProperties} />
|
<path id={id} className="react-flow__edge-path" d={d} style={style as CSSProperties} />
|
||||||
</g>
|
</g>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import ReactFlow, {
|
|||||||
Elements,
|
Elements,
|
||||||
Connection,
|
Connection,
|
||||||
Edge,
|
Edge,
|
||||||
ArrowHeadType,
|
|
||||||
} from 'react-flow-renderer';
|
} from 'react-flow-renderer';
|
||||||
|
|
||||||
import './style.css';
|
import './style.css';
|
||||||
@@ -31,8 +30,7 @@ const NodeAsHandleFlow = () => {
|
|||||||
|
|
||||||
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
|
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
|
||||||
|
|
||||||
const onConnect = (params: Connection | Edge) =>
|
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge({ ...params, type: 'floating' }, els));
|
||||||
setElements((els) => addEdge({ ...params, type: 'floating', arrowHeadType: ArrowHeadType.Arrow }, els));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="floatingedges">
|
<div className="floatingedges">
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import ReactFlow, {
|
|||||||
OnLoadParams,
|
OnLoadParams,
|
||||||
FlowTransform,
|
FlowTransform,
|
||||||
SnapGrid,
|
SnapGrid,
|
||||||
ArrowHeadType,
|
|
||||||
Connection,
|
Connection,
|
||||||
Edge,
|
Edge,
|
||||||
} from 'react-flow-renderer';
|
} from 'react-flow-renderer';
|
||||||
@@ -125,7 +124,7 @@ const initialElements: Elements = [
|
|||||||
{ id: 'e1-2', source: '1', target: '2', label: 'this is an edge label' },
|
{ id: 'e1-2', source: '1', target: '2', label: 'this is an edge label' },
|
||||||
{ id: 'e1-3', source: '1', target: '3' },
|
{ id: 'e1-3', source: '1', target: '3' },
|
||||||
{ id: 'e3-4', source: '3', target: '4', animated: true, label: 'animated edge' },
|
{ id: 'e3-4', source: '3', target: '4', animated: true, label: 'animated edge' },
|
||||||
{ id: 'e4-5', source: '4', target: '5', arrowHeadType: ArrowHeadType.Arrow, label: 'edge with arrow head' },
|
{ id: 'e4-5', source: '4', target: '5', label: 'edge with arrow head' },
|
||||||
{ id: 'e5-6', source: '5', target: '6', type: 'smoothstep', label: 'smooth step edge' },
|
{ id: 'e5-6', source: '5', target: '6', type: 'smoothstep', label: 'smooth step edge' },
|
||||||
{
|
{
|
||||||
id: 'e5-7',
|
id: 'e5-7',
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import ReactFlow, {
|
|||||||
ConnectionLineType,
|
ConnectionLineType,
|
||||||
ConnectionMode,
|
ConnectionMode,
|
||||||
updateEdge,
|
updateEdge,
|
||||||
ArrowHeadType,
|
|
||||||
} from 'react-flow-renderer';
|
} from 'react-flow-renderer';
|
||||||
import CustomNode from './CustomNode';
|
import CustomNode from './CustomNode';
|
||||||
|
|
||||||
@@ -69,7 +68,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'left',
|
sourceHandle: 'left',
|
||||||
targetHandle: 'bottom',
|
targetHandle: 'bottom',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e0-1b',
|
id: 'e0-1b',
|
||||||
@@ -78,7 +76,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'top',
|
sourceHandle: 'top',
|
||||||
targetHandle: 'right',
|
targetHandle: 'right',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e0-2a',
|
id: 'e0-2a',
|
||||||
@@ -87,7 +84,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'top',
|
sourceHandle: 'top',
|
||||||
targetHandle: 'left',
|
targetHandle: 'left',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e0-2b',
|
id: 'e0-2b',
|
||||||
@@ -96,7 +92,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'right',
|
sourceHandle: 'right',
|
||||||
targetHandle: 'bottom',
|
targetHandle: 'bottom',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e0-3a',
|
id: 'e0-3a',
|
||||||
@@ -105,7 +100,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'right',
|
sourceHandle: 'right',
|
||||||
targetHandle: 'top',
|
targetHandle: 'top',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e0-3b',
|
id: 'e0-3b',
|
||||||
@@ -114,7 +108,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'bottom',
|
sourceHandle: 'bottom',
|
||||||
targetHandle: 'left',
|
targetHandle: 'left',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e0-4a',
|
id: 'e0-4a',
|
||||||
@@ -123,7 +116,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'bottom',
|
sourceHandle: 'bottom',
|
||||||
targetHandle: 'right',
|
targetHandle: 'right',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e0-4b',
|
id: 'e0-4b',
|
||||||
@@ -132,7 +124,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'left',
|
sourceHandle: 'left',
|
||||||
targetHandle: 'top',
|
targetHandle: 'top',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e0-10',
|
id: 'e0-10',
|
||||||
@@ -141,7 +132,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'top',
|
sourceHandle: 'top',
|
||||||
targetHandle: 'bottom',
|
targetHandle: 'bottom',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e0-20',
|
id: 'e0-20',
|
||||||
@@ -150,7 +140,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'right',
|
sourceHandle: 'right',
|
||||||
targetHandle: 'left',
|
targetHandle: 'left',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e0-30',
|
id: 'e0-30',
|
||||||
@@ -159,7 +148,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'bottom',
|
sourceHandle: 'bottom',
|
||||||
targetHandle: 'top',
|
targetHandle: 'top',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e0-40',
|
id: 'e0-40',
|
||||||
@@ -168,7 +156,6 @@ const initialElements: Elements = [
|
|||||||
sourceHandle: 'left',
|
sourceHandle: 'left',
|
||||||
targetHandle: 'right',
|
targetHandle: 'right',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { memo } from 'react';
|
|||||||
|
|
||||||
import EdgeText from './EdgeText';
|
import EdgeText from './EdgeText';
|
||||||
|
|
||||||
import { getMarkerEnd, getCenter } from './utils';
|
import { getCenter } from './utils';
|
||||||
import { EdgeProps, Position } from '../../types';
|
import { EdgeProps, Position } from '../../types';
|
||||||
|
|
||||||
interface GetBezierPathParams {
|
interface GetBezierPathParams {
|
||||||
@@ -60,8 +60,8 @@ export default memo(
|
|||||||
labelBgPadding,
|
labelBgPadding,
|
||||||
labelBgBorderRadius,
|
labelBgBorderRadius,
|
||||||
style,
|
style,
|
||||||
arrowHeadType,
|
markerEnd,
|
||||||
markerEndId,
|
markerStart,
|
||||||
}: EdgeProps) => {
|
}: EdgeProps) => {
|
||||||
const [centerX, centerY] = getCenter({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition });
|
const [centerX, centerY] = getCenter({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition });
|
||||||
const path = getBezierPath({
|
const path = getBezierPath({
|
||||||
@@ -86,11 +86,15 @@ export default memo(
|
|||||||
/>
|
/>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
const markerEnd = getMarkerEnd(arrowHeadType, markerEndId);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<path style={style} d={path} className="react-flow__edge-path" markerEnd={markerEnd} />
|
<path
|
||||||
|
style={style}
|
||||||
|
d={path}
|
||||||
|
className="react-flow__edge-path"
|
||||||
|
markerEnd={markerEnd}
|
||||||
|
markerStart={markerStart}
|
||||||
|
/>
|
||||||
{text}
|
{text}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
|
|
||||||
import EdgeText from './EdgeText';
|
import EdgeText from './EdgeText';
|
||||||
import { getMarkerEnd, getCenter } from './utils';
|
import { getCenter } from './utils';
|
||||||
import { EdgeSmoothStepProps, Position } from '../../types';
|
import { EdgeSmoothStepProps, Position } from '../../types';
|
||||||
|
|
||||||
// These are some helper methods for drawing the round corners
|
// These are some helper methods for drawing the round corners
|
||||||
@@ -73,8 +73,8 @@ export function getSmoothStepPath({
|
|||||||
sourceY <= targetY ? rightTopCorner(cX, sourceY, cornerSize) : rightBottomCorner(cX, sourceY, cornerSize);
|
sourceY <= targetY ? rightTopCorner(cX, sourceY, cornerSize) : rightBottomCorner(cX, sourceY, cornerSize);
|
||||||
secondCornerPath =
|
secondCornerPath =
|
||||||
sourceY <= targetY ? bottomLeftCorner(cX, targetY, cornerSize) : topLeftCorner(cX, targetY, cornerSize);
|
sourceY <= targetY ? bottomLeftCorner(cX, targetY, cornerSize) : topLeftCorner(cX, targetY, cornerSize);
|
||||||
} else if (sourcePosition === Position.Right && targetPosition === Position.Left){
|
} else if (sourcePosition === Position.Right && targetPosition === Position.Left) {
|
||||||
// and sourceX > targetX
|
// and sourceX > targetX
|
||||||
firstCornerPath =
|
firstCornerPath =
|
||||||
sourceY <= targetY ? leftTopCorner(cX, sourceY, cornerSize) : leftBottomCorner(cX, sourceY, cornerSize);
|
sourceY <= targetY ? leftTopCorner(cX, sourceY, cornerSize) : leftBottomCorner(cX, sourceY, cornerSize);
|
||||||
secondCornerPath =
|
secondCornerPath =
|
||||||
@@ -126,8 +126,8 @@ export default memo(
|
|||||||
style,
|
style,
|
||||||
sourcePosition = Position.Bottom,
|
sourcePosition = Position.Bottom,
|
||||||
targetPosition = Position.Top,
|
targetPosition = Position.Top,
|
||||||
arrowHeadType,
|
markerEnd,
|
||||||
markerEndId,
|
markerStart,
|
||||||
borderRadius = 5,
|
borderRadius = 5,
|
||||||
}: EdgeSmoothStepProps) => {
|
}: EdgeSmoothStepProps) => {
|
||||||
const [centerX, centerY] = getCenter({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition });
|
const [centerX, centerY] = getCenter({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition });
|
||||||
@@ -142,8 +142,6 @@ export default memo(
|
|||||||
borderRadius,
|
borderRadius,
|
||||||
});
|
});
|
||||||
|
|
||||||
const markerEnd = getMarkerEnd(arrowHeadType, markerEndId);
|
|
||||||
|
|
||||||
const text = label ? (
|
const text = label ? (
|
||||||
<EdgeText
|
<EdgeText
|
||||||
x={centerX}
|
x={centerX}
|
||||||
@@ -159,7 +157,13 @@ export default memo(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<path style={style} className="react-flow__edge-path" d={path} markerEnd={markerEnd} />
|
<path
|
||||||
|
style={style}
|
||||||
|
className="react-flow__edge-path"
|
||||||
|
d={path}
|
||||||
|
markerEnd={markerEnd}
|
||||||
|
markerStart={markerStart}
|
||||||
|
/>
|
||||||
{text}
|
{text}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
|
|
||||||
import EdgeText from './EdgeText';
|
import EdgeText from './EdgeText';
|
||||||
import { getMarkerEnd } from './utils';
|
|
||||||
import { EdgeProps } from '../../types';
|
import { EdgeProps } from '../../types';
|
||||||
|
|
||||||
export default memo(
|
export default memo(
|
||||||
@@ -17,15 +16,14 @@ export default memo(
|
|||||||
labelBgPadding,
|
labelBgPadding,
|
||||||
labelBgBorderRadius,
|
labelBgBorderRadius,
|
||||||
style,
|
style,
|
||||||
arrowHeadType,
|
markerEnd,
|
||||||
markerEndId,
|
markerStart,
|
||||||
}: EdgeProps) => {
|
}: EdgeProps) => {
|
||||||
const yOffset = Math.abs(targetY - sourceY) / 2;
|
const yOffset = Math.abs(targetY - sourceY) / 2;
|
||||||
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
||||||
|
|
||||||
const xOffset = Math.abs(targetX - sourceX) / 2;
|
const xOffset = Math.abs(targetX - sourceX) / 2;
|
||||||
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
|
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
|
||||||
const markerEnd = getMarkerEnd(arrowHeadType, markerEndId);
|
|
||||||
|
|
||||||
const text = label ? (
|
const text = label ? (
|
||||||
<EdgeText
|
<EdgeText
|
||||||
@@ -47,6 +45,7 @@ export default memo(
|
|||||||
className="react-flow__edge-path"
|
className="react-flow__edge-path"
|
||||||
d={`M ${sourceX},${sourceY}L ${targetX},${targetY}`}
|
d={`M ${sourceX},${sourceY}L ${targetX},${targetY}`}
|
||||||
markerEnd={markerEnd}
|
markerEnd={markerEnd}
|
||||||
|
markerStart={markerStart}
|
||||||
/>
|
/>
|
||||||
{text}
|
{text}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useStoreActions, useStoreState } from '../../store/hooks';
|
|||||||
import { Edge, EdgeProps, WrapEdgeProps } from '../../types';
|
import { Edge, EdgeProps, WrapEdgeProps } from '../../types';
|
||||||
import { onMouseDown } from '../../components/Handle/handler';
|
import { onMouseDown } from '../../components/Handle/handler';
|
||||||
import { EdgeAnchor } from './EdgeAnchor';
|
import { EdgeAnchor } from './EdgeAnchor';
|
||||||
|
import { getMarkerId } from '../../utils/graph';
|
||||||
|
|
||||||
export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
||||||
const EdgeWrapper = ({
|
const EdgeWrapper = ({
|
||||||
@@ -23,7 +24,6 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
|||||||
labelBgPadding,
|
labelBgPadding,
|
||||||
labelBgBorderRadius,
|
labelBgBorderRadius,
|
||||||
style,
|
style,
|
||||||
arrowHeadType,
|
|
||||||
source,
|
source,
|
||||||
target,
|
target,
|
||||||
sourceX,
|
sourceX,
|
||||||
@@ -33,7 +33,6 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
|||||||
sourcePosition,
|
sourcePosition,
|
||||||
targetPosition,
|
targetPosition,
|
||||||
elementsSelectable,
|
elementsSelectable,
|
||||||
markerEndId,
|
|
||||||
isHidden,
|
isHidden,
|
||||||
sourceHandleId,
|
sourceHandleId,
|
||||||
targetHandleId,
|
targetHandleId,
|
||||||
@@ -46,6 +45,8 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
|||||||
edgeUpdaterRadius,
|
edgeUpdaterRadius,
|
||||||
onEdgeUpdateStart,
|
onEdgeUpdateStart,
|
||||||
onEdgeUpdateEnd,
|
onEdgeUpdateEnd,
|
||||||
|
markerEnd,
|
||||||
|
markerStart,
|
||||||
}: WrapEdgeProps): JSX.Element | null => {
|
}: WrapEdgeProps): JSX.Element | null => {
|
||||||
const addSelectedElements = useStoreActions((actions) => actions.addSelectedElements);
|
const addSelectedElements = useStoreActions((actions) => actions.addSelectedElements);
|
||||||
const setConnectionNodeId = useStoreActions((actions) => actions.setConnectionNodeId);
|
const setConnectionNodeId = useStoreActions((actions) => actions.setConnectionNodeId);
|
||||||
@@ -160,7 +161,18 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
|||||||
_onEdgeUpdate
|
_onEdgeUpdate
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[id, source, target, type, sourceHandleId, targetHandleId, setConnectionNodeId, setPosition, edgeElement, onConnectEdge]
|
[
|
||||||
|
id,
|
||||||
|
source,
|
||||||
|
target,
|
||||||
|
type,
|
||||||
|
sourceHandleId,
|
||||||
|
targetHandleId,
|
||||||
|
setConnectionNodeId,
|
||||||
|
setPosition,
|
||||||
|
edgeElement,
|
||||||
|
onConnectEdge,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onEdgeUpdaterSourceMouseDown = useCallback(
|
const onEdgeUpdaterSourceMouseDown = useCallback(
|
||||||
@@ -179,6 +191,8 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
|||||||
|
|
||||||
const onEdgeUpdaterMouseEnter = useCallback(() => setUpdating(true), [setUpdating]);
|
const onEdgeUpdaterMouseEnter = useCallback(() => setUpdating(true), [setUpdating]);
|
||||||
const onEdgeUpdaterMouseOut = useCallback(() => setUpdating(false), [setUpdating]);
|
const onEdgeUpdaterMouseOut = useCallback(() => setUpdating(false), [setUpdating]);
|
||||||
|
const markerStartUrl = useMemo(() => `url(#${getMarkerId(markerStart)})`, [markerStart]);
|
||||||
|
const markerEndUrl = useMemo(() => `url(#${getMarkerId(markerEnd)})`, [markerEnd]);
|
||||||
|
|
||||||
if (isHidden) {
|
if (isHidden) {
|
||||||
return null;
|
return null;
|
||||||
@@ -208,16 +222,16 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
|||||||
labelBgBorderRadius={labelBgBorderRadius}
|
labelBgBorderRadius={labelBgBorderRadius}
|
||||||
data={data}
|
data={data}
|
||||||
style={style}
|
style={style}
|
||||||
arrowHeadType={arrowHeadType}
|
|
||||||
sourceX={sourceX}
|
sourceX={sourceX}
|
||||||
sourceY={sourceY}
|
sourceY={sourceY}
|
||||||
targetX={targetX}
|
targetX={targetX}
|
||||||
targetY={targetY}
|
targetY={targetY}
|
||||||
sourcePosition={sourcePosition}
|
sourcePosition={sourcePosition}
|
||||||
targetPosition={targetPosition}
|
targetPosition={targetPosition}
|
||||||
markerEndId={markerEndId}
|
|
||||||
sourceHandleId={sourceHandleId}
|
sourceHandleId={sourceHandleId}
|
||||||
targetHandleId={targetHandleId}
|
targetHandleId={targetHandleId}
|
||||||
|
markerStart={markerStartUrl}
|
||||||
|
markerEnd={markerEndUrl}
|
||||||
/>
|
/>
|
||||||
{handleEdgeUpdate && (
|
{handleEdgeUpdate && (
|
||||||
<g
|
<g
|
||||||
|
|||||||
@@ -1,52 +1,98 @@
|
|||||||
import React, { ReactNode } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
|
import { useStoreState } from '../../store/hooks';
|
||||||
|
import { EdgeMarker, ArrowHeadType } from '../../types';
|
||||||
|
import { getMarkerId } from '../../utils/graph';
|
||||||
interface MarkerProps {
|
interface MarkerProps {
|
||||||
id: string;
|
id: string;
|
||||||
children: ReactNode;
|
type: ArrowHeadType;
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
|
interface MarkerDefinitionsProps {
|
||||||
|
defaultColor: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Marker = ({ id, children }: MarkerProps) => (
|
interface SymbolProps {
|
||||||
<marker
|
|
||||||
className="react-flow__arrowhead"
|
|
||||||
id={id}
|
|
||||||
markerWidth="12.5"
|
|
||||||
markerHeight="12.5"
|
|
||||||
viewBox="-10 -10 20 20"
|
|
||||||
orient="auto"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</marker>
|
|
||||||
);
|
|
||||||
|
|
||||||
interface MarkerDefinitionsProps {
|
|
||||||
color: string;
|
color: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MarkerDefinitions = ({ color }: MarkerDefinitionsProps) => {
|
interface EdgeMarkerExtended extends EdgeMarker {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ArrowSymbol = ({ color }: SymbolProps) => {
|
||||||
|
return (
|
||||||
|
<polyline
|
||||||
|
stroke={color}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="1"
|
||||||
|
fill={color}
|
||||||
|
points="-5,-4 0,0 -5,4 -5,-4"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ArrowClosedSymbol = ({ color }: SymbolProps) => {
|
||||||
|
return (
|
||||||
|
<polyline
|
||||||
|
stroke={color}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="1"
|
||||||
|
fill={color}
|
||||||
|
points="-5,-4 0,0 -5,4 -5,-4"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const markerSymbols = {
|
||||||
|
[ArrowHeadType.Arrow]: ArrowSymbol,
|
||||||
|
[ArrowHeadType.ArrowClosed]: ArrowClosedSymbol,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Marker = ({ id, type, color }: MarkerProps) => {
|
||||||
|
const Symbol = markerSymbols[type];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<marker
|
||||||
|
className="react-flow__arrowhead"
|
||||||
|
id={id}
|
||||||
|
markerWidth="12.5"
|
||||||
|
markerHeight="12.5"
|
||||||
|
viewBox="-10 -10 20 20"
|
||||||
|
orient="auto"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
>
|
||||||
|
<Symbol color={color} />
|
||||||
|
</marker>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const MarkerDefinitions = ({ defaultColor }: MarkerDefinitionsProps) => {
|
||||||
|
const edges = useStoreState((state) => state.edges);
|
||||||
|
const markers = useMemo(() => {
|
||||||
|
const ids: string[] = [];
|
||||||
|
|
||||||
|
return edges.reduce<EdgeMarkerExtended[]>((markers, edge) => {
|
||||||
|
[edge.markerStart, edge.markerEnd].forEach((marker) => {
|
||||||
|
if (marker && typeof marker === 'object') {
|
||||||
|
const markerId = getMarkerId(marker);
|
||||||
|
if (!ids.includes(markerId)) {
|
||||||
|
markers.push({ id: markerId, ...marker });
|
||||||
|
ids.push(markerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return markers.sort((a, b) => a.id.localeCompare(b.id));
|
||||||
|
}, []);
|
||||||
|
}, [edges]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<defs>
|
<defs>
|
||||||
<Marker id="react-flow__arrowclosed">
|
{markers.map((marker: EdgeMarkerExtended) => (
|
||||||
<polyline
|
<Marker id={marker.id} key={marker.id} type={marker.type} color={marker.color || defaultColor} />
|
||||||
stroke={color}
|
))}
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="1"
|
|
||||||
fill={color}
|
|
||||||
points="-5,-4 0,0 -5,4 -5,-4"
|
|
||||||
/>
|
|
||||||
</Marker>
|
|
||||||
<Marker id="react-flow__arrow">
|
|
||||||
<polyline
|
|
||||||
stroke={color}
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="1.5"
|
|
||||||
fill="none"
|
|
||||||
points="-5,-4 0,0 -5,4"
|
|
||||||
/>
|
|
||||||
</Marker>
|
|
||||||
</defs>
|
</defs>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,8 +26,7 @@ interface EdgeRendererProps {
|
|||||||
connectionMode?: ConnectionMode;
|
connectionMode?: ConnectionMode;
|
||||||
onElementClick?: (event: React.MouseEvent, element: Node | Edge) => void;
|
onElementClick?: (event: React.MouseEvent, element: Node | Edge) => void;
|
||||||
onEdgeDoubleClick?: (event: React.MouseEvent, edge: Edge) => void;
|
onEdgeDoubleClick?: (event: React.MouseEvent, edge: Edge) => void;
|
||||||
arrowHeadColor: string;
|
defaultMarkerColor: string;
|
||||||
markerEndId?: string;
|
|
||||||
onlyRenderVisibleElements: boolean;
|
onlyRenderVisibleElements: boolean;
|
||||||
onEdgeUpdate?: OnEdgeUpdateFunc;
|
onEdgeUpdate?: OnEdgeUpdateFunc;
|
||||||
onEdgeContextMenu?: (event: React.MouseEvent, edge: Edge) => void;
|
onEdgeContextMenu?: (event: React.MouseEvent, edge: Edge) => void;
|
||||||
@@ -155,7 +154,8 @@ const Edge = ({
|
|||||||
labelBgPadding={edge.labelBgPadding}
|
labelBgPadding={edge.labelBgPadding}
|
||||||
labelBgBorderRadius={edge.labelBgBorderRadius}
|
labelBgBorderRadius={edge.labelBgBorderRadius}
|
||||||
style={edge.style}
|
style={edge.style}
|
||||||
arrowHeadType={edge.arrowHeadType}
|
markerEnd={edge.markerEnd}
|
||||||
|
markerStart={edge.markerStart}
|
||||||
source={edge.source}
|
source={edge.source}
|
||||||
target={edge.target}
|
target={edge.target}
|
||||||
sourceHandleId={sourceHandleId}
|
sourceHandleId={sourceHandleId}
|
||||||
@@ -167,7 +167,6 @@ const Edge = ({
|
|||||||
sourcePosition={sourcePosition}
|
sourcePosition={sourcePosition}
|
||||||
targetPosition={targetPosition}
|
targetPosition={targetPosition}
|
||||||
elementsSelectable={elementsSelectable}
|
elementsSelectable={elementsSelectable}
|
||||||
markerEndId={props.markerEndId}
|
|
||||||
isHidden={edge.isHidden}
|
isHidden={edge.isHidden}
|
||||||
onConnectEdge={onConnectEdge}
|
onConnectEdge={onConnectEdge}
|
||||||
handleEdgeUpdate={typeof props.onEdgeUpdate !== 'undefined'}
|
handleEdgeUpdate={typeof props.onEdgeUpdate !== 'undefined'}
|
||||||
@@ -203,7 +202,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
connectionLineType,
|
connectionLineType,
|
||||||
arrowHeadColor,
|
defaultMarkerColor,
|
||||||
connectionLineStyle,
|
connectionLineStyle,
|
||||||
connectionLineComponent,
|
connectionLineComponent,
|
||||||
onlyRenderVisibleElements,
|
onlyRenderVisibleElements,
|
||||||
@@ -213,7 +212,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<svg width={width} height={height} className="react-flow__edges">
|
<svg width={width} height={height} className="react-flow__edges">
|
||||||
<MarkerDefinitions color={arrowHeadColor} />
|
<MarkerDefinitions defaultColor={defaultMarkerColor} />
|
||||||
<g transform={transformStyle}>
|
<g transform={transformStyle}>
|
||||||
{edges.map((edge: Edge) => (
|
{edges.map((edge: Edge) => (
|
||||||
<Edge
|
<Edge
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ interface FlowRendererProps
|
|||||||
| 'arrowHeadColor'
|
| 'arrowHeadColor'
|
||||||
| 'onlyRenderVisibleElements'
|
| 'onlyRenderVisibleElements'
|
||||||
| 'selectNodesOnDrag'
|
| 'selectNodesOnDrag'
|
||||||
|
| 'defaultMarkerColor'
|
||||||
> {
|
> {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export interface GraphViewProps extends Omit<ReactFlowProps, 'onSelectionChange'
|
|||||||
onlyRenderVisibleElements: boolean;
|
onlyRenderVisibleElements: boolean;
|
||||||
defaultZoom: number;
|
defaultZoom: number;
|
||||||
defaultPosition: [number, number];
|
defaultPosition: [number, number];
|
||||||
arrowHeadColor: string;
|
defaultMarkerColor: string;
|
||||||
selectNodesOnDrag: boolean;
|
selectNodesOnDrag: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,8 +75,7 @@ const GraphView = ({
|
|||||||
translateExtent,
|
translateExtent,
|
||||||
preventScrolling,
|
preventScrolling,
|
||||||
nodeExtent,
|
nodeExtent,
|
||||||
arrowHeadColor,
|
defaultMarkerColor,
|
||||||
markerEndId,
|
|
||||||
zoomOnScroll,
|
zoomOnScroll,
|
||||||
zoomOnPinch,
|
zoomOnPinch,
|
||||||
panOnScroll,
|
panOnScroll,
|
||||||
@@ -271,8 +270,7 @@ const GraphView = ({
|
|||||||
connectionLineStyle={connectionLineStyle}
|
connectionLineStyle={connectionLineStyle}
|
||||||
connectionLineComponent={connectionLineComponent}
|
connectionLineComponent={connectionLineComponent}
|
||||||
connectionMode={connectionMode}
|
connectionMode={connectionMode}
|
||||||
arrowHeadColor={arrowHeadColor}
|
defaultMarkerColor={defaultMarkerColor}
|
||||||
markerEndId={markerEndId}
|
|
||||||
onEdgeUpdate={onEdgeUpdate}
|
onEdgeUpdate={onEdgeUpdate}
|
||||||
onlyRenderVisibleElements={onlyRenderVisibleElements}
|
onlyRenderVisibleElements={onlyRenderVisibleElements}
|
||||||
onEdgeContextMenu={onEdgeContextMenu}
|
onEdgeContextMenu={onEdgeContextMenu}
|
||||||
|
|||||||
@@ -109,8 +109,7 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
|
|||||||
translateExtent?: TranslateExtent;
|
translateExtent?: TranslateExtent;
|
||||||
preventScrolling?: boolean;
|
preventScrolling?: boolean;
|
||||||
nodeExtent?: NodeExtent;
|
nodeExtent?: NodeExtent;
|
||||||
arrowHeadColor?: string;
|
defaultMarkerColor?: string;
|
||||||
markerEndId?: string;
|
|
||||||
zoomOnScroll?: boolean;
|
zoomOnScroll?: boolean;
|
||||||
zoomOnPinch?: boolean;
|
zoomOnPinch?: boolean;
|
||||||
panOnScroll?: boolean;
|
panOnScroll?: boolean;
|
||||||
@@ -184,8 +183,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
|||||||
translateExtent,
|
translateExtent,
|
||||||
preventScrolling = true,
|
preventScrolling = true,
|
||||||
nodeExtent,
|
nodeExtent,
|
||||||
arrowHeadColor = '#b1b1b7',
|
defaultMarkerColor = '#b1b1b7',
|
||||||
markerEndId,
|
|
||||||
zoomOnScroll = true,
|
zoomOnScroll = true,
|
||||||
zoomOnPinch = true,
|
zoomOnPinch = true,
|
||||||
panOnScroll = false,
|
panOnScroll = false,
|
||||||
@@ -262,8 +260,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
|||||||
translateExtent={translateExtent}
|
translateExtent={translateExtent}
|
||||||
preventScrolling={preventScrolling}
|
preventScrolling={preventScrolling}
|
||||||
nodeExtent={nodeExtent}
|
nodeExtent={nodeExtent}
|
||||||
arrowHeadColor={arrowHeadColor}
|
defaultMarkerColor={defaultMarkerColor}
|
||||||
markerEndId={markerEndId}
|
|
||||||
zoomOnScroll={zoomOnScroll}
|
zoomOnScroll={zoomOnScroll}
|
||||||
zoomOnPinch={zoomOnPinch}
|
zoomOnPinch={zoomOnPinch}
|
||||||
zoomOnDoubleClick={zoomOnDoubleClick}
|
zoomOnDoubleClick={zoomOnDoubleClick}
|
||||||
|
|||||||
+13
-5
@@ -57,6 +57,13 @@ export enum ArrowHeadType {
|
|||||||
ArrowClosed = 'arrowclosed',
|
ArrowClosed = 'arrowclosed',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface EdgeMarker {
|
||||||
|
type: ArrowHeadType;
|
||||||
|
color?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type EdgeMarkerType = string | EdgeMarker;
|
||||||
|
|
||||||
export interface Edge<T = any> {
|
export interface Edge<T = any> {
|
||||||
id: ElementId;
|
id: ElementId;
|
||||||
type?: string;
|
type?: string;
|
||||||
@@ -72,10 +79,11 @@ export interface Edge<T = any> {
|
|||||||
labelBgBorderRadius?: number;
|
labelBgBorderRadius?: number;
|
||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
animated?: boolean;
|
animated?: boolean;
|
||||||
arrowHeadType?: ArrowHeadType;
|
|
||||||
isHidden?: boolean;
|
isHidden?: boolean;
|
||||||
data?: T;
|
data?: T;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
markerStart?: EdgeMarkerType;
|
||||||
|
markerEnd?: EdgeMarkerType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum BackgroundVariant {
|
export enum BackgroundVariant {
|
||||||
@@ -111,7 +119,6 @@ export interface WrapEdgeProps<T = any> {
|
|||||||
labelBgPadding?: [number, number];
|
labelBgPadding?: [number, number];
|
||||||
labelBgBorderRadius?: number;
|
labelBgBorderRadius?: number;
|
||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
arrowHeadType?: ArrowHeadType;
|
|
||||||
source: ElementId;
|
source: ElementId;
|
||||||
target: ElementId;
|
target: ElementId;
|
||||||
sourceHandleId: ElementId | null;
|
sourceHandleId: ElementId | null;
|
||||||
@@ -123,7 +130,6 @@ export interface WrapEdgeProps<T = any> {
|
|||||||
sourcePosition: Position;
|
sourcePosition: Position;
|
||||||
targetPosition: Position;
|
targetPosition: Position;
|
||||||
elementsSelectable?: boolean;
|
elementsSelectable?: boolean;
|
||||||
markerEndId?: string;
|
|
||||||
isHidden?: boolean;
|
isHidden?: boolean;
|
||||||
handleEdgeUpdate: boolean;
|
handleEdgeUpdate: boolean;
|
||||||
onConnectEdge: OnConnectFunc;
|
onConnectEdge: OnConnectFunc;
|
||||||
@@ -134,6 +140,8 @@ export interface WrapEdgeProps<T = any> {
|
|||||||
edgeUpdaterRadius?: number;
|
edgeUpdaterRadius?: number;
|
||||||
onEdgeUpdateStart?: (event: React.MouseEvent, edge: Edge) => void;
|
onEdgeUpdateStart?: (event: React.MouseEvent, edge: Edge) => void;
|
||||||
onEdgeUpdateEnd?: (event: MouseEvent, edge: Edge) => void;
|
onEdgeUpdateEnd?: (event: MouseEvent, edge: Edge) => void;
|
||||||
|
markerStart?: EdgeMarkerType;
|
||||||
|
markerEnd?: EdgeMarkerType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EdgeProps<T = any> {
|
export interface EdgeProps<T = any> {
|
||||||
@@ -155,11 +163,11 @@ export interface EdgeProps<T = any> {
|
|||||||
labelBgPadding?: [number, number];
|
labelBgPadding?: [number, number];
|
||||||
labelBgBorderRadius?: number;
|
labelBgBorderRadius?: number;
|
||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
arrowHeadType?: ArrowHeadType;
|
|
||||||
markerEndId?: string;
|
|
||||||
data?: T;
|
data?: T;
|
||||||
sourceHandleId?: ElementId | null;
|
sourceHandleId?: ElementId | null;
|
||||||
targetHandleId?: ElementId | null;
|
targetHandleId?: ElementId | null;
|
||||||
|
markerStart?: string;
|
||||||
|
markerEnd?: string;
|
||||||
}
|
}
|
||||||
export interface EdgeSmoothStepProps<T = any> extends EdgeProps<T> {
|
export interface EdgeSmoothStepProps<T = any> extends EdgeProps<T> {
|
||||||
borderRadius?: number;
|
borderRadius?: number;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
FlowExportObject,
|
FlowExportObject,
|
||||||
ReactFlowState,
|
ReactFlowState,
|
||||||
NodeExtent,
|
NodeExtent,
|
||||||
|
EdgeMarkerType,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
|
|
||||||
export const isEdge = (element: Node | Connection | Edge): element is Edge =>
|
export const isEdge = (element: Node | Connection | Edge): element is Edge =>
|
||||||
@@ -57,6 +58,21 @@ export const removeElements = (elementsToRemove: Elements, elements: Elements):
|
|||||||
const getEdgeId = ({ source, sourceHandle, target, targetHandle }: Connection): ElementId =>
|
const getEdgeId = ({ source, sourceHandle, target, targetHandle }: Connection): ElementId =>
|
||||||
`reactflow__edge-${source}${sourceHandle}-${target}${targetHandle}`;
|
`reactflow__edge-${source}${sourceHandle}-${target}${targetHandle}`;
|
||||||
|
|
||||||
|
export const getMarkerId = (marker: EdgeMarkerType | undefined): string => {
|
||||||
|
if (typeof marker === 'undefined') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof marker === 'string') {
|
||||||
|
return marker;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(marker)
|
||||||
|
.sort()
|
||||||
|
.map((key: string) => `${key}=${(marker as any)[key]}`)
|
||||||
|
.join('&');
|
||||||
|
};
|
||||||
|
|
||||||
const connectionExists = (edge: Edge, elements: Elements) => {
|
const connectionExists = (edge: Edge, elements: Elements) => {
|
||||||
return elements.some(
|
return elements.some(
|
||||||
(el) =>
|
(el) =>
|
||||||
|
|||||||
Reference in New Issue
Block a user