refactor(examples): use cra + ts
This commit is contained in:
@@ -1,11 +1,23 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, MouseEvent } from 'react';
|
||||
|
||||
import ReactFlow, { removeElements, addEdge, isNode, Background } from 'react-flow-renderer';
|
||||
import ReactFlow, {
|
||||
removeElements,
|
||||
addEdge,
|
||||
isNode,
|
||||
Background,
|
||||
Elements,
|
||||
BackgroundVariant,
|
||||
FlowElement,
|
||||
Node,
|
||||
Edge,
|
||||
Connection,
|
||||
OnLoadParams,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
const onNodeDragStop = (event, node) => console.log('drag stop', node);
|
||||
const onElementClick = (event, element) => console.log('click', element);
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
|
||||
|
||||
const initialElements = [
|
||||
const initialElements: Elements = [
|
||||
{ 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' },
|
||||
@@ -15,11 +27,11 @@ const initialElements = [
|
||||
];
|
||||
|
||||
const BasicFlow = () => {
|
||||
const [rfInstance, setRfInstance] = useState(null);
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const onLoad = (reactFlowInstance) => setRfInstance(reactFlowInstance);
|
||||
const [rfInstance, setRfInstance] = useState<OnLoadParams | null>(null);
|
||||
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 onLoad = (reactFlowInstance: OnLoadParams) => setRfInstance(reactFlowInstance);
|
||||
|
||||
const updatePos = () => {
|
||||
setElements((elms) => {
|
||||
@@ -36,8 +48,8 @@ const BasicFlow = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const logToObject = () => console.log(rfInstance.toObject());
|
||||
const resetTransform = () => rfInstance.setTransform({ x: 0, y: 0, zoom: 1 });
|
||||
const logToObject = () => console.log(rfInstance?.toObject());
|
||||
const resetTransform = () => rfInstance?.setTransform({ x: 0, y: 0, zoom: 1 });
|
||||
|
||||
const toggleClassnames = () => {
|
||||
setElements((elms) => {
|
||||
@@ -64,7 +76,7 @@ const BasicFlow = () => {
|
||||
minZoom={0.2}
|
||||
maxZoom={4}
|
||||
>
|
||||
<Background variant="lines" />
|
||||
<Background variant={BackgroundVariant.Lines} />
|
||||
|
||||
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
|
||||
<button onClick={resetTransform} style={{ marginRight: 5 }}>
|
||||
+5
-11
@@ -1,15 +1,7 @@
|
||||
import React from 'react';
|
||||
import React, { FC } from 'react';
|
||||
import { ConnectionLineComponentProps } from 'react-flow-renderer';
|
||||
|
||||
export default ({
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourcePosition,
|
||||
targetX,
|
||||
targetY,
|
||||
targetPosition,
|
||||
connectionLineType,
|
||||
connectionLineStyle,
|
||||
}) => {
|
||||
const ConnectionLine: FC<ConnectionLineComponentProps> = ({ sourceX, sourceY, targetX, targetY }) => {
|
||||
return (
|
||||
<g>
|
||||
<path
|
||||
@@ -23,3 +15,5 @@ export default ({
|
||||
</g>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConnectionLine;
|
||||
@@ -1,25 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import ReactFlow, { removeElements, addEdge, Background } from 'react-flow-renderer';
|
||||
|
||||
import ConnectionLine from './ConnectionLine';
|
||||
|
||||
const initialElements = [{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } }];
|
||||
|
||||
const ConnectionLineFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
connectionLineComponent={ConnectionLine}
|
||||
onElementsRemove={onElementsRemove}
|
||||
onConnect={onConnect}
|
||||
>
|
||||
<Background variant="lines" />
|
||||
</ReactFlow>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConnectionLineFlow;
|
||||
@@ -0,0 +1,33 @@
|
||||
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<Elements>(initialElements);
|
||||
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
connectionLineComponent={ConnectionLine}
|
||||
onElementsRemove={onElementsRemove}
|
||||
onConnect={onConnect}
|
||||
>
|
||||
<Background variant={BackgroundVariant.Lines} />
|
||||
</ReactFlow>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConnectionLineFlow;
|
||||
@@ -1,22 +0,0 @@
|
||||
import React, { memo } from 'react';
|
||||
|
||||
import { Handle } from 'react-flow-renderer';
|
||||
|
||||
export default memo(({ data }) => {
|
||||
return (
|
||||
<>
|
||||
<Handle
|
||||
type="target"
|
||||
position="left"
|
||||
style={{ background: '#555' }}
|
||||
onConnect={(params) => console.log('handle onConnect', params)}
|
||||
/>
|
||||
<div>
|
||||
Custom Color Picker Node: <strong>{data.color}</strong>
|
||||
</div>
|
||||
<input className="nodrag" type="color" onChange={data.onChange} defaultValue={data.color} />
|
||||
<Handle type="source" position="right" id="a" style={{ top: 10, background: '#555' }} />
|
||||
<Handle type="source" position="right" id="b" style={{ bottom: 10, top: 'auto', background: '#555' }} />
|
||||
</>
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
import React, { memo, FC, CSSProperties } from 'react';
|
||||
|
||||
import { Handle, Position, NodeProps, Connection, Edge } from 'react-flow-renderer';
|
||||
|
||||
const targetHandleStyle: CSSProperties = { background: '#555' };
|
||||
const sourceHandleStyleA: CSSProperties = { ...targetHandleStyle, top: 10 };
|
||||
const sourceHandleStyleB: CSSProperties = { ...targetHandleStyle, bottom: 10, top: 'auto' };
|
||||
|
||||
const onConnect = (params: Connection | Edge) => console.log('handle onConnect', params);
|
||||
|
||||
const ColorSelectorNode: FC<NodeProps> = ({ data }) => {
|
||||
return (
|
||||
<>
|
||||
<Handle type="target" position={Position.Left} style={targetHandleStyle} onConnect={onConnect} />
|
||||
<div>
|
||||
Custom Color Picker Node: <strong>{data.color}</strong>
|
||||
</div>
|
||||
<input className="nodrag" type="color" onChange={data.onChange} defaultValue={data.color} />
|
||||
<Handle type="source" position={Position.Right} id="a" style={sourceHandleStyleA} />
|
||||
<Handle type="source" position={Position.Right} id="b" style={sourceHandleStyleB} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(ColorSelectorNode);
|
||||
@@ -1,27 +1,42 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, MouseEvent } from 'react';
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
import ReactFlow, { isEdge, removeElements, addEdge, MiniMap, Controls } from 'react-flow-renderer';
|
||||
import ReactFlow, {
|
||||
isEdge,
|
||||
removeElements,
|
||||
addEdge,
|
||||
MiniMap,
|
||||
Controls,
|
||||
Node,
|
||||
FlowElement,
|
||||
OnLoadParams,
|
||||
Elements,
|
||||
Position,
|
||||
SnapGrid,
|
||||
Connection,
|
||||
Edge,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
import ColorSelectorNode from './ColorSelectorNode';
|
||||
|
||||
const onLoad = (reactFlowInstance) => console.log('flow loaded:', reactFlowInstance);
|
||||
const onNodeDragStop = (event, node) => console.log('drag stop', node);
|
||||
const onElementClick = (event, element) => console.log('click', element);
|
||||
const onLoad = (reactFlowInstance: OnLoadParams) => console.log('flow loaded:', reactFlowInstance);
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
|
||||
|
||||
const initBgColor = '#1A192B';
|
||||
|
||||
const connectionLineStyle = { stroke: '#fff' };
|
||||
const snapGrid = [16, 16];
|
||||
const snapGrid: SnapGrid = [16, 16];
|
||||
const nodeTypes = {
|
||||
selectorNode: ColorSelectorNode,
|
||||
};
|
||||
|
||||
const CustomNodeFlow = () => {
|
||||
const [elements, setElements] = useState([]);
|
||||
const [bgColor, setBgColor] = useState(initBgColor);
|
||||
const [elements, setElements] = useState<Elements>([]);
|
||||
const [bgColor, setBgColor] = useState<string>(initBgColor);
|
||||
|
||||
useEffect(() => {
|
||||
const onChange = (event) => {
|
||||
const onChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
setElements((els) =>
|
||||
els.map((e) => {
|
||||
if (isEdge(e) || e.id !== '2') {
|
||||
@@ -44,7 +59,13 @@ const CustomNodeFlow = () => {
|
||||
};
|
||||
|
||||
setElements([
|
||||
{ id: '1', type: 'input', data: { label: 'An input node' }, position: { x: 0, y: 50 }, sourcePosition: 'right' },
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
data: { label: 'An input node' },
|
||||
position: { x: 0, y: 50 },
|
||||
sourcePosition: Position.Right,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'selectorNode',
|
||||
@@ -52,8 +73,20 @@ const CustomNodeFlow = () => {
|
||||
style: { border: '1px solid #777', padding: 10 },
|
||||
position: { x: 250, y: 50 },
|
||||
},
|
||||
{ id: '3', type: 'output', data: { label: 'Output A' }, position: { x: 550, y: 25 }, targetPosition: 'left' },
|
||||
{ id: '4', type: 'output', data: { label: 'Output B' }, position: { x: 550, y: 100 }, targetPosition: 'left' },
|
||||
{
|
||||
id: '3',
|
||||
type: 'output',
|
||||
data: { label: 'Output A' },
|
||||
position: { x: 550, y: 25 },
|
||||
targetPosition: Position.Left,
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
type: 'output',
|
||||
data: { label: 'Output B' },
|
||||
position: { x: 550, y: 100 },
|
||||
targetPosition: Position.Left,
|
||||
},
|
||||
|
||||
{ id: 'e1-2', source: '1', target: '2', animated: true, style: { stroke: '#fff' } },
|
||||
{ id: 'e2a-3', source: '2', sourceHandle: 'a', target: '3', animated: true, style: { stroke: '#fff' } },
|
||||
@@ -61,8 +94,8 @@ const CustomNodeFlow = () => {
|
||||
]);
|
||||
}, []);
|
||||
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) =>
|
||||
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params: Connection | Edge) =>
|
||||
setElements((els) => addEdge({ ...params, animated: true, style: { stroke: '#fff' } }, els));
|
||||
|
||||
return (
|
||||
@@ -81,13 +114,16 @@ const CustomNodeFlow = () => {
|
||||
defaultZoom={1.5}
|
||||
>
|
||||
<MiniMap
|
||||
nodeStrokeColor={(n) => {
|
||||
nodeStrokeColor={(n: Node): string => {
|
||||
if (n.type === 'input') return '#0041d0';
|
||||
if (n.type === 'selectorNode') return bgColor;
|
||||
if (n.type === 'output') return '#ff0072';
|
||||
|
||||
return '#eee';
|
||||
}}
|
||||
nodeColor={(n) => {
|
||||
nodeColor={(n: Node): string => {
|
||||
if (n.type === 'selectorNode') return bgColor;
|
||||
|
||||
return '#fff';
|
||||
}}
|
||||
/>
|
||||
@@ -1,23 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
export default () => {
|
||||
const onDragStart = (event, nodeType) => {
|
||||
event.dataTransfer.setData('application/reactflow', nodeType);
|
||||
event.dataTransfer.effectAllowed = 'move';
|
||||
};
|
||||
|
||||
return (
|
||||
<aside>
|
||||
<div className="description">You can drag these nodes to the pane on the right.</div>
|
||||
<div className="dndnode input" onDragStart={(event) => onDragStart(event, 'input')} draggable>
|
||||
Input Node
|
||||
</div>
|
||||
<div className="dndnode" onDragStart={(event) => onDragStart(event, 'default')} draggable>
|
||||
Default Node
|
||||
</div>
|
||||
<div className="dndnode output" onDragStart={(event) => onDragStart(event, 'output')} draggable>
|
||||
Output Node
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import React, { DragEvent } from 'react';
|
||||
|
||||
const onDragStart = (event: DragEvent, nodeType: string) => {
|
||||
event.dataTransfer.setData('application/reactflow', nodeType);
|
||||
event.dataTransfer.effectAllowed = 'move';
|
||||
};
|
||||
|
||||
const Sidebar = () => {
|
||||
return (
|
||||
<aside>
|
||||
<div className="description">You can drag these nodes to the pane on the right.</div>
|
||||
<div className="dndnode input" onDragStart={(event: DragEvent) => onDragStart(event, 'input')} draggable>
|
||||
Input Node
|
||||
</div>
|
||||
<div className="dndnode" onDragStart={(event: DragEvent) => onDragStart(event, 'default')} draggable>
|
||||
Default Node
|
||||
</div>
|
||||
<div className="dndnode output" onDragStart={(event: DragEvent) => onDragStart(event, 'output')} draggable>
|
||||
Output Node
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
@@ -1,62 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import ReactFlow, { ReactFlowProvider, addEdge, removeElements, Controls } 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 } }];
|
||||
|
||||
let id = 0;
|
||||
const getId = () => `dndnode_${id++}`;
|
||||
|
||||
const DnDFlow = () => {
|
||||
const [reactFlowInstance, setReactFlowInstance] = useState(null);
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
|
||||
const onLoad = (_reactFlowInstance) => setReactFlowInstance(_reactFlowInstance);
|
||||
|
||||
const onDragOver = (event) => {
|
||||
event.preventDefault();
|
||||
event.dataTransfer.dropEffect = 'move';
|
||||
};
|
||||
|
||||
const onDrop = (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const type = event.dataTransfer.getData('application/reactflow');
|
||||
const position = reactFlowInstance.project({ x: event.clientX, y: event.clientY - 40 });
|
||||
const newNode = {
|
||||
id: getId(),
|
||||
type,
|
||||
position,
|
||||
data: { label: `${type} node` },
|
||||
};
|
||||
|
||||
setElements((es) => es.concat(newNode));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="dndflow">
|
||||
<ReactFlowProvider>
|
||||
<div className="reactflow-wrapper">
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
onConnect={onConnect}
|
||||
onElementsRemove={onElementsRemove}
|
||||
onLoad={onLoad}
|
||||
onDrop={onDrop}
|
||||
onDragOver={onDragOver}
|
||||
>
|
||||
<Controls />
|
||||
</ReactFlow>
|
||||
</div>
|
||||
<Sidebar />
|
||||
</ReactFlowProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DnDFlow;
|
||||
@@ -0,0 +1,75 @@
|
||||
import React, { useState, DragEvent } from 'react';
|
||||
import ReactFlow, {
|
||||
ReactFlowProvider,
|
||||
addEdge,
|
||||
removeElements,
|
||||
Controls,
|
||||
OnLoadParams,
|
||||
Elements,
|
||||
Connection,
|
||||
Edge,
|
||||
ElementId,
|
||||
Node,
|
||||
} 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 onDragOver = (event: DragEvent) => {
|
||||
event.preventDefault();
|
||||
event.dataTransfer.dropEffect = 'move';
|
||||
};
|
||||
|
||||
let id = 0;
|
||||
const getId = (): ElementId => `dndnode_${id++}`;
|
||||
|
||||
const DnDFlow = () => {
|
||||
const [reactFlowInstance, setReactFlowInstance] = useState<OnLoadParams>();
|
||||
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 onLoad = (_reactFlowInstance: OnLoadParams) => setReactFlowInstance(_reactFlowInstance);
|
||||
|
||||
const onDrop = (event: DragEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (reactFlowInstance) {
|
||||
const type = event.dataTransfer.getData('application/reactflow');
|
||||
const position = reactFlowInstance.project({ x: event.clientX, y: event.clientY - 40 });
|
||||
const newNode: Node = {
|
||||
id: getId(),
|
||||
type,
|
||||
position,
|
||||
data: { label: `${type} node` },
|
||||
};
|
||||
|
||||
setElements((es) => es.concat(newNode));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="dndflow">
|
||||
<ReactFlowProvider>
|
||||
<div className="reactflow-wrapper">
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
onConnect={onConnect}
|
||||
onElementsRemove={onElementsRemove}
|
||||
onLoad={onLoad}
|
||||
onDrop={onDrop}
|
||||
onDragOver={onDragOver}
|
||||
>
|
||||
<Controls />
|
||||
</ReactFlow>
|
||||
</div>
|
||||
<Sidebar />
|
||||
</ReactFlowProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DnDFlow;
|
||||
@@ -3,10 +3,20 @@
|
||||
*/
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import ReactFlow, { removeElements, addEdge, MiniMap, Controls, Background } from 'react-flow-renderer';
|
||||
import ReactFlow, {
|
||||
removeElements,
|
||||
addEdge,
|
||||
MiniMap,
|
||||
Controls,
|
||||
Background,
|
||||
OnLoadParams,
|
||||
Connection,
|
||||
Edge,
|
||||
Elements,
|
||||
} from 'react-flow-renderer';
|
||||
import { getElements } from './utils';
|
||||
|
||||
const onLoad = (reactFlowInstance) => {
|
||||
const onLoad = (reactFlowInstance: OnLoadParams) => {
|
||||
reactFlowInstance.fitView();
|
||||
console.log(reactFlowInstance.getElements());
|
||||
};
|
||||
@@ -14,9 +24,9 @@ const onLoad = (reactFlowInstance) => {
|
||||
const initialElements = getElements();
|
||||
|
||||
const EdgeTypesFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
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 (
|
||||
<ReactFlow
|
||||
@@ -1,10 +1,12 @@
|
||||
import { ElementId, Elements, Position } from 'react-flow-renderer';
|
||||
|
||||
const nodeWidth = 80;
|
||||
const nodeGapWidth = nodeWidth * 2;
|
||||
const nodeStyle = { width: nodeWidth, fontSize: 11, color: 'white' };
|
||||
|
||||
const sourceTargetPositions = [
|
||||
{ source: 'bottom', target: 'top' },
|
||||
{ source: 'right', target: 'left' },
|
||||
{ source: Position.Bottom, target: Position.Top },
|
||||
{ source: Position.Right, target: Position.Left },
|
||||
];
|
||||
const nodeColors = [
|
||||
['#1e9e99', '#4cb3ac', '#6ec9c0', '#8ddfd4'],
|
||||
@@ -47,9 +49,9 @@ const offsets = [
|
||||
];
|
||||
|
||||
let id = 0;
|
||||
const getNodeId = () => (id++).toString();
|
||||
const getNodeId = (): ElementId => (id++).toString();
|
||||
|
||||
export function getElements() {
|
||||
export function getElements(): Elements {
|
||||
const initialElements = [];
|
||||
|
||||
for (let sourceTargetIndex = 0; sourceTargetIndex < sourceTargetPositions.length; sourceTargetIndex++) {
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { getBezierPath, getMarkerEnd } from 'react-flow-renderer';
|
||||
import React, { FC } from 'react';
|
||||
import { EdgeProps, getBezierPath, getMarkerEnd } from 'react-flow-renderer';
|
||||
|
||||
export default function CustomEdge({
|
||||
const CustomEdge: FC<EdgeProps> = ({
|
||||
id,
|
||||
sourceX,
|
||||
sourceY,
|
||||
@@ -13,7 +13,7 @@ export default function CustomEdge({
|
||||
data,
|
||||
arrowHeadType,
|
||||
markerEndId,
|
||||
}) {
|
||||
}) => {
|
||||
const edgePath = getBezierPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition });
|
||||
const markerEnd = getMarkerEnd(arrowHeadType, markerEndId);
|
||||
|
||||
@@ -27,4 +27,6 @@ export default function CustomEdge({
|
||||
</text>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default CustomEdge;
|
||||
@@ -1,14 +1,28 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, MouseEvent } from 'react';
|
||||
|
||||
import ReactFlow, { removeElements, addEdge, MiniMap, Controls, Background } from 'react-flow-renderer';
|
||||
import ReactFlow, {
|
||||
removeElements,
|
||||
addEdge,
|
||||
MiniMap,
|
||||
Controls,
|
||||
Background,
|
||||
OnLoadParams,
|
||||
FlowElement,
|
||||
EdgeTypesType,
|
||||
Elements,
|
||||
Connection,
|
||||
Edge,
|
||||
ArrowHeadType,
|
||||
Node,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
import CustomEdge from './CustomEdge';
|
||||
|
||||
const onLoad = (reactFlowInstance) => reactFlowInstance.fitView();
|
||||
const onNodeDragStop = (event, node) => console.log('drag stop', node);
|
||||
const onElementClick = (event, element) => console.log('click', element);
|
||||
const onLoad = (reactFlowInstance: OnLoadParams) => reactFlowInstance.fitView();
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
|
||||
|
||||
const initialElements = [
|
||||
const initialElements: Elements = [
|
||||
{ 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 } },
|
||||
@@ -31,7 +45,7 @@ const initialElements = [
|
||||
target: '6',
|
||||
label: 'styled label',
|
||||
labelStyle: { fill: 'red', fontWeight: 700 },
|
||||
arrowHeadType: 'arrow',
|
||||
arrowHeadType: ArrowHeadType.Arrow,
|
||||
},
|
||||
{
|
||||
id: 'e5-7',
|
||||
@@ -41,20 +55,27 @@ const initialElements = [
|
||||
labelBgPadding: [8, 4],
|
||||
labelBgBorderRadius: 4,
|
||||
labelBgStyle: { fill: '#FFCC00', color: '#fff', fillOpacity: 0.7 },
|
||||
arrowHeadType: 'arrowclosed',
|
||||
arrowHeadType: ArrowHeadType.ArrowClosed,
|
||||
},
|
||||
{
|
||||
id: 'e5-8',
|
||||
source: '5',
|
||||
target: '8',
|
||||
type: 'custom',
|
||||
data: { text: 'custom edge' },
|
||||
arrowHeadType: ArrowHeadType.ArrowClosed,
|
||||
},
|
||||
{ id: 'e5-8', source: '5', target: '8', type: 'custom', data: { text: 'custom edge' }, arrowHeadType: 'arrowclosed' },
|
||||
];
|
||||
|
||||
const edgeTypes = {
|
||||
const edgeTypes: EdgeTypesType = {
|
||||
custom: CustomEdge,
|
||||
};
|
||||
|
||||
const EdgesFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const [elements, setElements] = useState<Elements>(initialElements);
|
||||
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
@@ -1,44 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import ReactFlow, { removeElements, addEdge, MiniMap, Controls, Background } from 'react-flow-renderer';
|
||||
|
||||
const onLoad = (reactFlowInstance) => console.log('flow loaded:', reactFlowInstance);
|
||||
const onElementClick = (event, element) => console.log('click', element);
|
||||
const onNodeDragStop = (event, node) => console.log('drag stop', node);
|
||||
|
||||
const EmptyFlow = () => {
|
||||
const [elements, setElements] = useState([]);
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const addRandomNode = () => {
|
||||
const nodeId = (elements.length + 1).toString();
|
||||
const newNode = {
|
||||
id: nodeId,
|
||||
data: { label: `Node: ${nodeId}` },
|
||||
position: { x: Math.random() * window.innerWidth, y: Math.random() * window.innerHeight },
|
||||
};
|
||||
setElements((els) => els.concat(newNode));
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
onLoad={onLoad}
|
||||
onElementClick={onElementClick}
|
||||
onElementsRemove={onElementsRemove}
|
||||
onConnect={(p) => onConnect(p)}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
onlyRenderVisibleElements={false}
|
||||
>
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
<Background variant="lines" />
|
||||
|
||||
<button type="button" onClick={addRandomNode} style={{ position: 'absolute', left: 10, top: 10, zIndex: 4 }}>
|
||||
add node
|
||||
</button>
|
||||
</ReactFlow>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmptyFlow;
|
||||
@@ -0,0 +1,60 @@
|
||||
import React, { useState, MouseEvent, CSSProperties } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
removeElements,
|
||||
addEdge,
|
||||
MiniMap,
|
||||
Controls,
|
||||
Background,
|
||||
OnLoadParams,
|
||||
Elements,
|
||||
ElementId,
|
||||
Node,
|
||||
FlowElement,
|
||||
BackgroundVariant,
|
||||
Connection,
|
||||
Edge,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
const onLoad = (reactFlowInstance: OnLoadParams) => console.log('flow loaded:', reactFlowInstance);
|
||||
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
|
||||
const buttonStyle: CSSProperties = { position: 'absolute', left: 10, top: 10, zIndex: 4 };
|
||||
|
||||
const EmptyFlow = () => {
|
||||
const [elements, setElements] = useState<Elements>([]);
|
||||
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
|
||||
const addRandomNode = () => {
|
||||
const nodeId: ElementId = (elements.length + 1).toString();
|
||||
const newNode: Node = {
|
||||
id: nodeId,
|
||||
data: { label: `Node: ${nodeId}` },
|
||||
position: { x: Math.random() * window.innerWidth, y: Math.random() * window.innerHeight },
|
||||
};
|
||||
setElements((els) => els.concat(newNode));
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
onLoad={onLoad}
|
||||
onElementClick={onElementClick}
|
||||
onElementsRemove={onElementsRemove}
|
||||
onConnect={(p) => onConnect(p)}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
onlyRenderVisibleElements={false}
|
||||
>
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
<Background variant={BackgroundVariant.Lines} />
|
||||
|
||||
<button type="button" onClick={addRandomNode} style={buttonStyle}>
|
||||
add node
|
||||
</button>
|
||||
</ReactFlow>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmptyFlow;
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import ReactFlow, { addEdge, MiniMap, Controls } from 'react-flow-renderer';
|
||||
import { useEffect } from 'react';
|
||||
import ReactFlow, { addEdge, MiniMap, Controls, Connection, Edge, Elements } from 'react-flow-renderer';
|
||||
|
||||
const initialElements = [
|
||||
const initialElements: Elements = [
|
||||
{ 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 } },
|
||||
@@ -14,9 +14,9 @@ const initialElements = [
|
||||
];
|
||||
|
||||
const HiddenFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const [isHidden, setIsHidden] = useState(false);
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const [elements, setElements] = useState<Elements>(initialElements);
|
||||
const [isHidden, setIsHidden] = useState<boolean>(false);
|
||||
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
|
||||
|
||||
useEffect(() => {
|
||||
setElements((els) =>
|
||||
@@ -1,8 +1,18 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, MouseEvent, WheelEvent } from 'react';
|
||||
import ReactFlow, {
|
||||
addEdge,
|
||||
MiniMap,
|
||||
Controls,
|
||||
Elements,
|
||||
Node,
|
||||
FlowElement,
|
||||
Connection,
|
||||
Edge,
|
||||
PanOnScrollMode,
|
||||
FlowTransform,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
import ReactFlow, { addEdge, MiniMap, Controls } from 'react-flow-renderer';
|
||||
|
||||
const initialElements = [
|
||||
const initialElements: Elements = [
|
||||
{ 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 } },
|
||||
@@ -11,30 +21,30 @@ const initialElements = [
|
||||
{ id: 'e1-3', source: '1', target: '3' },
|
||||
];
|
||||
|
||||
const onNodeDragStart = (event, node) => console.log('drag start', node);
|
||||
const onNodeDragStop = (event, node) => console.log('drag stop', node);
|
||||
const onElementClick = (event, element) => console.log('click', element);
|
||||
const onPaneClick = (event) => console.log('onPaneClick', event);
|
||||
const onPaneScroll = (event) => console.log('onPaneScroll', event);
|
||||
const onPaneContextMenu = (event) => console.log('onPaneContextMenu', event);
|
||||
const onMoveEnd = (event) => console.log('onMoveEnd', event);
|
||||
const onNodeDragStart = (_: MouseEvent, node: Node) => console.log('drag start', node);
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
|
||||
const onPaneClick = (event: MouseEvent) => console.log('onPaneClick', event);
|
||||
const onPaneScroll = (event?: WheelEvent) => console.log('onPaneScroll', event);
|
||||
const onPaneContextMenu = (event: MouseEvent) => console.log('onPaneContextMenu', event);
|
||||
const onMoveEnd = (flowTranasform?: FlowTransform) => console.log('onMoveEnd', flowTranasform);
|
||||
|
||||
const InteractionFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const [elements, setElements] = useState<Elements>(initialElements);
|
||||
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
|
||||
|
||||
const [isSelectable, setIsSelectable] = useState(false);
|
||||
const [isDraggable, setIsDraggable] = useState(false);
|
||||
const [isConnectable, setIsConnectable] = useState(false);
|
||||
const [zoomOnScroll, setZoomOnScroll] = useState(false);
|
||||
const [zoomOnPinch, setZoomOnPinch] = useState(false);
|
||||
const [panOnScroll, setPanOnScroll] = useState(false);
|
||||
const [panOnScrollMode, setPanOnScrollMode] = useState('free');
|
||||
const [zoomOnDoubleClick, setZoomOnDoubleClick] = useState(false);
|
||||
const [paneMoveable, setPaneMoveable] = useState(true);
|
||||
const [captureZoomClick, setCaptureZoomClick] = useState(false);
|
||||
const [captureZoomScroll, setCaptureZoomScroll] = useState(false);
|
||||
const [captureElementClick, setCaptureElementClick] = useState(false);
|
||||
const [isSelectable, setIsSelectable] = useState<boolean>(false);
|
||||
const [isDraggable, setIsDraggable] = useState<boolean>(false);
|
||||
const [isConnectable, setIsConnectable] = useState<boolean>(false);
|
||||
const [zoomOnScroll, setZoomOnScroll] = useState<boolean>(false);
|
||||
const [zoomOnPinch, setZoomOnPinch] = useState<boolean>(false);
|
||||
const [panOnScroll, setPanOnScroll] = useState<boolean>(false);
|
||||
const [panOnScrollMode, setPanOnScrollMode] = useState<PanOnScrollMode>(PanOnScrollMode.Free);
|
||||
const [zoomOnDoubleClick, setZoomOnDoubleClick] = useState<boolean>(false);
|
||||
const [paneMoveable, setPaneMoveable] = useState<boolean>(true);
|
||||
const [captureZoomClick, setCaptureZoomClick] = useState<boolean>(false);
|
||||
const [captureZoomScroll, setCaptureZoomScroll] = useState<boolean>(false);
|
||||
const [captureElementClick, setCaptureElementClick] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
@@ -139,7 +149,7 @@ const InteractionFlow = () => {
|
||||
<select
|
||||
id="panonscrollmode"
|
||||
value={panOnScrollMode}
|
||||
onChange={(event) => setPanOnScrollMode(event.target.value)}
|
||||
onChange={(event) => setPanOnScrollMode(event.target.value as PanOnScrollMode)}
|
||||
className="react-flow__panonscrollmode"
|
||||
>
|
||||
<option value="free">free</option>
|
||||
@@ -1,5 +1,16 @@
|
||||
import React, { useState } from 'react';
|
||||
import ReactFlow, { ReactFlowProvider, addEdge, removeElements, Controls, isNode } from 'react-flow-renderer';
|
||||
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';
|
||||
@@ -9,17 +20,17 @@ import './layouting.css';
|
||||
const dagreGraph = new dagre.graphlib.Graph();
|
||||
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
||||
|
||||
const nodeExtent = [
|
||||
const nodeExtent: NodeExtent = [
|
||||
[0, 0],
|
||||
[1000, 1000],
|
||||
];
|
||||
|
||||
const LayoutFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
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) => {
|
||||
const onLayout = (direction: string) => {
|
||||
const isHorizontal = direction === 'LR';
|
||||
dagreGraph.setGraph({ rankdir: direction });
|
||||
|
||||
@@ -36,8 +47,8 @@ const LayoutFlow = () => {
|
||||
const layoutedElements = elements.map((el) => {
|
||||
if (isNode(el)) {
|
||||
const nodeWithPosition = dagreGraph.node(el.id);
|
||||
el.targetPosition = isHorizontal ? 'left' : 'top';
|
||||
el.sourcePosition = isHorizontal ? 'right' : 'bottom';
|
||||
el.targetPosition = isHorizontal ? Position.Left : Position.Top;
|
||||
el.sourcePosition = isHorizontal ? Position.Right : Position.Bottom;
|
||||
// we need to pass a slighltiy 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 };
|
||||
+6
-2
@@ -1,6 +1,8 @@
|
||||
const position = { x: 0, y: 0 };
|
||||
import { Elements, XYPosition } from 'react-flow-renderer';
|
||||
|
||||
export default [
|
||||
const position: XYPosition = { x: 0, y: 0 };
|
||||
|
||||
const elements: Elements = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
@@ -65,3 +67,5 @@ export default [
|
||||
{ id: 'e56', source: '5', target: '6', type: 'smoothstep' },
|
||||
{ id: 'e57', source: '5', target: '7', type: 'smoothstep' },
|
||||
];
|
||||
|
||||
export default elements;
|
||||
@@ -1,13 +1,13 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, CSSProperties } from 'react';
|
||||
|
||||
import ReactFlow, { addEdge, isEdge } from 'react-flow-renderer';
|
||||
import ReactFlow, { addEdge, isEdge, OnLoadParams, Elements, Position, Connection, Edge } from 'react-flow-renderer';
|
||||
|
||||
const onLoad = (reactFlowInstance) => reactFlowInstance.fitView();
|
||||
const onLoad = (reactFlowInstance: OnLoadParams) => reactFlowInstance.fitView();
|
||||
|
||||
const initialElements = [
|
||||
const initialElements: Elements = [
|
||||
{
|
||||
id: '1',
|
||||
sourcePosition: 'right',
|
||||
sourcePosition: Position.Right,
|
||||
type: 'input',
|
||||
data: { label: 'Input' },
|
||||
position: { x: 0, y: 80 },
|
||||
@@ -15,17 +15,19 @@ const initialElements = [
|
||||
{
|
||||
id: '2',
|
||||
type: 'output',
|
||||
sourcePosition: 'right',
|
||||
targetPosition: 'left',
|
||||
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(initialElements);
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const [elements, setElements] = useState<Elements>(initialElements);
|
||||
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
|
||||
const changeType = () => {
|
||||
setElements((elms) =>
|
||||
elms.map((el) => {
|
||||
@@ -43,7 +45,7 @@ const NodeTypeChangeFlow = () => {
|
||||
|
||||
return (
|
||||
<ReactFlow elements={elements} onConnect={onConnect} onLoad={onLoad}>
|
||||
<button onClick={changeType} style={{ position: 'absolute', right: 10, top: 30, zIndex: 4 }}>
|
||||
<button onClick={changeType} style={buttonStyle}>
|
||||
change type
|
||||
</button>
|
||||
</ReactFlow>
|
||||
@@ -1,30 +1,47 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, MouseEvent, CSSProperties } from 'react';
|
||||
|
||||
import ReactFlow, { removeElements, addEdge, MiniMap, Controls, Background, isNode } from 'react-flow-renderer';
|
||||
import ReactFlow, {
|
||||
removeElements,
|
||||
addEdge,
|
||||
MiniMap,
|
||||
Controls,
|
||||
Background,
|
||||
isNode,
|
||||
Node,
|
||||
Elements,
|
||||
FlowElement,
|
||||
OnLoadParams,
|
||||
FlowTransform,
|
||||
SnapGrid,
|
||||
ArrowHeadType,
|
||||
Connection,
|
||||
Edge,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
const onNodeDragStart = (event, node) => console.log('drag start', node);
|
||||
const onNodeDrag = (event, node) => console.log('drag', node);
|
||||
const onNodeDragStop = (event, node) => console.log('drag stop', node);
|
||||
const onPaneClick = (event) => console.log('pane click', event);
|
||||
const onPaneScroll = (event) => console.log('pane scroll', event);
|
||||
const onPaneContextMenu = (event) => console.log('pane context menu', event);
|
||||
const onSelectionDrag = (event, nodes) => console.log('selection drag', nodes);
|
||||
const onSelectionDragStart = (event, nodes) => console.log('selection drag start', nodes);
|
||||
const onSelectionDragStop = (event, nodes) => console.log('selection drag stop', nodes);
|
||||
const onSelectionContextMenu = (event, nodes) => {
|
||||
const onNodeDragStart = (_: MouseEvent, node: Node) => console.log('drag start', node);
|
||||
const onNodeDrag = (_: MouseEvent, node: Node) => console.log('drag', node);
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
const onPaneClick = (event: MouseEvent) => console.log('pane click', event);
|
||||
const onPaneScroll = (event?: MouseEvent) => console.log('pane scroll', event);
|
||||
const onPaneContextMenu = (event: MouseEvent) => console.log('pane context menu', event);
|
||||
const onSelectionDrag = (_: MouseEvent, nodes: Node[]) => console.log('selection drag', nodes);
|
||||
const onSelectionDragStart = (_: MouseEvent, nodes: Node[]) => console.log('selection drag start', nodes);
|
||||
const onSelectionDragStop = (_: MouseEvent, nodes: Node[]) => console.log('selection drag stop', nodes);
|
||||
const onSelectionContextMenu = (event: MouseEvent, nodes: Node[]) => {
|
||||
event.preventDefault();
|
||||
console.log('selection context menu', nodes);
|
||||
};
|
||||
const onElementClick = (event, element) => console.log(`${isNode(element) ? 'node' : 'edge'} click:`, element);
|
||||
const onSelectionChange = (elements) => console.log('selection change', elements);
|
||||
const onLoad = (reactFlowInstance) => {
|
||||
const onElementClick = (_: MouseEvent, element: FlowElement) =>
|
||||
console.log(`${isNode(element) ? 'node' : 'edge'} click:`, element);
|
||||
const onSelectionChange = (elements: Elements | null) => console.log('selection change', elements);
|
||||
const onLoad = (reactFlowInstance: OnLoadParams) => {
|
||||
console.log('flow loaded:', reactFlowInstance);
|
||||
reactFlowInstance.fitView();
|
||||
};
|
||||
|
||||
const onMoveEnd = (transform) => console.log('zoom/move end', transform);
|
||||
const onMoveEnd = (transform?: FlowTransform) => console.log('zoom/move end', transform);
|
||||
|
||||
const initialElements = [
|
||||
const initialElements: Elements = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
@@ -101,7 +118,7 @@ const initialElements = [
|
||||
{ id: 'e1-2', source: '1', target: '2', label: 'this is an edge label' },
|
||||
{ id: 'e1-3', source: '1', target: '3' },
|
||||
{ id: 'e3-4', source: '3', target: '4', animated: true, label: 'animated edge' },
|
||||
{ id: 'e4-5', source: '4', target: '5', arrowHeadType: 'arrowclosed', label: 'edge with arrow head' },
|
||||
{ id: 'e4-5', source: '4', target: '5', arrowHeadType: ArrowHeadType.Arrow, label: 'edge with arrow head' },
|
||||
{ id: 'e5-6', source: '5', target: '6', type: 'smoothstep', label: 'smooth step edge' },
|
||||
{
|
||||
id: 'e5-7',
|
||||
@@ -115,13 +132,28 @@ const initialElements = [
|
||||
},
|
||||
];
|
||||
|
||||
const connectionLineStyle = { stroke: '#ddd' };
|
||||
const snapGrid = [16, 16];
|
||||
const connectionLineStyle: CSSProperties = { stroke: '#ddd' };
|
||||
const snapGrid: SnapGrid = [16, 16];
|
||||
|
||||
const nodeStrokeColor = (n: Node): string => {
|
||||
if (n.style?.background) return n.style.background as string;
|
||||
if (n.type === 'input') return '#0041d0';
|
||||
if (n.type === 'output') return '#ff0072';
|
||||
if (n.type === 'default') return '#1a192b';
|
||||
|
||||
return '#eee';
|
||||
};
|
||||
|
||||
const nodeColor = (n: Node): string => {
|
||||
if (n.style?.background) return n.style.background as string;
|
||||
|
||||
return '#fff';
|
||||
};
|
||||
|
||||
const OverviewFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const onElementsRemove = (elementsToRemove: Elements) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
@@ -146,22 +178,7 @@ const OverviewFlow = () => {
|
||||
snapToGrid={true}
|
||||
snapGrid={snapGrid}
|
||||
>
|
||||
<MiniMap
|
||||
nodeStrokeColor={(n) => {
|
||||
if (n.style?.background) return n.style.background;
|
||||
if (n.type === 'input') return '#0041d0';
|
||||
if (n.type === 'output') return '#ff0072';
|
||||
if (n.type === 'default') return '#1a192b';
|
||||
|
||||
return '#eee';
|
||||
}}
|
||||
nodeColor={(n) => {
|
||||
if (n.style?.background) return n.style.background;
|
||||
|
||||
return '#fff';
|
||||
}}
|
||||
nodeBorderRadius={2}
|
||||
/>
|
||||
<MiniMap nodeStrokeColor={nodeStrokeColor} nodeColor={nodeColor} nodeBorderRadius={2} />
|
||||
<Controls />
|
||||
<Background color="#aaa" gap={16} />
|
||||
</ReactFlow>
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { useStoreState, useStoreActions, isNode } from 'react-flow-renderer';
|
||||
import { useStoreState, useStoreActions } from 'react-flow-renderer';
|
||||
|
||||
const Sidebar = () => {
|
||||
const nodes = useStoreState((store) => store.nodes);
|
||||
@@ -1,14 +1,25 @@
|
||||
import React, { useState } from 'react';
|
||||
import ReactFlow, { ReactFlowProvider, addEdge, removeElements, Controls } from 'react-flow-renderer';
|
||||
import React, { useState, MouseEvent } from 'react';
|
||||
import ReactFlow, {
|
||||
ReactFlowProvider,
|
||||
addEdge,
|
||||
removeElements,
|
||||
Controls,
|
||||
OnLoadParams,
|
||||
FlowElement,
|
||||
Connection,
|
||||
Edge,
|
||||
Elements,
|
||||
ConnectionMode,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
import Sidebar from './Sidebar';
|
||||
|
||||
import './provider.css';
|
||||
|
||||
const onElementClick = (event, element) => console.log('click', element);
|
||||
const onLoad = (reactFlowInstance) => console.log('flow loaded:', reactFlowInstance);
|
||||
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
|
||||
const onLoad = (reactFlowInstance: OnLoadParams) => console.log('flow loaded:', reactFlowInstance);
|
||||
|
||||
const initialElements = [
|
||||
const initialElements: Elements = [
|
||||
{ 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 } },
|
||||
@@ -18,9 +29,9 @@ const initialElements = [
|
||||
];
|
||||
|
||||
const ProviderFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
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));
|
||||
|
||||
return (
|
||||
<div className="providerflow">
|
||||
@@ -33,7 +44,7 @@ const ProviderFlow = () => {
|
||||
onConnect={onConnect}
|
||||
onElementsRemove={onElementsRemove}
|
||||
onLoad={onLoad}
|
||||
connectionMode="loose"
|
||||
connectionMode={ConnectionMode.Loose}
|
||||
>
|
||||
<Controls />
|
||||
</ReactFlow>
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { memo, useCallback } from 'react';
|
||||
import { useZoomPanHelper } from 'react-flow-renderer';
|
||||
import React, { memo, useCallback, Dispatch, FC } from 'react';
|
||||
import { useZoomPanHelper, OnLoadParams, Elements, FlowExportObject } from 'react-flow-renderer';
|
||||
import localforage from 'localforage';
|
||||
|
||||
localforage.config({
|
||||
@@ -11,7 +11,12 @@ const flowKey = 'example-flow';
|
||||
|
||||
const getNodeId = () => `randomnode_${+new Date()}`;
|
||||
|
||||
const Controls = memo(({ rfInstance, setElements }) => {
|
||||
type ControlsProps = {
|
||||
rfInstance?: OnLoadParams;
|
||||
setElements: Dispatch<React.SetStateAction<Elements<any>>>;
|
||||
};
|
||||
|
||||
const Controls: FC<ControlsProps> = ({ rfInstance, setElements }) => {
|
||||
const { transform } = useZoomPanHelper();
|
||||
|
||||
const onSave = useCallback(() => {
|
||||
@@ -23,7 +28,7 @@ const Controls = memo(({ rfInstance, setElements }) => {
|
||||
|
||||
const onRestore = useCallback(() => {
|
||||
const restoreFlow = async () => {
|
||||
const flow = await localforage.getItem(flowKey);
|
||||
const flow: FlowExportObject | null = await localforage.getItem(flowKey);
|
||||
|
||||
if (flow) {
|
||||
const [x = 0, y = 0] = flow.position;
|
||||
@@ -51,6 +56,6 @@ const Controls = memo(({ rfInstance, setElements }) => {
|
||||
<button onClick={onAdd}>add node</button>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export default Controls;
|
||||
export default memo(Controls);
|
||||
@@ -1,21 +1,29 @@
|
||||
import React, { memo, useState } from 'react';
|
||||
import ReactFlow, { ReactFlowProvider, removeElements, addEdge } from 'react-flow-renderer';
|
||||
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 = [
|
||||
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(null);
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
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>
|
||||
@@ -1,19 +1,32 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, CSSProperties } from 'react';
|
||||
import ReactFlow, {
|
||||
removeElements,
|
||||
addEdge,
|
||||
MiniMap,
|
||||
isNode,
|
||||
Controls,
|
||||
Background,
|
||||
OnLoadParams,
|
||||
Elements,
|
||||
Connection,
|
||||
Edge,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
import ReactFlow, { removeElements, addEdge, MiniMap, isNode, Controls, Background } from 'react-flow-renderer';
|
||||
import { getElements } from './utils';
|
||||
|
||||
const onLoad = (reactFlowInstance) => {
|
||||
const buttonWrapperStyles: CSSProperties = { position: 'absolute', right: 10, top: 10, zIndex: 4 };
|
||||
|
||||
const onLoad = (reactFlowInstance: OnLoadParams) => {
|
||||
reactFlowInstance.fitView();
|
||||
console.log(reactFlowInstance.getElements());
|
||||
};
|
||||
|
||||
const initialElements = getElements(30, 30);
|
||||
const initialElements: Elements = getElements(30, 30);
|
||||
|
||||
const StressFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
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 updatePos = () => {
|
||||
setElements((elms) => {
|
||||
@@ -44,7 +57,7 @@ const StressFlow = () => {
|
||||
<Controls />
|
||||
<Background />
|
||||
|
||||
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
|
||||
<div style={buttonWrapperStyles}>
|
||||
<button onClick={updatePos} style={{ marginRight: 5 }}>
|
||||
change pos
|
||||
</button>
|
||||
@@ -1,4 +1,6 @@
|
||||
export function getElements(xElements = 10, yElements = 10) {
|
||||
import { Elements } from 'react-flow-renderer';
|
||||
|
||||
export function getElements(xElements: number = 10, yElements: number = 10): Elements {
|
||||
const initialElements = [];
|
||||
let nodeId = 1;
|
||||
let recentNodeId = null;
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, MouseEvent } from 'react';
|
||||
|
||||
import ReactFlow, { removeElements, addEdge } from 'react-flow-renderer';
|
||||
import ReactFlow, { removeElements, addEdge, Node, FlowElement, Elements, Connection, Edge } from 'react-flow-renderer';
|
||||
|
||||
const onNodeDragStop = (event, node) => console.log('drag stop', node);
|
||||
const onElementClick = (event, element) => console.log('click', element);
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
|
||||
|
||||
const elementsA = [
|
||||
const elementsA: Elements = [
|
||||
{ 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' },
|
||||
@@ -14,7 +14,7 @@ const elementsA = [
|
||||
{ id: 'e1-3', source: '1a', target: '3a' },
|
||||
];
|
||||
|
||||
const elementsB = [
|
||||
const elementsB: Elements = [
|
||||
{ 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' },
|
||||
@@ -28,9 +28,9 @@ const elementsB = [
|
||||
];
|
||||
|
||||
const BasicFlow = () => {
|
||||
const [elements, setElements] = useState(elementsA);
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
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));
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
@@ -39,7 +39,6 @@ const BasicFlow = () => {
|
||||
onElementsRemove={onElementsRemove}
|
||||
onConnect={onConnect}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
className="react-flow-basic-example"
|
||||
>
|
||||
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
|
||||
<button onClick={() => setElements(elementsA)} style={{ marginRight: 5 }}>
|
||||
@@ -1,7 +1,15 @@
|
||||
import React, { useState } from 'react';
|
||||
import ReactFlow, { Controls, updateEdge, addEdge } from 'react-flow-renderer';
|
||||
import ReactFlow, {
|
||||
Controls,
|
||||
updateEdge,
|
||||
addEdge,
|
||||
Elements,
|
||||
OnLoadParams,
|
||||
Connection,
|
||||
Edge,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
const initialElements = [
|
||||
const initialElements: Elements = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
@@ -40,12 +48,13 @@ const initialElements = [
|
||||
{ id: 'e1-2', source: '1', target: '2', label: 'This is a draggable edge' },
|
||||
];
|
||||
|
||||
const onLoad = (reactFlowInstance) => reactFlowInstance.fitView();
|
||||
const onLoad = (reactFlowInstance: OnLoadParams) => reactFlowInstance.fitView();
|
||||
|
||||
const UpdatableEdge = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onEdgeUpdate = (oldEdge, newConnection) => setElements((els) => updateEdge(oldEdge, newConnection, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const [elements, setElements] = useState<Elements>(initialElements);
|
||||
const onEdgeUpdate = (oldEdge: Edge, newConnection: Connection) =>
|
||||
setElements((els) => updateEdge(oldEdge, newConnection, els));
|
||||
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
|
||||
|
||||
return (
|
||||
<ReactFlow elements={elements} onLoad={onLoad} snapToGrid={true} onEdgeUpdate={onEdgeUpdate} onConnect={onConnect}>
|
||||
@@ -1,19 +1,19 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import ReactFlow from 'react-flow-renderer';
|
||||
import ReactFlow, { Elements } from 'react-flow-renderer';
|
||||
|
||||
import './updatenode.css';
|
||||
|
||||
const initialElements = [
|
||||
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);
|
||||
const [elements, setElements] = useState<Elements>(initialElements);
|
||||
const [nodeName, setNodeName] = useState<string>('Node 1');
|
||||
const [nodeBg, setNodeBg] = useState<string>('#eee');
|
||||
const [nodeHidden, setNodeHidden] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
setElements((els) =>
|
||||
@@ -7,9 +7,13 @@ import ReactFlow, {
|
||||
MiniMap,
|
||||
useZoomPanHelper,
|
||||
ReactFlowProvider,
|
||||
Elements,
|
||||
ElementId,
|
||||
Connection,
|
||||
Edge,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
const initialElements = [
|
||||
const initialElements: Elements = [
|
||||
{ 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' },
|
||||
@@ -19,12 +23,12 @@ const initialElements = [
|
||||
];
|
||||
|
||||
let id = 5;
|
||||
const getId = () => `${id++}`;
|
||||
const getId = (): ElementId => `${id++}`;
|
||||
|
||||
const UseZoomPanHelperFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
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 { project } = useZoomPanHelper();
|
||||
|
||||
const onPaneClick = useCallback(
|
||||
@@ -53,8 +57,10 @@ const UseZoomPanHelperFlow = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default () => (
|
||||
const WrappedFlow = () => (
|
||||
<ReactFlowProvider>
|
||||
<UseZoomPanHelperFlow />
|
||||
</ReactFlowProvider>
|
||||
);
|
||||
|
||||
export default WrappedFlow;
|
||||
@@ -1,62 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import ReactFlow, { addEdge, Handle } from 'react-flow-renderer';
|
||||
|
||||
import './validation.css';
|
||||
|
||||
const initialElements = [
|
||||
{ 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 onLoad = (reactFlowInstance) => reactFlowInstance.fitView();
|
||||
const isValidConnection = (connection) => connection.target === 'B';
|
||||
const onConnectStart = (event, { nodeId, handleType }) => console.log('on connect start', { nodeId, handleType });
|
||||
const onConnectStop = (event) => console.log('on connect stop', event);
|
||||
const onConnectEnd = (event) => console.log('on connect end', event);
|
||||
|
||||
const CustomInput = () => (
|
||||
<>
|
||||
<div>Only connectable with B</div>
|
||||
<Handle type="source" position="right" isValidConnection={isValidConnection} />
|
||||
</>
|
||||
);
|
||||
|
||||
const CustomNode = ({ id }) => (
|
||||
<>
|
||||
<Handle type="target" position="left" isValidConnection={isValidConnection} />
|
||||
<div>{id}</div>
|
||||
<Handle type="source" position="right" isValidConnection={isValidConnection} />
|
||||
</>
|
||||
);
|
||||
|
||||
const nodeTypes = {
|
||||
custominput: CustomInput,
|
||||
customnode: CustomNode,
|
||||
};
|
||||
|
||||
const HorizontalFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onConnect = (params) => {
|
||||
console.log('on connect', params);
|
||||
setElements((els) => addEdge(params, els));
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
onConnect={onConnect}
|
||||
selectNodesOnDrag={false}
|
||||
onLoad={onLoad}
|
||||
className="validationflow"
|
||||
nodeTypes={nodeTypes}
|
||||
onConnectStart={onConnectStart}
|
||||
onConnectStop={onConnectStop}
|
||||
onConnectEnd={onConnectEnd}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default HorizontalFlow;
|
||||
@@ -0,0 +1,73 @@
|
||||
import React, { useState, MouseEvent as ReactMouseEvent, FC } from 'react';
|
||||
import ReactFlow, {
|
||||
addEdge,
|
||||
Handle,
|
||||
OnLoadParams,
|
||||
Connection,
|
||||
Position,
|
||||
Elements,
|
||||
Edge,
|
||||
OnConnectStartParams,
|
||||
NodeProps,
|
||||
NodeTypesType,
|
||||
} 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 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 });
|
||||
const onConnectStop = (event: MouseEvent) => console.log('on connect stop', event);
|
||||
const onConnectEnd = (event: MouseEvent) => console.log('on connect end', event);
|
||||
|
||||
const CustomInput: FC<NodeProps> = () => (
|
||||
<>
|
||||
<div>Only connectable with B</div>
|
||||
<Handle type="source" position={Position.Right} isValidConnection={isValidConnection} />
|
||||
</>
|
||||
);
|
||||
|
||||
const CustomNode: FC<NodeProps> = ({ id }) => (
|
||||
<>
|
||||
<Handle type="target" position={Position.Left} isValidConnection={isValidConnection} />
|
||||
<div>{id}</div>
|
||||
<Handle type="source" position={Position.Right} isValidConnection={isValidConnection} />
|
||||
</>
|
||||
);
|
||||
|
||||
const nodeTypes: NodeTypesType = {
|
||||
custominput: CustomInput,
|
||||
customnode: CustomNode,
|
||||
};
|
||||
|
||||
const HorizontalFlow = () => {
|
||||
const [elements, setElements] = useState<Elements>(initialElements);
|
||||
const onConnect = (params: Connection | Edge) => {
|
||||
console.log('on connect', params);
|
||||
setElements((els) => addEdge(params, els));
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
onConnect={onConnect}
|
||||
selectNodesOnDrag={false}
|
||||
onLoad={onLoad}
|
||||
className="validationflow"
|
||||
nodeTypes={nodeTypes}
|
||||
onConnectStart={onConnectStart}
|
||||
onConnectStop={onConnectStop}
|
||||
onConnectEnd={onConnectEnd}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default HorizontalFlow;
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { ChangeEvent } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter as Router, Route, Switch, withRouter } from 'react-router-dom';
|
||||
|
||||
@@ -109,7 +109,7 @@ const routes = [
|
||||
];
|
||||
|
||||
const Header = withRouter(({ history, location }) => {
|
||||
const onChange = (event) => history.push(event.target.value);
|
||||
const onChange = (event: ChangeEvent<HTMLSelectElement>) => history.push(event.target.value);
|
||||
|
||||
return (
|
||||
<header>
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
/// <reference types="react-scripts" />
|
||||
Reference in New Issue
Block a user