diff --git a/example/src_oldapi/CustomConnectionLine/ConnectionLine.tsx b/example/src/CustomConnectionLine/ConnectionLine.tsx
similarity index 100%
rename from example/src_oldapi/CustomConnectionLine/ConnectionLine.tsx
rename to example/src/CustomConnectionLine/ConnectionLine.tsx
diff --git a/example/src/CustomConnectionLine/index.tsx b/example/src/CustomConnectionLine/index.tsx
new file mode 100644
index 00000000..cca1e821
--- /dev/null
+++ b/example/src/CustomConnectionLine/index.tsx
@@ -0,0 +1,36 @@
+import ReactFlow, {
+ Node,
+ addEdge,
+ Background,
+ BackgroundVariant,
+ Connection,
+ Edge,
+ useNodesState,
+ useEdgesState,
+} from 'react-flow-renderer';
+
+import ConnectionLine from './ConnectionLine';
+
+const initialNodes: Node[] = [{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } }];
+const initialEdges: Edge[] = [];
+
+const ConnectionLineFlow = () => {
+ const [nodes, , onNodesChange] = useNodesState(initialNodes);
+ const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
+ const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
+
+ return (
+
+
+
+ );
+};
+
+export default ConnectionLineFlow;
diff --git a/example/src/Overview/index.tsx b/example/src/Overview/index.tsx
index 4cb1e045..9219fe38 100644
--- a/example/src/Overview/index.tsx
+++ b/example/src/Overview/index.tsx
@@ -33,8 +33,7 @@ const onNodeClick = (_: MouseEvent, node: Node) => console.log('node click:', no
const onSelectionChange = ({ nodes, edges }: OnSelectionChangeParams) => console.log('selection change', nodes, edges);
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => {
- console.log('flow loaded:', reactFlowInstance);
- reactFlowInstance.fitView();
+ console.log('pane ready:', reactFlowInstance);
};
const onMoveStart = (transform?: FlowTransform) => console.log('zoom/move start', transform);
@@ -158,7 +157,7 @@ const nodeColor = (n: Node): string => {
};
const OverviewFlow = () => {
- const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
+ const [nodes, , onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
@@ -193,6 +192,7 @@ const OverviewFlow = () => {
onEdgeMouseMove={onEdgeMouseMove}
onEdgeMouseLeave={onEdgeMouseLeave}
onEdgeDoubleClick={onEdgeDoubleClick}
+ fitViewOnInit
>
diff --git a/example/src_oldapi/Provider/Sidebar.tsx b/example/src/Provider/Sidebar.tsx
similarity index 56%
rename from example/src_oldapi/Provider/Sidebar.tsx
rename to example/src/Provider/Sidebar.tsx
index 0b2c5f24..ecd0665b 100644
--- a/example/src_oldapi/Provider/Sidebar.tsx
+++ b/example/src/Provider/Sidebar.tsx
@@ -1,13 +1,13 @@
-import React from 'react';
-import { useStoreState, useStoreActions } from 'react-flow-renderer';
+import { useStore, useStoreApi } from 'react-flow-renderer';
const Sidebar = () => {
- const nodes = useStoreState((store) => store.nodes);
- const transform = useStoreState((store) => store.transform);
- const setSelectedElements = useStoreActions((actions) => actions.setSelectedElements);
+ const store = useStoreApi();
+ const nodeInternals = useStore((store) => store.nodeInternals);
+ const transform = useStore((store) => store.transform);
const selectAll = () => {
- setSelectedElements(nodes.map((node) => ({ id: node.id, type: node.type })));
+ nodeInternals.forEach((node) => (node.selected = true));
+ store.setState({ nodeInternals: new Map(nodeInternals) });
};
return (
@@ -20,9 +20,9 @@ const Sidebar = () => {
[{transform[0].toFixed(2)}, {transform[1].toFixed(2)}, {transform[2].toFixed(2)}]
Nodes
- {nodes.map((node) => (
+ {Array.from(nodeInternals).map(([, node]) => (
- Node {node.id} - x: {node.__rf.position.x.toFixed(2)}, y: {node.__rf.position.y.toFixed(2)}
+ Node {node.id} - x: {node.position.x.toFixed(2)}, y: {node.position.y.toFixed(2)}
))}
diff --git a/example/src_oldapi/Provider/index.tsx b/example/src/Provider/index.tsx
similarity index 56%
rename from example/src_oldapi/Provider/index.tsx
rename to example/src/Provider/index.tsx
index a7a78b7c..342900e1 100644
--- a/example/src_oldapi/Provider/index.tsx
+++ b/example/src/Provider/index.tsx
@@ -1,37 +1,40 @@
-import React, { useState, MouseEvent } from 'react';
+import { MouseEvent } from 'react';
import ReactFlow, {
ReactFlowProvider,
addEdge,
- removeElements,
+ Node,
Controls,
- OnLoadParams,
- FlowElement,
Connection,
Edge,
- Elements,
ConnectionMode,
+ useNodesState,
+ useEdgesState,
+ ReactFlowInstance,
} from 'react-flow-renderer';
import Sidebar from './Sidebar';
import './provider.css';
-const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
-const onLoad = (reactFlowInstance: OnLoadParams) => console.log('flow loaded:', reactFlowInstance);
+const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
+const onPaneReady = (reactFlowInstance: ReactFlowInstance) => console.log('pane ready:', reactFlowInstance);
-const initialElements: Elements = [
+const initialNodes: Node[] = [
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } },
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 } },
{ id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 } },
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 } },
+];
+
+const initialEdges: Edge[] = [
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e1-3', source: '1', target: '3' },
];
const ProviderFlow = () => {
- const [elements, setElements] = useState(initialElements);
- const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
- const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
+ const [nodes, , onNodesChange] = useNodesState(initialNodes);
+ const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
+ const onConnect = (params: Edge | Connection) => setEdges((els) => addEdge(params, els));
return (
@@ -39,11 +42,13 @@ const ProviderFlow = () => {
diff --git a/example/src_oldapi/Provider/provider.css b/example/src/Provider/provider.css
similarity index 100%
rename from example/src_oldapi/Provider/provider.css
rename to example/src/Provider/provider.css
diff --git a/example/src_oldapi/Undirectional/CustomNode.tsx b/example/src/Undirectional/CustomNode.tsx
similarity index 100%
rename from example/src_oldapi/Undirectional/CustomNode.tsx
rename to example/src/Undirectional/CustomNode.tsx
diff --git a/example/src_oldapi/Undirectional/index.tsx b/example/src/Undirectional/index.tsx
similarity index 80%
rename from example/src_oldapi/Undirectional/index.tsx
rename to example/src/Undirectional/index.tsx
index de6bc11f..79b5615a 100644
--- a/example/src_oldapi/Undirectional/index.tsx
+++ b/example/src/Undirectional/index.tsx
@@ -1,66 +1,79 @@
-import React, { useState, useCallback } from 'react';
+import { useCallback } from 'react';
import ReactFlow, {
NodeTypesType,
addEdge,
useZoomPanHelper,
ReactFlowProvider,
- Elements,
+ Node,
Connection,
Edge,
- ElementId,
ConnectionLineType,
ConnectionMode,
updateEdge,
+ useNodesState,
+ useEdgesState,
} from 'react-flow-renderer';
import CustomNode from './CustomNode';
-const initialElements: Elements = [
+const initialNodes: Node[] = [
{
id: '00',
type: 'custom',
position: { x: 300, y: 250 },
+ data: null,
},
{
id: '01',
type: 'custom',
position: { x: 100, y: 50 },
+ data: null,
},
{
id: '02',
type: 'custom',
position: { x: 500, y: 50 },
+ data: null,
},
{
id: '03',
type: 'custom',
position: { x: 500, y: 500 },
+ data: null,
},
{
id: '04',
type: 'custom',
position: { x: 100, y: 500 },
+ data: null,
},
{
id: '10',
type: 'custom',
position: { x: 300, y: 5 },
+ data: null,
},
{
id: '20',
type: 'custom',
position: { x: 600, y: 250 },
+ data: null,
},
{
id: '30',
type: 'custom',
position: { x: 300, y: 600 },
+ data: null,
},
{
id: '40',
type: 'custom',
position: { x: 5, y: 250 },
+ data: null,
},
+];
+
+const initialEdges: Edge[] = [
{
id: 'e0-1a',
source: '00',
@@ -164,22 +177,25 @@ const nodeTypes: NodeTypesType = {
};
let id = 4;
-const getId = (): ElementId => `${id++}`;
+const getId = () => `${id++}`;
const UpdateNodeInternalsFlow = () => {
- const [elements, setElements] = useState(initialElements);
- const onConnect = (params: Connection | Edge) => setElements((els) => addEdge({ ...params, type: 'default' }, els));
+ const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
+ const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
+
+ const onConnect = (params: Edge | Connection) => setEdges((els) => addEdge(params, els));
const { project } = useZoomPanHelper();
const onEdgeUpdate = (oldEdge: Edge, newConnection: Connection) =>
- setElements((els) => updateEdge(oldEdge, newConnection, els));
+ setEdges((els) => updateEdge(oldEdge, newConnection, els));
const onPaneClick = useCallback(
(evt) =>
- setElements((els) =>
- els.concat({
+ setNodes((nds) =>
+ nds.concat({
id: getId(),
position: project({ x: evt.clientX, y: evt.clientY - 40 }),
type: 'custom',
+ data: null,
})
),
[project]
@@ -187,7 +203,10 @@ const UpdateNodeInternalsFlow = () => {
return (
`${id++}`;
+
+const getId = () => `${id++}`;
const UseZoomPanHelperFlow = () => {
- const [elements, setElements] = useState(initialElements);
- const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
- const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
+ const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
+ const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
+ const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
const { project, setCenter, zoomIn, zoomOut } = useZoomPanHelper();
const onPaneClick = useCallback(
(evt) => {
const projectedPosition = project({ x: evt.clientX, y: evt.clientY - 40 });
- setElements((els) =>
- els.concat({
+ setNodes((nds) =>
+ nds.concat({
id: getId(),
position: projectedPosition,
data: {
@@ -48,25 +52,27 @@ const UseZoomPanHelperFlow = () => {
[project]
);
- const onElementClick = useCallback(
+ const onNodeClick = useCallback(
(_, element) => {
const { x, y } = element.position;
- setCenter(x, y, 1);
+ setCenter(x, y, { zoom: 1 });
},
[setCenter]
);
return (
-
-
+
+
diff --git a/example/src/index.tsx b/example/src/index.tsx
index d81cad1f..967a7087 100644
--- a/example/src/index.tsx
+++ b/example/src/index.tsx
@@ -17,6 +17,10 @@ import Subflow from './Subflow';
import Interaction from './Interaction';
import Empty from './Empty';
import DragHandle from './DragHandle';
+import Undirectional from './Undirectional';
+import Provider from './Provider';
+import CustomConnectionLine from './CustomConnectionLine';
+import UseZoomPanHelper from './UseZoomPanHelper';
import './index.css';
@@ -81,6 +85,22 @@ const routes = [
path: '/draghandle',
component: DragHandle,
},
+ {
+ path: '/undirectional',
+ component: Undirectional,
+ },
+ {
+ path: '/provider',
+ component: Provider,
+ },
+ {
+ path: '/custom-connectionline',
+ component: CustomConnectionLine,
+ },
+ {
+ path: '/usezoompanhelper',
+ component: UseZoomPanHelper,
+ },
];
const Header = withRouter(({ history, location }) => {
diff --git a/example/src_oldapi/CustomConnectionLine/index.tsx b/example/src_oldapi/CustomConnectionLine/index.tsx
deleted file mode 100644
index 48cbf561..00000000
--- a/example/src_oldapi/CustomConnectionLine/index.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import React, { useState } from 'react';
-import ReactFlow, {
- removeElements,
- addEdge,
- Background,
- BackgroundVariant,
- Elements,
- Connection,
- Edge,
-} from 'react-flow-renderer';
-
-import ConnectionLine from './ConnectionLine';
-
-const initialElements: Elements = [{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } }];
-
-const ConnectionLineFlow = () => {
- const [elements, setElements] = useState(initialElements);
- const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
- const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
-
- return (
-
-
-
- );
-};
-
-export default ConnectionLineFlow;
diff --git a/example/src_oldapi/UpdateNode/index.tsx b/example/src_oldapi/UpdateNode/index.tsx
deleted file mode 100644
index a7cce8f2..00000000
--- a/example/src_oldapi/UpdateNode/index.tsx
+++ /dev/null
@@ -1,78 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import ReactFlow, { Elements } from 'react-flow-renderer';
-
-import './updatenode.css';
-
-const initialElements: Elements = [
- { id: '1', data: { label: '-' }, position: { x: 100, y: 100 } },
- { id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 200 } },
- { id: 'e1-2', source: '1', target: '2' },
-];
-
-const UpdateNode = () => {
- const [elements, setElements] = useState(initialElements);
- const [nodeName, setNodeName] = useState('Node 1');
- const [nodeBg, setNodeBg] = useState('#eee');
- const [nodeHidden, setNodeHidden] = useState(false);
-
- useEffect(() => {
- setElements((els) =>
- els.map((el) => {
- if (el.id === '1') {
- // it's important that you create a new object here in order to notify react flow about the change
- el.data = {
- ...el.data,
- label: nodeName,
- };
- }
-
- return el;
- })
- );
- }, [nodeName, setElements]);
-
- useEffect(() => {
- setElements((els) =>
- els.map((el) => {
- if (el.id === '1') {
- // it's important that you create a new object here in order to notify react flow about the change
- el.style = { ...el.style, backgroundColor: nodeBg };
- }
-
- return el;
- })
- );
- }, [nodeBg, setElements]);
-
- useEffect(() => {
- setElements((els) =>
- els.map((el) => {
- if (el.id === '1' || el.id === 'e1-2') {
- // when you update a simple type you can just update the value
- el.isHidden = nodeHidden;
- }
-
- return el;
- })
- );
- }, [nodeHidden, setElements]);
-
- return (
-
-
-
- );
-};
-
-export default UpdateNode;
diff --git a/example/src_oldapi/UpdateNode/updatenode.css b/example/src_oldapi/UpdateNode/updatenode.css
deleted file mode 100644
index 95438054..00000000
--- a/example/src_oldapi/UpdateNode/updatenode.css
+++ /dev/null
@@ -1,21 +0,0 @@
-.updatenode__controls {
- position: absolute;
- right: 10px;
- top: 10px;
- z-index: 4;
- font-size: 12px;
-}
-
-.updatenode__controls label {
- display: block;
-}
-
-.updatenode__bglabel {
- margin-top: 10px;
-}
-
-.updatenode__checkboxwrapper {
- margin-top: 10px;
- display: flex;
- align-items: center;
-}