chore(examples): add layouting with new api

This commit is contained in:
moklick
2021-11-02 12:52:24 +01:00
parent 6e3ff4e849
commit 65991de037
8 changed files with 120 additions and 94 deletions
+4 -1
View File
@@ -19,7 +19,10 @@ import ReactFlow, {
import ColorSelectorNode from './ColorSelectorNode';
const onLoad = (reactFlowInstance: OnLoadParams) => console.log('flow loaded:', reactFlowInstance);
const onLoad = (reactFlowInstance: OnLoadParams) => {
console.log('flow loaded:', reactFlowInstance);
reactFlowInstance.fitView();
};
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
+99
View File
@@ -0,0 +1,99 @@
import { useState, useCallback } from 'react';
import ReactFlow, {
ReactFlowProvider,
addEdge,
applyNodeChanges,
applyEdgeChanges,
Controls,
NodeChange,
EdgeChange,
Node,
Connection,
Edge,
NodeExtent,
Position,
} from 'react-flow-renderer';
import dagre from 'dagre';
import initialNodesAndEdges from './initial-elements';
import './layouting.css';
const dagreGraph = new dagre.graphlib.Graph();
dagreGraph.setDefaultEdgeLabel(() => ({}));
const nodeExtent: NodeExtent = [
[0, 0],
[1000, 1000],
];
const LayoutFlow = () => {
const [nodes, setNodes] = useState<Node[]>(initialNodesAndEdges.nodes);
const [edges, setEdges] = useState<Edge[]>(initialNodesAndEdges.edges);
const onConnect = useCallback((params: Edge | Connection) => {
setEdges((eds) => {
return addEdge(params, eds);
});
}, []);
const onLayout = (direction: string) => {
const isHorizontal = direction === 'LR';
dagreGraph.setGraph({ rankdir: direction });
nodes.forEach((node) => {
dagreGraph.setNode(node.id, { width: 150, height: 50 });
});
edges.forEach((edge) => {
dagreGraph.setEdge(edge.source, edge.target);
});
dagre.layout(dagreGraph);
const layoutedNodes = nodes.map((node) => {
const nodeWithPosition = dagreGraph.node(node.id);
node.targetPosition = isHorizontal ? Position.Left : Position.Top;
node.sourcePosition = isHorizontal ? Position.Right : Position.Bottom;
// we need to pass a slightly different position in order to notify react flow about the change
// @TODO how can we change the position handling so that we dont need this hack?
node.position = { x: nodeWithPosition.x + Math.random() / 1000, y: nodeWithPosition.y };
return node;
});
setNodes(layoutedNodes);
};
const onNodesChange = useCallback((changes: NodeChange[]) => setNodes((ns) => applyNodeChanges(changes, ns)), []);
const onEdgesChange = useCallback((changes: EdgeChange[]) => {
setEdges((es) => applyEdgeChanges(changes, es));
}, []);
return (
<div className="layoutflow">
<ReactFlowProvider>
<ReactFlow
nodes={nodes}
edges={edges}
onConnect={onConnect}
nodeExtent={nodeExtent}
onLoad={() => onLayout('TB')}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
>
<Controls />
</ReactFlow>
<div className="controls">
<button onClick={() => onLayout('TB')} style={{ marginRight: 10 }}>
vertical layout
</button>
<button onClick={() => onLayout('LR')}>horizontal layout</button>
</div>
</ReactFlowProvider>
</div>
);
};
export default LayoutFlow;
@@ -1,8 +1,8 @@
import { Elements, XYPosition } from 'react-flow-renderer';
import { Node, Edge, XYPosition } from 'react-flow-renderer';
const position: XYPosition = { x: 0, y: 0 };
const elements: Elements = [
const nodes: Node[] = [
{
id: '1',
type: 'input',
@@ -56,6 +56,9 @@ const elements: Elements = [
position,
},
{ id: '7', type: 'output', data: { label: 'output' }, position: { x: 400, y: 450 } },
];
const edges: Edge[] = [
{ id: 'e12', source: '1', target: '2', type: 'smoothstep' },
{ id: 'e13', source: '1', target: '3', type: 'smoothstep' },
{ id: 'e22a', source: '2', target: '2a', type: 'smoothstep' },
@@ -68,4 +71,6 @@ const elements: Elements = [
{ id: 'e57', source: '5', target: '7', type: 'smoothstep' },
];
export default elements;
const nodesAndEdges = { nodes, edges };
export default nodesAndEdges;
+6 -1
View File
@@ -1,4 +1,4 @@
import React, { ChangeEvent } from 'react';
import { ChangeEvent } from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, Switch, withRouter } from 'react-router-dom';
@@ -7,6 +7,7 @@ import UpdateNode from './UpdateNode';
import Stress from './Stress';
import CustomNode from './CustomNode';
import FloatingEdges from './FloatingEdges';
import Layouting from './Layouting';
import './index.css';
@@ -31,6 +32,10 @@ const routes = [
path: '/floating-edges',
component: FloatingEdges,
},
{
path: '/layouting',
component: Layouting,
},
];
const Header = withRouter(({ history, location }) => {
-86
View File
@@ -1,86 +0,0 @@
import React, { useState } from 'react';
import ReactFlow, {
ReactFlowProvider,
addEdge,
removeElements,
Controls,
isNode,
Elements,
Connection,
Edge,
NodeExtent,
Position,
} from 'react-flow-renderer';
import dagre from 'dagre';
import initialElements from './initial-elements';
import './layouting.css';
const dagreGraph = new dagre.graphlib.Graph();
dagreGraph.setDefaultEdgeLabel(() => ({}));
const nodeExtent: NodeExtent = [
[0, 0],
[1000, 1000],
];
const LayoutFlow = () => {
const [elements, setElements] = useState<Elements>(initialElements);
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
const onLayout = (direction: string) => {
const isHorizontal = direction === 'LR';
dagreGraph.setGraph({ rankdir: direction });
elements.forEach((el) => {
if (isNode(el)) {
dagreGraph.setNode(el.id, { width: 150, height: 50 });
} else {
dagreGraph.setEdge(el.source, el.target);
}
});
dagre.layout(dagreGraph);
const layoutedElements = elements.map((el) => {
if (isNode(el)) {
const nodeWithPosition = dagreGraph.node(el.id);
el.targetPosition = isHorizontal ? Position.Left : Position.Top;
el.sourcePosition = isHorizontal ? Position.Right : Position.Bottom;
// we need to pass a slightly different position in order to notify react flow about the change
// @TODO how can we change the position handling so that we dont need this hack?
el.position = { x: nodeWithPosition.x + Math.random() / 1000, y: nodeWithPosition.y };
}
return el;
});
setElements(layoutedElements);
};
return (
<div className="layoutflow">
<ReactFlowProvider>
<ReactFlow
elements={elements}
onConnect={onConnect}
onElementsRemove={onElementsRemove}
nodeExtent={nodeExtent}
onLoad={() => onLayout('TB')}
>
<Controls />
</ReactFlow>
<div className="controls">
<button onClick={() => onLayout('TB')} style={{ marginRight: 10 }}>
vertical layout
</button>
<button onClick={() => onLayout('LR')}>horizontal layout</button>
</div>
</ReactFlowProvider>
</div>
);
};
export default LayoutFlow;
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "react-flow-renderer",
"version": "10.0.0-next.6",
"version": "10.0.0-next.7",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "react-flow-renderer",
"version": "10.0.0-next.6",
"version": "10.0.0-next.7",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.15.4",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "react-flow-renderer",
"version": "10.0.0-next.6",
"version": "10.0.0-next.7",
"engines": {
"node": ">=12"
},