chore(examples): use new api

This commit is contained in:
moklick
2021-12-25 13:30:13 +01:00
parent 7a85bb9666
commit a969c63400
29 changed files with 398 additions and 523 deletions
+1 -2
View File
@@ -4,7 +4,6 @@ import ReactFlow, {
addEdge,
Background,
BackgroundVariant,
FlowElement,
Node,
Edge,
Connection,
@@ -14,7 +13,7 @@ import ReactFlow, {
} from 'react-flow-renderer';
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
const onNodeClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
const initialNodes: Node[] = [
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 }, className: 'light' },
@@ -1,22 +1,21 @@
import React, { useState, DragEvent } from 'react';
import { useState, DragEvent } from 'react';
import ReactFlow, {
ReactFlowProvider,
addEdge,
removeElements,
Controls,
OnLoadParams,
Elements,
ReactFlowInstance,
Connection,
Edge,
ElementId,
Node,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
import Sidebar from './Sidebar';
import './dnd.css';
const initialElements = [{ id: '1', type: 'input', data: { label: 'input node' }, position: { x: 250, y: 5 } }];
const initialNodes: Node[] = [{ id: '1', type: 'input', data: { label: 'input node' }, position: { x: 250, y: 5 } }];
const onDragOver = (event: DragEvent) => {
event.preventDefault();
@@ -24,15 +23,15 @@ const onDragOver = (event: DragEvent) => {
};
let id = 0;
const getId = (): ElementId => `dndnode_${id++}`;
const getId = () => `dndnode_${id++}`;
const DnDFlow = () => {
const [reactFlowInstance, setReactFlowInstance] = useState<OnLoadParams>();
const [elements, setElements] = useState<Elements>(initialElements);
const [reactFlowInstance, setReactFlowInstance] = useState<ReactFlowInstance>();
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
const onLoad = (_reactFlowInstance: OnLoadParams) => setReactFlowInstance(_reactFlowInstance);
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
const onPaneReady = (rfi: ReactFlowInstance) => setReactFlowInstance(rfi);
const onDrop = (event: DragEvent) => {
event.preventDefault();
@@ -47,7 +46,7 @@ const DnDFlow = () => {
data: { label: `${type} node` },
};
setElements((es) => es.concat(newNode));
setNodes((nds) => nds.concat(newNode));
}
};
@@ -56,10 +55,12 @@ const DnDFlow = () => {
<ReactFlowProvider>
<div className="reactflow-wrapper">
<ReactFlow
elements={elements}
nodes={nodes}
edges={edges}
onEdgesChange={onEdgesChange}
onNodesChange={onNodesChange}
onConnect={onConnect}
onElementsRemove={onElementsRemove}
onLoad={onLoad}
onPaneReady={onPaneReady}
onDrop={onDrop}
onDragOver={onDragOver}
>
@@ -1,41 +1,42 @@
/**
* Example for checking the different edge types and source and target positions
*/
import React, { useState } from 'react';
import ReactFlow, {
removeElements,
addEdge,
MiniMap,
Controls,
Background,
OnLoadParams,
ReactFlowInstance,
Connection,
Edge,
Elements,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
import { getElements } from './utils';
const onLoad = (reactFlowInstance: OnLoadParams) => {
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => {
reactFlowInstance.fitView();
console.log(reactFlowInstance.getElements());
console.log(reactFlowInstance.getNodes());
};
const initialElements = getElements();
const { nodes: initialNodes, edges: initialEdges } = getElements();
const multiSelectionKeyCode = ['ShiftLeft', 'ShiftRight'];
const deleteKeyCode = ['AltLeft+KeyD', 'Backspace'];
const EdgeTypesFlow = () => {
const [elements, setElements] = useState<Elements>(initialElements);
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
const [nodes, , onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
return (
<ReactFlow
elements={elements}
onLoad={onLoad}
onElementsRemove={onElementsRemove}
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onPaneReady={onPaneReady}
onConnect={onConnect}
minZoom={0.2}
zoomOnScroll={false}
@@ -1,4 +1,4 @@
import { ElementId, Elements, Position } from 'react-flow-renderer';
import { Node, Edge, Position } from 'react-flow-renderer';
const nodeWidth = 80;
const nodeGapWidth = nodeWidth * 2;
@@ -49,10 +49,10 @@ const offsets = [
];
let id = 0;
const getNodeId = (): ElementId => (id++).toString();
const getNodeId = (): string => (id++).toString();
export function getElements(): Elements {
const initialElements = [];
export function getElements(): { nodes: Node[]; edges: Edge[] } {
const initialElements = { nodes: [] as Node[], edges: [] as Edge[] };
for (let sourceTargetIndex = 0; sourceTargetIndex < sourceTargetPositions.length; sourceTargetIndex++) {
const currSourceTargetPos = sourceTargetPositions[sourceTargetIndex];
@@ -70,7 +70,7 @@ export function getElements(): Elements {
};
const sourceId = getNodeId();
const sourceData = { label: `Source ${sourceId}` };
const sourceNode = {
const sourceNode: Node = {
id: sourceId,
style,
data: sourceData,
@@ -85,7 +85,7 @@ export function getElements(): Elements {
x: sourcePosition.x + currOffset.x,
y: sourcePosition.y + currOffset.y,
};
const targetNode = {
const targetNode: Node = {
id: targetId,
style,
data: targetData,
@@ -94,10 +94,15 @@ export function getElements(): Elements {
targetPosition: currSourceTargetPos.target,
};
initialElements.push(sourceNode);
initialElements.push(targetNode);
initialElements.nodes.push(sourceNode);
initialElements.nodes.push(targetNode);
initialElements.push({ id: `${sourceId}-${targetId}`, source: sourceId, target: targetId, type: currEdgeType });
initialElements.edges.push({
id: `${sourceId}-${targetId}`,
source: sourceId,
target: targetId,
type: currEdgeType,
} as Edge);
}
}
}
@@ -1,29 +1,28 @@
import React, { useState, MouseEvent } from 'react';
import { MouseEvent } from 'react';
import ReactFlow, {
removeElements,
addEdge,
MiniMap,
Controls,
Background,
OnLoadParams,
FlowElement,
ReactFlowInstance,
EdgeTypesType,
Elements,
Connection,
Edge,
ArrowHeadType,
MarkerType,
Node,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
import CustomEdge from './CustomEdge';
import CustomEdge2 from './CustomEdge2';
const onLoad = (reactFlowInstance: OnLoadParams) => reactFlowInstance.fitView();
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitView();
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
const initialElements: Elements = [
const initialNodes: Node[] = [
{ id: '1', type: 'input', data: { label: 'Input 1' }, position: { x: 250, y: 0 } },
{ id: '2', data: { label: 'Node 2' }, position: { x: 150, y: 100 } },
{ id: '2a', data: { label: 'Node 2a' }, position: { x: 0, y: 180 } },
@@ -35,6 +34,9 @@ const initialElements: Elements = [
{ id: '7', type: 'output', data: { label: 'Output 7' }, position: { x: 250, y: 550 } },
{ id: '8', type: 'output', data: { label: 'Output 8' }, position: { x: 525, y: 600 } },
{ id: '9', type: 'output', data: { label: 'Output 9' }, position: { x: 675, y: 500 } },
];
const initialEdges: Edge[] = [
{ id: 'e1-2', source: '1', target: '2', label: 'bezier edge (default)', className: 'normal-edge' },
{ id: 'e2-2a', source: '2', target: '2a', type: 'smoothstep', label: 'smoothstep edge' },
{ id: 'e2-3', source: '2', target: '3', type: 'step', label: 'step edge' },
@@ -50,7 +52,7 @@ const initialElements: Elements = [
labelBgBorderRadius: 4,
labelBgStyle: { fill: '#FFCC00', color: '#fff', fillOpacity: 0.7 },
markerEnd: {
type: ArrowHeadType.ArrowClosed,
type: MarkerType.ArrowClosed,
},
},
{
@@ -82,18 +84,18 @@ const initialElements: Elements = [
labelStyle: { fill: 'red', fontWeight: 700 },
style: { stroke: '#ffcc00' },
markerEnd: {
type: ArrowHeadType.Arrow,
type: MarkerType.Arrow,
color: '#FFCC00',
units: 'userSpaceOnUse',
markerUnits: 'userSpaceOnUse',
width: 20,
height: 20,
strokeWidth: 2,
},
markerStart: {
type: ArrowHeadType.ArrowClosed,
type: MarkerType.ArrowClosed,
color: '#FFCC00',
orient: 'auto-start-reverse',
units: 'userSpaceOnUse',
markerUnits: 'userSpaceOnUse',
width: 20,
height: 20,
},
@@ -106,19 +108,20 @@ const edgeTypes: EdgeTypesType = {
};
const EdgesFlow = () => {
const [elements, setElements] = useState<Elements>(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));
return (
<ReactFlow
elements={elements}
onElementClick={onElementClick}
onElementsRemove={onElementsRemove}
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onNodeClick={onNodeClick}
onConnect={onConnect}
onNodeDragStop={onNodeDragStop}
onLoad={onLoad}
onPaneReady={onPaneReady}
snapToGrid={true}
edgeTypes={edgeTypes}
>
@@ -1,34 +1,45 @@
import React, { useState, FC } from 'react';
import { FC } from 'react';
import ReactFlow, {
removeElements,
addEdge,
Background,
Elements,
Node,
Edge,
Connection,
ReactFlowProvider,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
import './multiflows.css';
const initialElements: Elements = [
const initialNodes: Node[] = [
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 }, className: 'light' },
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 }, className: 'light' },
{ id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 }, className: 'light' },
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 }, className: 'light' },
];
const initialEdges: Edge[] = [
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e1-3', source: '1', target: '3' },
];
const Flow: FC = () => {
const [elements, setElements] = useState<Elements>(initialElements);
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
const onConnect = (params: Edge | Connection) => setElements((els) => addEdge(params, els));
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: Edge | Connection) => setEdges((eds) => addEdge(params, eds));
return (
<ReactFlowProvider>
<ReactFlow elements={elements} onElementsRemove={onElementsRemove} onConnect={onConnect}>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
>
<Background />
</ReactFlow>
</ReactFlowProvider>
+70
View File
@@ -0,0 +1,70 @@
import { CSSProperties } from 'react';
import ReactFlow, {
addEdge,
Node,
Position,
Connection,
Edge,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
const initialNodes: Node[] = [
{
id: '1',
sourcePosition: Position.Right,
type: 'input',
data: { label: 'Input' },
position: { x: 0, y: 80 },
},
{
id: '2',
type: 'output',
sourcePosition: Position.Right,
targetPosition: Position.Left,
data: { label: 'A Node' },
position: { x: 250, y: 0 },
},
];
const initialEdges: Edge[] = [{ id: 'e1-2', source: '1', type: 'smoothstep', target: '2', animated: true }];
const buttonStyle: CSSProperties = { position: 'absolute', right: 10, top: 30, zIndex: 4 };
const NodeTypeChangeFlow = () => {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
const changeType = () => {
setNodes((nds) =>
nds.map((node) => {
if (node.type === 'input') {
return node;
}
return {
...node,
type: node.type === 'default' ? 'output' : 'default',
};
})
);
};
return (
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
fitViewOnInit
>
<button onClick={changeType} style={buttonStyle}>
change type
</button>
</ReactFlow>
);
};
export default NodeTypeChangeFlow;
@@ -1,16 +1,18 @@
import React, { useState, CSSProperties, FC } from 'react';
import { useState, CSSProperties, FC } from 'react';
import ReactFlow, {
addEdge,
Elements,
Node,
Position,
Connection,
Edge,
NodeProps,
NodeTypesType,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
const initialElements: Elements = [
const initialNodes: Node[] = [
{
id: '1',
sourcePosition: Position.Right,
@@ -55,16 +57,19 @@ const nodeTypesObjects: NodeTypesObject = {
const NodeTypeChangeFlow = () => {
const [nodeTypesId, setNodeTypesId] = useState<string>('a');
const [elements, setElements] = useState<Elements>(initialElements);
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
const changeType = () => setNodeTypesId((nt) => (nt === 'a' ? 'b' : 'a'));
return (
<ReactFlow
elements={elements}
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
nodeTypes={nodeTypesObjects[nodeTypesId]}
nodeTypesId={nodeTypesId}
>
<button onClick={changeType} style={buttonStyle}>
change type
@@ -1,5 +1,5 @@
import React, { memo, useCallback, Dispatch, FC } from 'react';
import { useZoomPanHelper, OnLoadParams, Elements, FlowExportObject } from 'react-flow-renderer';
import { useZoomPanHelper, ReactFlowInstance, Edge, Node, FlowExportObject } from 'react-flow-renderer';
import localforage from 'localforage';
localforage.config({
@@ -12,12 +12,13 @@ const flowKey = 'example-flow';
const getNodeId = () => `randomnode_${+new Date()}`;
type ControlsProps = {
rfInstance?: OnLoadParams;
setElements: Dispatch<React.SetStateAction<Elements<any>>>;
rfInstance?: ReactFlowInstance;
setNodes: Dispatch<React.SetStateAction<Node<any>[]>>;
setEdges: Dispatch<React.SetStateAction<Edge<any>[]>>;
};
const Controls: FC<ControlsProps> = ({ rfInstance, setElements }) => {
const { transform } = useZoomPanHelper();
const Controls: FC<ControlsProps> = ({ rfInstance, setNodes, setEdges }) => {
const { setTransform } = useZoomPanHelper();
const onSave = useCallback(() => {
if (rfInstance) {
@@ -32,13 +33,14 @@ const Controls: FC<ControlsProps> = ({ rfInstance, setElements }) => {
if (flow) {
const [x = 0, y = 0] = flow.position;
setElements(flow.elements || []);
transform({ x, y, zoom: flow.zoom || 0 });
setNodes(flow.nodes || []);
setEdges(flow.edges || []);
setTransform({ x, y, zoom: flow.zoom || 0 });
}
};
restoreFlow();
}, [setElements, transform]);
}, [setNodes, setEdges, setTransform]);
const onAdd = useCallback(() => {
const newNode = {
@@ -46,8 +48,8 @@ const Controls: FC<ControlsProps> = ({ rfInstance, setElements }) => {
data: { label: 'Added node' },
position: { x: Math.random() * window.innerWidth - 100, y: Math.random() * window.innerHeight },
};
setElements((els) => els.concat(newNode));
}, [setElements]);
setNodes((nds) => nds.concat(newNode));
}, [setNodes]);
return (
<div className="save__controls">
+46
View File
@@ -0,0 +1,46 @@
import { useState } from 'react';
import ReactFlow, {
ReactFlowProvider,
Node,
addEdge,
Connection,
Edge,
ReactFlowInstance,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
import Controls from './Controls';
import './save.css';
const initialNodes: Node[] = [
{ id: '1', data: { label: 'Node 1' }, position: { x: 100, y: 100 } },
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 200 } },
];
const initialEdges: Edge[] = [{ id: 'e1-2', source: '1', target: '2' }];
const SaveRestore = () => {
const [rfInstance, setRfInstance] = useState<ReactFlowInstance>();
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
return (
<ReactFlowProvider>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
onPaneReady={setRfInstance}
>
<Controls rfInstance={rfInstance} setNodes={setNodes} setEdges={setEdges} />
</ReactFlow>
</ReactFlowProvider>
);
};
export default SaveRestore;
@@ -1,26 +1,30 @@
import React, { useState, MouseEvent } from 'react';
import ReactFlow, { removeElements, addEdge, Node, FlowElement, Elements, Connection, Edge } from 'react-flow-renderer';
import { MouseEvent } from 'react';
import ReactFlow, { addEdge, Node, Connection, Edge, useNodesState, useEdgesState } from 'react-flow-renderer';
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
const elementsA: Elements = [
const nodesA: Node[] = [
{ id: '1a', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 }, className: 'light' },
{ id: '2a', data: { label: 'Node 2' }, position: { x: 100, y: 100 }, className: 'light' },
{ id: '3a', data: { label: 'Node 3' }, position: { x: 400, y: 100 }, className: 'light' },
{ id: '4a', data: { label: 'Node 4' }, position: { x: 400, y: 200 }, className: 'light' },
];
const edgesA: Edge[] = [
{ id: 'e1-2', source: '1a', target: '2a' },
{ id: 'e1-3', source: '1a', target: '3a' },
];
const elementsB: Elements = [
const nodesB: Node[] = [
{ id: 'inputb', type: 'input', data: { label: 'Input' }, position: { x: 300, y: 5 }, className: 'light' },
{ id: '1b', data: { label: 'Node 1' }, position: { x: 0, y: 100 }, className: 'light' },
{ id: '2b', data: { label: 'Node 2' }, position: { x: 200, y: 100 }, className: 'light' },
{ id: '3b', data: { label: 'Node 3' }, position: { x: 400, y: 100 }, className: 'light' },
{ id: '4b', data: { label: 'Node 4' }, position: { x: 600, y: 100 }, className: 'light' },
];
const edgesB: Edge[] = [
{ id: 'e1b', source: 'inputb', target: '1b' },
{ id: 'e2b', source: 'inputb', target: '2b' },
{ id: 'e3b', source: 'inputb', target: '3b' },
@@ -28,23 +32,39 @@ const elementsB: Elements = [
];
const BasicFlow = () => {
const [elements, setElements] = useState<Elements>(elementsA);
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
const [nodes, setNodes, onNodesChange] = useNodesState(nodesA);
const [edges, setEdges, onEdgesChange] = useEdgesState(edgesA);
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
return (
<ReactFlow
elements={elements}
onElementClick={onElementClick}
onElementsRemove={onElementsRemove}
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onNodeClick={onNodeClick}
onConnect={onConnect}
onNodeDragStop={onNodeDragStop}
>
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
<button onClick={() => setElements(elementsA)} style={{ marginRight: 5 }}>
<button
onClick={() => {
setNodes(nodesA);
setEdges(edgesA);
}}
style={{ marginRight: 5 }}
>
flow a
</button>
<button onClick={() => setElements(elementsB)}>flow b</button>
<button
onClick={() => {
setNodes(nodesB);
setEdges(edgesB);
}}
>
flow b
</button>
</div>
</ReactFlow>
);
+1 -1
View File
@@ -31,7 +31,7 @@ const initialNodes: Node[] = [
const initialEdges: Edge[] = [];
const TouchDeviceFlow = () => {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [nodes, , onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = useCallback((connection: Connection) => setEdges((eds) => addEdge(connection, eds)), []);
@@ -1,5 +1,4 @@
import React, { memo, FC, useMemo, CSSProperties } from 'react';
import { Handle, Position, NodeProps } from 'react-flow-renderer';
const nodeStyles: CSSProperties = { padding: 10, border: '1px solid #ddd' };
@@ -1,23 +1,23 @@
import React, { useState, useCallback, CSSProperties } from 'react';
import { useCallback, CSSProperties } from 'react';
import ReactFlow, {
NodeTypesType,
addEdge,
useZoomPanHelper,
ReactFlowProvider,
Elements,
Node,
Connection,
Edge,
ElementId,
useUpdateNodeInternals,
Position,
isEdge,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
import CustomNode from './CustomNode';
const initialHandleCount = 1;
const initialElements: Elements = [
const initialNodes: Node[] = [
{
id: '1',
type: 'custom',
@@ -33,18 +33,20 @@ const nodeTypes: NodeTypesType = {
};
let id = 5;
const getId = (): ElementId => `${id++}`;
const getId = (): string => `${id++}`;
const UpdateNodeInternalsFlow = () => {
const [elements, setElements] = useState<Elements>(initialElements);
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
const onConnect = (params: Edge | Connection) => setEdges((els) => addEdge(params, els));
const updateNodeInternals = useUpdateNodeInternals();
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
const { project } = useZoomPanHelper();
const onPaneClick = useCallback(
(evt) =>
setElements((els) =>
els.concat({
setNodes((nds) =>
nds.concat({
id: getId(),
position: project({ x: evt.clientX, y: evt.clientY - 40 }),
data: { label: 'new node' },
@@ -56,25 +58,17 @@ const UpdateNodeInternalsFlow = () => {
);
const toggleHandleCount = useCallback(() => {
setElements((els) =>
els.map((el) => {
if (isEdge(el)) {
return el;
}
return { ...el, data: { ...el.data, handleCount: el.data?.handleCount === 1 ? 2 : 1 } };
setNodes((nds) =>
nds.map((node) => {
return { ...node, data: { ...node.data, handleCount: node.data?.handleCount === 1 ? 2 : 1 } };
})
);
}, []);
const toggleHandlePosition = useCallback(() => {
setElements((els) =>
els.map((el) => {
if (isEdge(el)) {
return el;
}
return { ...el, data: { ...el.data, handlePosition: el.data?.handlePosition === 0 ? 1 : 0 } };
setNodes((nds) =>
nds.map((node) => {
return { ...node, data: { ...node.data, handlePosition: node.data?.handlePosition === 0 ? 1 : 0 } };
})
);
}, []);
@@ -82,7 +76,15 @@ const UpdateNodeInternalsFlow = () => {
const updateNode = useCallback(() => updateNodeInternals('1'), [updateNodeInternals]);
return (
<ReactFlow elements={elements} nodeTypes={nodeTypes} onConnect={onConnect} onPaneClick={onPaneClick}>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
nodeTypes={nodeTypes}
onConnect={onConnect}
onPaneClick={onPaneClick}
>
<div style={buttonWrapperStyles}>
<button onClick={toggleHandleCount}>toggle handle count</button>
<button onClick={toggleHandlePosition}>toggle handle position</button>
@@ -1,27 +1,27 @@
import React, { useState, MouseEvent as ReactMouseEvent, FC } from 'react';
import { MouseEvent as ReactMouseEvent, FC } from 'react';
import ReactFlow, {
addEdge,
Handle,
OnLoadParams,
Connection,
Position,
Elements,
Node,
Edge,
OnConnectStartParams,
NodeProps,
NodeTypesType,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
import './validation.css';
const initialElements: Elements = [
{ id: '0', type: 'custominput', position: { x: 0, y: 150 } },
{ id: 'A', type: 'customnode', position: { x: 250, y: 0 } },
{ id: 'B', type: 'customnode', position: { x: 250, y: 150 } },
{ id: 'C', type: 'customnode', position: { x: 250, y: 300 } },
const initialNodes: Node[] = [
{ id: '0', type: 'custominput', position: { x: 0, y: 150 }, data: null },
{ id: 'A', type: 'customnode', position: { x: 250, y: 0 }, data: null },
{ id: 'B', type: 'customnode', position: { x: 250, y: 150 }, data: null },
{ id: 'C', type: 'customnode', position: { x: 250, y: 300 }, data: null },
];
const onLoad = (reactFlowInstance: OnLoadParams) => reactFlowInstance.fitView();
const isValidConnection = (connection: Connection) => connection.target === 'B';
const onConnectStart = (_: ReactMouseEvent, { nodeId, handleType }: OnConnectStartParams) =>
console.log('on connect start', { nodeId, handleType });
@@ -48,26 +48,31 @@ const nodeTypes: NodeTypesType = {
customnode: CustomNode,
};
const HorizontalFlow = () => {
const [elements, setElements] = useState<Elements>(initialElements);
const ValidationFlow = () => {
const [nodes, , onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
const onConnect = (params: Connection | Edge) => {
console.log('on connect', params);
setElements((els) => addEdge(params, els));
setEdges((eds) => addEdge(params, eds));
};
return (
<ReactFlow
elements={elements}
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
selectNodesOnDrag={false}
onLoad={onLoad}
className="validationflow"
nodeTypes={nodeTypes}
onConnectStart={onConnectStart}
onConnectStop={onConnectStop}
onConnectEnd={onConnectEnd}
fitViewOnInit
/>
);
};
export default HorizontalFlow;
export default ValidationFlow;
+86 -36
View File
@@ -21,6 +21,16 @@ import Undirectional from './Undirectional';
import Provider from './Provider';
import CustomConnectionLine from './CustomConnectionLine';
import UseZoomPanHelper from './UseZoomPanHelper';
import DragNDrop from './DragNDrop';
import UseUpdateNodeInternals from './UseUpdateNodeInternals';
import Edges from './Edges';
import EdgeTypes from './EdgeTypes';
import MultiFlows from './MultiFlows';
import NodeTypeChange from './NodeTypeChange';
import NodeTypesObjectChange from './NodeTypesObjectChange';
import SaveRestore from './SaveRestore';
import SwitchFlow from './Switch';
import Validation from './Validation';
import './index.css';
@@ -34,73 +44,113 @@ const routes = [
component: Basic,
},
{
path: '/update-node',
component: UpdateNode,
},
{
path: '/stress',
component: Stress,
path: '/custom-connectionline',
component: CustomConnectionLine,
},
{
path: '/custom-node',
component: CustomNode,
},
{
path: '/floating-edges',
component: FloatingEdges,
path: '/draghandle',
component: DragHandle,
},
{
path: '/layouting',
component: Layouting,
path: '/dragndrop',
component: DragNDrop,
},
{
path: '/nested-nodes',
component: NestedNodes,
path: '/edges',
component: Edges,
},
{
path: '/hidden',
component: Hidden,
},
{
path: '/updatable-edge',
component: UpdatableEdge,
},
{
path: '/touch-device',
component: TouchDevice,
},
{
path: '/subflow',
component: Subflow,
},
{
path: '/interaction',
component: Interaction,
path: '/edge-types',
component: EdgeTypes,
},
{
path: '/empty',
component: Empty,
},
{
path: '/draghandle',
component: DragHandle,
path: '/floating-edges',
component: FloatingEdges,
},
{
path: '/undirectional',
component: Undirectional,
path: '/hidden',
component: Hidden,
},
{
path: '/interaction',
component: Interaction,
},
{
path: '/layouting',
component: Layouting,
},
{
path: '/multiflows',
component: MultiFlows,
},
{
path: '/nested-nodes',
component: NestedNodes,
},
{
path: '/nodetype-change',
component: NodeTypeChange,
},
{
path: '/nodetypesobject-change',
component: NodeTypesObjectChange,
},
{
path: '/provider',
component: Provider,
},
{
path: '/custom-connectionline',
component: CustomConnectionLine,
path: '/save-restore',
component: SaveRestore,
},
{
path: '/stress',
component: Stress,
},
{
path: '/subflow',
component: Subflow,
},
{
path: '/switch',
component: SwitchFlow,
},
{
path: '/touch-device',
component: TouchDevice,
},
{
path: '/undirectional',
component: Undirectional,
},
{
path: '/updatable-edge',
component: UpdatableEdge,
},
{
path: '/update-node',
component: UpdateNode,
},
{
path: '/usezoompanhelper',
component: UseZoomPanHelper,
},
{
path: '/useupdatenodeinternals',
component: UseUpdateNodeInternals,
},
{
path: '/validation',
component: Validation,
},
];
const Header = withRouter(({ history, location }) => {
@@ -1,55 +0,0 @@
import React, { useState, CSSProperties } from 'react';
import ReactFlow, { addEdge, isEdge, OnLoadParams, Elements, Position, Connection, Edge } from 'react-flow-renderer';
const onLoad = (reactFlowInstance: OnLoadParams) => reactFlowInstance.fitView();
const initialElements: Elements = [
{
id: '1',
sourcePosition: Position.Right,
type: 'input',
data: { label: 'Input' },
position: { x: 0, y: 80 },
},
{
id: '2',
type: 'output',
sourcePosition: Position.Right,
targetPosition: Position.Left,
data: { label: 'A Node' },
position: { x: 250, y: 0 },
},
{ id: 'e1-2', source: '1', type: 'smoothstep', target: '2', animated: true },
];
const buttonStyle: CSSProperties = { position: 'absolute', right: 10, top: 30, zIndex: 4 };
const NodeTypeChangeFlow = () => {
const [elements, setElements] = useState<Elements>(initialElements);
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
const changeType = () => {
setElements((elms) =>
elms.map((el) => {
if (isEdge(el) || el.type === 'input') {
return el;
}
return {
...el,
type: el.type === 'default' ? 'output' : 'default',
};
})
);
};
return (
<ReactFlow elements={elements} onConnect={onConnect} onLoad={onLoad}>
<button onClick={changeType} style={buttonStyle}>
change type
</button>
</ReactFlow>
);
};
export default NodeTypeChangeFlow;
-37
View File
@@ -1,37 +0,0 @@
import React, { useState } from 'react';
import ReactFlow, {
ReactFlowProvider,
removeElements,
addEdge,
Elements,
Connection,
Edge,
OnLoadParams,
} from 'react-flow-renderer';
import Controls from './Controls';
import './save.css';
const initialElements: Elements = [
{ id: '1', data: { label: 'Node 1' }, position: { x: 100, y: 100 } },
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 200 } },
{ id: 'e1-2', source: '1', target: '2' },
];
const SaveRestore = () => {
const [rfInstance, setRfInstance] = useState<OnLoadParams>();
const [elements, setElements] = useState<Elements>(initialElements);
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
return (
<ReactFlowProvider>
<ReactFlow elements={elements} onElementsRemove={onElementsRemove} onConnect={onConnect} onLoad={setRfInstance}>
<Controls rfInstance={rfInstance} setElements={setElements} />
</ReactFlow>
</ReactFlowProvider>
);
};
export default SaveRestore;
-82
View File
@@ -1,82 +0,0 @@
body {
font-family: sans-serif;
color: #111;
}
html,
body,
#root {
margin: 0;
height: 100%;
}
#root {
display: flex;
flex-direction: column;
}
header {
padding: 10px;
border-bottom: 1px solid #eee;
display: flex;
font-weight: 700;
align-items: center;
}
.logo {
text-decoration: none;
display: block;
line-height: 1;
}
header a,
header a:focus,
header a:active,
header a:visited {
color: #111;
}
header a:hover {
color: #333;
}
header select {
margin-left: 1em;
}
.overview-example__add {
display: none;
}
.react-flow__node a {
font-weight: 700;
color: #111;
}
.react-flow__node.dark-node {
background: #0041d0;
color: #f8f8f8;
}
.react-flow__node.dark {
background: #557;
color: #f8f8f8;
}
.react-flow__node-selectorNode {
font-size: 12px;
background: #f0f2f3;
border: 1px solid 555;
border-radius: 5px;
text-align: center;
}
.react-flow__node-selectorNode .react-flow__handle {
border-color: #f0f2f3;
}
@media screen and (min-width: 768px) {
.overview-example__add {
display: block;
}
}
-165
View File
@@ -1,165 +0,0 @@
import React, { ChangeEvent } from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, Switch, withRouter } from 'react-router-dom';
import Overview from './Overview';
import Basic from './Basic';
import CustomNode from './CustomNode';
import Stress from './Stress';
import Interaction from './Interaction';
import Empty from './Empty';
import Edges from './Edges';
import Validation from './Validation';
import Provider from './Provider';
import Hidden from './Hidden';
import EdgeTypes from './EdgeTypes';
import CustomConnectionLine from './CustomConnectionLine';
import NodeTypeChange from './NodeTypeChange';
import NodeTypesObjectChange from './NodeTypesObjectChange';
import UpdatableEdge from './UpdatableEdge';
import UpdateNode from './UpdateNode';
import SaveRestore from './SaveRestore';
import DragNDrop from './DragNDrop';
import Layout from './Layouting';
import SwitchFlows from './Switch';
import UseZoomPanHelper from './UseZoomPanHelper';
import UseUpdateNodeInternals from './UseUpdateNodeInternals';
import Undirectional from './Undirectional';
import MultiFlows from './MultiFlows';
import DragHandle from './DragHandle';
import './index.css';
const routes = [
{
path: '/',
component: Overview,
},
{
path: '/edges',
component: Edges,
},
{
path: '/custom-node',
component: CustomNode,
},
{
path: '/validation',
component: Validation,
},
{
path: '/provider',
component: Provider,
},
{
path: '/stress',
component: Stress,
},
{
path: '/interaction',
component: Interaction,
},
{
path: '/basic',
component: Basic,
},
{
path: '/empty',
component: Empty,
},
{
path: '/hidden',
component: Hidden,
},
{
path: '/edge-types',
component: EdgeTypes,
},
{
path: '/custom-connectionline',
component: CustomConnectionLine,
},
{
path: '/nodetype-change',
component: NodeTypeChange,
},
{
path: '/nodetypesobject-change',
component: NodeTypesObjectChange,
},
{
path: '/updatable-edge',
component: UpdatableEdge,
},
{
path: '/update-node',
component: UpdateNode,
},
{
path: '/save-restore',
component: SaveRestore,
},
{
path: '/drag-and-drop',
component: DragNDrop,
},
{
path: '/layouting',
component: Layout,
},
{
path: '/switch',
component: SwitchFlows,
},
{
path: '/usezoompanhelper',
component: UseZoomPanHelper,
},
{
path: '/useupdatenodeinternals',
component: UseUpdateNodeInternals,
},
{
path: '/undirectional',
component: Undirectional,
},
{
path: '/multiflows',
component: MultiFlows,
},
{
path: '/draghandle',
component: DragHandle,
},
];
const Header = withRouter(({ history, location }) => {
const onChange = (event: ChangeEvent<HTMLSelectElement>) => history.push(event.target.value);
return (
<header>
<a className="logo" href="https://github.com/wbkd/react-flow">
React Flow Dev
</a>
<select defaultValue={location.pathname} onChange={onChange}>
{routes.map((route) => (
<option value={route.path} key={route.path}>
{route.path === '/' ? 'overview' : route.path.substr(1, route.path.length)}
</option>
))}
</select>
</header>
);
});
ReactDOM.render(
<Router forceRefresh={true}>
<Header />
<Switch>
{routes.map((route) => (
<Route exact path={route.path} render={() => <route.component />} key={route.path} />
))}
</Switch>
</Router>,
document.getElementById('root')
);
-1
View File
@@ -1 +0,0 @@
/// <reference types="react-scripts" />
-4
View File
@@ -7,10 +7,6 @@ import { Node, NodeInternals, NodeDimensionUpdate, NodeDiffUpdate } from './node
import { Edge } from './edges';
import { HandleType, StartHandle } from './handles';
export type FlowElement<T = any> = Node<T> | Edge<T>;
export type Elements<T = any> = Array<FlowElement<T>>;
export type NodeTypesType = { [key: string]: ReactNode };
export type EdgeTypesType = NodeTypesType;