@@ -8,6 +8,8 @@ import ReactFlow, {
|
|||||||
Position,
|
Position,
|
||||||
useNodesState,
|
useNodesState,
|
||||||
useEdgesState,
|
useEdgesState,
|
||||||
|
MarkerType,
|
||||||
|
EdgeMarker,
|
||||||
} from 'react-flow-renderer';
|
} from 'react-flow-renderer';
|
||||||
import dagre from 'dagre';
|
import dagre from 'dagre';
|
||||||
|
|
||||||
@@ -27,9 +29,12 @@ const LayoutFlow = () => {
|
|||||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialItems.nodes);
|
const [nodes, setNodes, onNodesChange] = useNodesState(initialItems.nodes);
|
||||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialItems.edges);
|
const [edges, setEdges, onEdgesChange] = useEdgesState(initialItems.edges);
|
||||||
|
|
||||||
const onConnect = useCallback((connection: Connection) => {
|
const onConnect = useCallback(
|
||||||
setEdges((eds) => addEdge(connection, eds));
|
(connection: Connection) => {
|
||||||
}, []);
|
setEdges((eds) => addEdge(connection, eds));
|
||||||
|
},
|
||||||
|
[setEdges]
|
||||||
|
);
|
||||||
|
|
||||||
const onLayout = (direction: string) => {
|
const onLayout = (direction: string) => {
|
||||||
const isHorizontal = direction === 'LR';
|
const isHorizontal = direction === 'LR';
|
||||||
@@ -63,6 +68,17 @@ const LayoutFlow = () => {
|
|||||||
setNodes((nds) => nds.map((n) => ({ ...n, selected: false })));
|
setNodes((nds) => nds.map((n) => ({ ...n, selected: false })));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const changeMarker = () => {
|
||||||
|
setEdges((eds) =>
|
||||||
|
eds.map((e) => ({
|
||||||
|
...e,
|
||||||
|
markerEnd: {
|
||||||
|
type: (e.markerEnd as EdgeMarker)?.type === MarkerType.Arrow ? MarkerType.ArrowClosed : MarkerType.Arrow,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="layoutflow">
|
<div className="layoutflow">
|
||||||
<ReactFlowProvider>
|
<ReactFlowProvider>
|
||||||
@@ -85,6 +101,7 @@ const LayoutFlow = () => {
|
|||||||
horizontal layout
|
horizontal layout
|
||||||
</button>
|
</button>
|
||||||
<button onClick={() => unselect()}>unselect nodes</button>
|
<button onClick={() => unselect()}>unselect nodes</button>
|
||||||
|
<button onClick={() => changeMarker()}>change marker</button>
|
||||||
</div>
|
</div>
|
||||||
</ReactFlowProvider>
|
</ReactFlowProvider>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Node, Edge, XYPosition } from 'react-flow-renderer';
|
import { Node, Edge, XYPosition, MarkerType } from 'react-flow-renderer';
|
||||||
|
|
||||||
const position: XYPosition = { x: 0, y: 0 };
|
const position: XYPosition = { x: 0, y: 0 };
|
||||||
|
|
||||||
@@ -59,16 +59,16 @@ const nodes: Node[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const edges: Edge[] = [
|
const edges: Edge[] = [
|
||||||
{ id: 'e12', source: '1', target: '2', type: 'smoothstep' },
|
{ id: 'e12', source: '1', target: '2', type: 'smoothstep', markerEnd: { type: MarkerType.Arrow } },
|
||||||
{ id: 'e13', source: '1', target: '3', type: 'smoothstep' },
|
{ id: 'e13', source: '1', target: '3', type: 'smoothstep', markerEnd: { type: MarkerType.Arrow } },
|
||||||
{ id: 'e22a', source: '2', target: '2a', type: 'smoothstep' },
|
{ id: 'e22a', source: '2', target: '2a', type: 'smoothstep', markerEnd: { type: MarkerType.Arrow } },
|
||||||
{ id: 'e22b', source: '2', target: '2b', type: 'smoothstep' },
|
{ id: 'e22b', source: '2', target: '2b', type: 'smoothstep', markerEnd: { type: MarkerType.Arrow } },
|
||||||
{ id: 'e22c', source: '2', target: '2c', type: 'smoothstep' },
|
{ id: 'e22c', source: '2', target: '2c', type: 'smoothstep', markerEnd: { type: MarkerType.Arrow } },
|
||||||
{ id: 'e2c2d', source: '2c', target: '2d', type: 'smoothstep' },
|
{ id: 'e2c2d', source: '2c', target: '2d', type: 'smoothstep', markerEnd: { type: MarkerType.Arrow } },
|
||||||
|
|
||||||
{ id: 'e45', source: '4', target: '5', type: 'smoothstep' },
|
{ id: 'e45', source: '4', target: '5', type: 'smoothstep', markerEnd: { type: MarkerType.Arrow } },
|
||||||
{ id: 'e56', source: '5', target: '6', type: 'smoothstep' },
|
{ id: 'e56', source: '5', target: '6', type: 'smoothstep', markerEnd: { type: MarkerType.Arrow } },
|
||||||
{ id: 'e57', source: '5', target: '7', type: 'smoothstep' },
|
{ id: 'e57', source: '5', target: '7', type: 'smoothstep', markerEnd: { type: MarkerType.Arrow } },
|
||||||
];
|
];
|
||||||
|
|
||||||
const nodesAndEdges = { nodes, edges };
|
const nodesAndEdges = { nodes, edges };
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import ReactFlow, {
|
|||||||
ReactFlowProvider,
|
ReactFlowProvider,
|
||||||
useNodesState,
|
useNodesState,
|
||||||
useEdgesState,
|
useEdgesState,
|
||||||
|
MarkerType,
|
||||||
} from 'react-flow-renderer';
|
} from 'react-flow-renderer';
|
||||||
|
|
||||||
import './multiflows.css';
|
import './multiflows.css';
|
||||||
@@ -21,12 +22,12 @@ const initialNodes: Node[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const initialEdges: Edge[] = [
|
const initialEdges: Edge[] = [
|
||||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
{ id: 'e1-2', source: '1', target: '2', animated: true, markerEnd: { type: MarkerType.Arrow } },
|
||||||
{ id: 'e1-3', source: '1', target: '3' },
|
{ id: 'e1-3', source: '1', target: '3' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const Flow: FC = () => {
|
const Flow: FC<{ id: string }> = ({ id }) => {
|
||||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
const [nodes, , onNodesChange] = useNodesState(initialNodes);
|
||||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||||
|
|
||||||
const onConnect = (params: Edge | Connection) => setEdges((eds) => addEdge(params, eds));
|
const onConnect = (params: Edge | Connection) => setEdges((eds) => addEdge(params, eds));
|
||||||
@@ -39,6 +40,7 @@ const Flow: FC = () => {
|
|||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
|
id={id}
|
||||||
>
|
>
|
||||||
<Background />
|
<Background />
|
||||||
</ReactFlow>
|
</ReactFlow>
|
||||||
@@ -48,8 +50,8 @@ const Flow: FC = () => {
|
|||||||
|
|
||||||
const MultiFlows: FC = () => (
|
const MultiFlows: FC = () => (
|
||||||
<div className="react-flow__example-multiflows">
|
<div className="react-flow__example-multiflows">
|
||||||
<Flow />
|
<Flow id="flow-a" />
|
||||||
<Flow />
|
<Flow id="flow-b" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,13 @@ const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
|||||||
const onEdgeClick = (_: MouseEvent, edge: Edge) => console.log('click', edge);
|
const onEdgeClick = (_: MouseEvent, edge: Edge) => console.log('click', edge);
|
||||||
|
|
||||||
const initialNodes: Node[] = [
|
const initialNodes: Node[] = [
|
||||||
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 }, className: 'light' },
|
{
|
||||||
|
id: '1',
|
||||||
|
type: 'input',
|
||||||
|
data: { label: 'Node 1' },
|
||||||
|
position: { x: 250, y: 5 },
|
||||||
|
className: 'light',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: '4',
|
id: '4',
|
||||||
data: { label: 'Node 4' },
|
data: { label: 'Node 4' },
|
||||||
@@ -34,21 +40,23 @@ const initialNodes: Node[] = [
|
|||||||
position: { x: 15, y: 15 },
|
position: { x: 15, y: 15 },
|
||||||
className: 'light',
|
className: 'light',
|
||||||
parentNode: '4',
|
parentNode: '4',
|
||||||
extent: 'parent',
|
extent: [
|
||||||
|
[0, 0],
|
||||||
|
[100, 100],
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '4b',
|
id: '4b',
|
||||||
data: { label: 'Node 4b' },
|
data: { label: 'Node 4b' },
|
||||||
position: { x: 150, y: 50 },
|
position: { x: 100, y: 60 },
|
||||||
className: 'light',
|
className: 'light',
|
||||||
style: { backgroundColor: 'rgba(50, 50, 255, 0.5)', height: 200, width: 300 },
|
style: { backgroundColor: 'rgba(50, 50, 255, 0.5)', height: 200, width: 300 },
|
||||||
parentNode: '4',
|
parentNode: '4',
|
||||||
expandParent: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '4b1',
|
id: '4b1',
|
||||||
data: { label: 'Node 4b1' },
|
data: { label: 'Node 4b1' },
|
||||||
position: { x: 20, y: 20 },
|
position: { x: 40, y: 20 },
|
||||||
className: 'light',
|
className: 'light',
|
||||||
parentNode: '4b',
|
parentNode: '4b',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
|||||||
onEdgeUpdateEnd,
|
onEdgeUpdateEnd,
|
||||||
markerEnd,
|
markerEnd,
|
||||||
markerStart,
|
markerStart,
|
||||||
|
rfId,
|
||||||
}: WrapEdgeProps): JSX.Element | null => {
|
}: WrapEdgeProps): JSX.Element | null => {
|
||||||
const [updating, setUpdating] = useState<boolean>(false);
|
const [updating, setUpdating] = useState<boolean>(false);
|
||||||
const { addSelectedEdges, connectionMode } = useStore(selector, shallow);
|
const { addSelectedEdges, connectionMode } = useStore(selector, shallow);
|
||||||
@@ -120,8 +121,8 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
|||||||
|
|
||||||
const onEdgeUpdaterMouseEnter = () => setUpdating(true);
|
const onEdgeUpdaterMouseEnter = () => setUpdating(true);
|
||||||
const onEdgeUpdaterMouseOut = () => setUpdating(false);
|
const onEdgeUpdaterMouseOut = () => setUpdating(false);
|
||||||
const markerStartUrl = useMemo(() => `url(#${getMarkerId(markerStart)})`, [markerStart]);
|
const markerStartUrl = useMemo(() => `url(#${getMarkerId(markerStart, rfId)})`, [markerStart, rfId]);
|
||||||
const markerEndUrl = useMemo(() => `url(#${getMarkerId(markerEnd)})`, [markerEnd]);
|
const markerEndUrl = useMemo(() => `url(#${getMarkerId(markerEnd, rfId)})`, [markerEnd, rfId]);
|
||||||
|
|
||||||
if (hidden) {
|
if (hidden) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
|
|||||||
isParent,
|
isParent,
|
||||||
noPanClassName,
|
noPanClassName,
|
||||||
noDragClassName,
|
noDragClassName,
|
||||||
|
initialized,
|
||||||
}: WrapNodeProps) => {
|
}: WrapNodeProps) => {
|
||||||
const store = useStoreApi();
|
const store = useStoreApi();
|
||||||
const updateNodeDimensions = useStore(selector);
|
const updateNodeDimensions = useStore(selector);
|
||||||
@@ -134,6 +135,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
|
|||||||
zIndex,
|
zIndex,
|
||||||
transform: `translate(${xPos}px,${yPos}px)`,
|
transform: `translate(${xPos}px,${yPos}px)`,
|
||||||
pointerEvents: hasPointerEvents ? 'all' : 'none',
|
pointerEvents: hasPointerEvents ? 'all' : 'none',
|
||||||
|
visibility: initialized ? 'visible' : 'hidden',
|
||||||
...style,
|
...style,
|
||||||
}}
|
}}
|
||||||
onMouseEnter={onMouseEnterHandler}
|
onMouseEnter={onMouseEnterHandler}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { memo, useCallback } from 'react';
|
||||||
|
|
||||||
import { useStore } from '../../store';
|
import { useStore } from '../../store';
|
||||||
import { EdgeMarker, ReactFlowState } from '../../types';
|
import { EdgeMarker, ReactFlowState } from '../../types';
|
||||||
@@ -9,6 +9,7 @@ interface MarkerProps extends EdgeMarker {
|
|||||||
}
|
}
|
||||||
interface MarkerDefinitionsProps {
|
interface MarkerDefinitionsProps {
|
||||||
defaultColor: string;
|
defaultColor: string;
|
||||||
|
rfId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Marker = ({
|
const Marker = ({
|
||||||
@@ -40,26 +41,36 @@ const Marker = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const edgesSelector = (s: ReactFlowState) => s.edges;
|
const markerSelector =
|
||||||
|
({ defaultColor, rfId }: { defaultColor: string; rfId?: string }) =>
|
||||||
const MarkerDefinitions = ({ defaultColor }: MarkerDefinitionsProps) => {
|
(s: ReactFlowState) => {
|
||||||
const edges = useStore(edgesSelector);
|
|
||||||
const markers = useMemo(() => {
|
|
||||||
const ids: string[] = [];
|
const ids: string[] = [];
|
||||||
|
|
||||||
return edges.reduce<MarkerProps[]>((markers, edge) => {
|
return s.edges
|
||||||
[edge.markerStart, edge.markerEnd].forEach((marker) => {
|
.reduce<MarkerProps[]>((markers, edge) => {
|
||||||
if (marker && typeof marker === 'object') {
|
[edge.markerStart, edge.markerEnd].forEach((marker) => {
|
||||||
const markerId = getMarkerId(marker);
|
if (marker && typeof marker === 'object') {
|
||||||
if (!ids.includes(markerId)) {
|
const markerId = getMarkerId(marker, rfId);
|
||||||
markers.push({ id: markerId, color: marker.color || defaultColor, ...marker });
|
if (!ids.includes(markerId)) {
|
||||||
ids.push(markerId);
|
markers.push({ id: markerId, color: marker.color || defaultColor, ...marker });
|
||||||
|
ids.push(markerId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
return markers;
|
||||||
return markers.sort((a, b) => a.id.localeCompare(b.id));
|
}, [])
|
||||||
}, []);
|
.sort((a, b) => a.id.localeCompare(b.id));
|
||||||
}, [edges, defaultColor]);
|
};
|
||||||
|
|
||||||
|
// when you have multiple flows on a page and you hide the first one, the other ones have no markers anymore
|
||||||
|
// when they do have markers with the same ids. To prevent this the user can pass a unique id to the react flow wrapper
|
||||||
|
// that we can then use for creating our unique marker ids
|
||||||
|
const MarkerDefinitions = ({ defaultColor, rfId }: MarkerDefinitionsProps) => {
|
||||||
|
const markers = useStore(
|
||||||
|
useCallback(markerSelector({ defaultColor, rfId }), [defaultColor, rfId]),
|
||||||
|
// the id includes all marker options, so we just need to look at that part of the marker
|
||||||
|
(a, b) => !(a.length !== b.length || a.some((m, i) => m.id !== b[i].id))
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<defs>
|
<defs>
|
||||||
@@ -82,4 +93,4 @@ const MarkerDefinitions = ({ defaultColor }: MarkerDefinitionsProps) => {
|
|||||||
|
|
||||||
MarkerDefinitions.displayName = 'MarkerDefinitions';
|
MarkerDefinitions.displayName = 'MarkerDefinitions';
|
||||||
|
|
||||||
export default MarkerDefinitions;
|
export default memo(MarkerDefinitions);
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ interface EdgeRendererProps {
|
|||||||
edgeUpdaterRadius?: number;
|
edgeUpdaterRadius?: number;
|
||||||
noPanClassName?: string;
|
noPanClassName?: string;
|
||||||
elevateEdgesOnSelect: boolean;
|
elevateEdgesOnSelect: boolean;
|
||||||
|
rfId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selector = (s: ReactFlowState) => ({
|
const selector = (s: ReactFlowState) => ({
|
||||||
@@ -93,7 +94,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
|
|||||||
height={height}
|
height={height}
|
||||||
className="react-flow__edges react-flow__container"
|
className="react-flow__edges react-flow__container"
|
||||||
>
|
>
|
||||||
{isMaxLevel && <MarkerDefinitions defaultColor={defaultMarkerColor} />}
|
{isMaxLevel && <MarkerDefinitions defaultColor={defaultMarkerColor} rfId={props.rfId} />}
|
||||||
<g>
|
<g>
|
||||||
{edges.map((edge: Edge) => {
|
{edges.map((edge: Edge) => {
|
||||||
const [sourceNodeRect, sourceHandleBounds, sourceIsValid] = getNodeData(nodeInternals, edge.source);
|
const [sourceNodeRect, sourceHandleBounds, sourceIsValid] = getNodeData(nodeInternals, edge.source);
|
||||||
@@ -184,6 +185,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
|
|||||||
onEdgeDoubleClick={props.onEdgeDoubleClick}
|
onEdgeDoubleClick={props.onEdgeDoubleClick}
|
||||||
onEdgeUpdateStart={props.onEdgeUpdateStart}
|
onEdgeUpdateStart={props.onEdgeUpdateStart}
|
||||||
onEdgeUpdateEnd={props.onEdgeUpdateEnd}
|
onEdgeUpdateEnd={props.onEdgeUpdateEnd}
|
||||||
|
rfId={props.rfId}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ const GraphView = ({
|
|||||||
noWheelClassName,
|
noWheelClassName,
|
||||||
noPanClassName,
|
noPanClassName,
|
||||||
elevateEdgesOnSelect,
|
elevateEdgesOnSelect,
|
||||||
|
id,
|
||||||
}: GraphViewProps) => {
|
}: GraphViewProps) => {
|
||||||
useOnInitHandler(onInit);
|
useOnInitHandler(onInit);
|
||||||
|
|
||||||
@@ -139,6 +140,7 @@ const GraphView = ({
|
|||||||
defaultMarkerColor={defaultMarkerColor}
|
defaultMarkerColor={defaultMarkerColor}
|
||||||
noPanClassName={noPanClassName}
|
noPanClassName={noPanClassName}
|
||||||
elevateEdgesOnSelect={!!elevateEdgesOnSelect}
|
elevateEdgesOnSelect={!!elevateEdgesOnSelect}
|
||||||
|
rfId={id}
|
||||||
/>
|
/>
|
||||||
<NodeRenderer
|
<NodeRenderer
|
||||||
nodeTypes={nodeTypes}
|
nodeTypes={nodeTypes}
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ const NodeRenderer = (props: NodeRendererProps) => {
|
|||||||
isParent={!!node[internalsSymbol]?.isParent}
|
isParent={!!node[internalsSymbol]?.isParent}
|
||||||
noDragClassName={props.noDragClassName}
|
noDragClassName={props.noDragClassName}
|
||||||
noPanClassName={props.noPanClassName}
|
noPanClassName={props.noPanClassName}
|
||||||
|
initialized={!!node.width && !!node.height}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
|||||||
noWheelClassName={noWheelClassName}
|
noWheelClassName={noWheelClassName}
|
||||||
noPanClassName={noPanClassName}
|
noPanClassName={noPanClassName}
|
||||||
elevateEdgesOnSelect={elevateEdgesOnSelect}
|
elevateEdgesOnSelect={elevateEdgesOnSelect}
|
||||||
|
id={rest?.id}
|
||||||
/>
|
/>
|
||||||
<StoreUpdater
|
<StoreUpdater
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
|
|||||||
@@ -84,6 +84,14 @@ export function updatePosition(
|
|||||||
}
|
}
|
||||||
currentExtent = nodeExtent;
|
currentExtent = nodeExtent;
|
||||||
}
|
}
|
||||||
|
} else if (dragItem.extent && dragItem.parentNode) {
|
||||||
|
const parent = nodeInternals.get(dragItem.parentNode);
|
||||||
|
const parentX = parent?.positionAbsolute?.x ?? 0;
|
||||||
|
const parentY = parent?.positionAbsolute?.y ?? 0;
|
||||||
|
currentExtent = [
|
||||||
|
[dragItem.extent[0][0] + parentX, dragItem.extent[0][1] + parentY],
|
||||||
|
[dragItem.extent[1][0] + parentX, dragItem.extent[1][1] + parentY],
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
dragItem.position = currentExtent ? clampPosition(nextPosition, currentExtent as CoordinateExtent) : nextPosition;
|
dragItem.position = currentExtent ? clampPosition(nextPosition, currentExtent as CoordinateExtent) : nextPosition;
|
||||||
|
|||||||
@@ -69,8 +69,8 @@ function useVisibleEdges(onlyRenderVisible: boolean, nodeInternals: NodeInternal
|
|||||||
targetNode?.width &&
|
targetNode?.width &&
|
||||||
targetNode?.height &&
|
targetNode?.height &&
|
||||||
isEdgeVisible({
|
isEdgeVisible({
|
||||||
sourcePos: sourceNode.position || { x: 0, y: 0 },
|
sourcePos: sourceNode.positionAbsolute || { x: 0, y: 0 },
|
||||||
targetPos: targetNode.position || { x: 0, y: 0 },
|
targetPos: targetNode.positionAbsolute || { x: 0, y: 0 },
|
||||||
sourceWidth: sourceNode.width,
|
sourceWidth: sourceNode.width,
|
||||||
sourceHeight: sourceNode.height,
|
sourceHeight: sourceNode.height,
|
||||||
targetWidth: targetNode.width,
|
targetWidth: targetNode.width,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export {
|
|||||||
export { default as SmoothStepEdge, getSmoothStepPath } from './components/Edges/SmoothStepEdge';
|
export { default as SmoothStepEdge, getSmoothStepPath } from './components/Edges/SmoothStepEdge';
|
||||||
export * from './additional-components';
|
export * from './additional-components';
|
||||||
|
|
||||||
|
export { internalsSymbol } from './utils';
|
||||||
export {
|
export {
|
||||||
isNode,
|
isNode,
|
||||||
isEdge,
|
isEdge,
|
||||||
|
|||||||
+1
-1
@@ -105,7 +105,7 @@ export function fitView(get: GetState<ReactFlowState>, options: InternalFitViewO
|
|||||||
if ((options.initial && !fitViewOnInitDone && fitViewOnInit) || !options.initial) {
|
if ((options.initial && !fitViewOnInitDone && fitViewOnInit) || !options.initial) {
|
||||||
if (d3Zoom && d3Selection) {
|
if (d3Zoom && d3Selection) {
|
||||||
const nodes = Array.from(nodeInternals.values()).filter((n) =>
|
const nodes = Array.from(nodeInternals.values()).filter((n) =>
|
||||||
options.includeHiddenNodes ? !n.parentNode && n.width && n.height : !n.parentNode && !n.hidden
|
options.includeHiddenNodes ? n.width && n.height : !n.hidden
|
||||||
);
|
);
|
||||||
|
|
||||||
const nodesInitialized = nodes.every((n) => n.width && n.height);
|
const nodesInitialized = nodes.every((n) => n.width && n.height);
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ export interface WrapEdgeProps<T = any> {
|
|||||||
onEdgeUpdateEnd?: (event: MouseEvent, edge: Edge, handleType: HandleType) => void;
|
onEdgeUpdateEnd?: (event: MouseEvent, edge: Edge, handleType: HandleType) => void;
|
||||||
markerStart?: EdgeMarkerType;
|
markerStart?: EdgeMarkerType;
|
||||||
markerEnd?: EdgeMarkerType;
|
markerEnd?: EdgeMarkerType;
|
||||||
|
rfId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EdgeSmoothStepProps<T = any> extends EdgeProps<T> {
|
export interface EdgeSmoothStepProps<T = any> extends EdgeProps<T> {
|
||||||
|
|||||||
+1
-2
@@ -64,8 +64,7 @@ export interface WrapNodeProps<T = any> {
|
|||||||
isConnectable: boolean;
|
isConnectable: boolean;
|
||||||
xPos: number;
|
xPos: number;
|
||||||
yPos: number;
|
yPos: number;
|
||||||
width?: number | null;
|
initialized: boolean;
|
||||||
height?: number | null;
|
|
||||||
isSelectable: boolean;
|
isSelectable: boolean;
|
||||||
isDraggable: boolean;
|
isDraggable: boolean;
|
||||||
selectNodesOnDrag: boolean;
|
selectNodesOnDrag: boolean;
|
||||||
|
|||||||
+5
-3
@@ -30,7 +30,7 @@ export const getIncomers = <T = any, U extends T = T>(node: Node<U>, nodes: Node
|
|||||||
const getEdgeId = ({ source, sourceHandle, target, targetHandle }: Connection): string =>
|
const getEdgeId = ({ source, sourceHandle, target, targetHandle }: Connection): string =>
|
||||||
`reactflow__edge-${source}${sourceHandle || ''}-${target}${targetHandle || ''}`;
|
`reactflow__edge-${source}${sourceHandle || ''}-${target}${targetHandle || ''}`;
|
||||||
|
|
||||||
export const getMarkerId = (marker: EdgeMarkerType | undefined): string => {
|
export const getMarkerId = (marker: EdgeMarkerType | undefined, rfId?: string): string => {
|
||||||
if (typeof marker === 'undefined') {
|
if (typeof marker === 'undefined') {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -39,10 +39,12 @@ export const getMarkerId = (marker: EdgeMarkerType | undefined): string => {
|
|||||||
return marker;
|
return marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.keys(marker)
|
const idPrefix = rfId ? `${rfId}__` : '';
|
||||||
|
|
||||||
|
return `${idPrefix}${Object.keys(marker)
|
||||||
.sort()
|
.sort()
|
||||||
.map((key: string) => `${key}=${(marker as any)[key]}`)
|
.map((key: string) => `${key}=${(marker as any)[key]}`)
|
||||||
.join('&');
|
.join('&')}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const connectionExists = (edge: Edge, edges: Edge[]) => {
|
const connectionExists = (edge: Edge, edges: Edge[]) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user