chore(examples): add examples

This commit is contained in:
moklick
2021-12-22 23:53:05 +01:00
parent c1e5f90c7c
commit 7a85bb9666
13 changed files with 141 additions and 187 deletions
@@ -0,0 +1,19 @@
import React, { FC } from 'react';
import { ConnectionLineComponentProps } from 'react-flow-renderer';
const ConnectionLine: FC<ConnectionLineComponentProps> = ({ sourceX, sourceY, targetX, targetY }) => {
return (
<g>
<path
fill="none"
stroke="#222"
strokeWidth={1.5}
className="animated"
d={`M${sourceX},${sourceY} C ${sourceX} ${targetY} ${sourceX} ${targetY} ${targetX},${targetY}`}
/>
<circle cx={targetX} cy={targetY} fill="#fff" r={3} stroke="#222" strokeWidth={1.5} />
</g>
);
};
export default ConnectionLine;
@@ -0,0 +1,36 @@
import ReactFlow, {
Node,
addEdge,
Background,
BackgroundVariant,
Connection,
Edge,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
import ConnectionLine from './ConnectionLine';
const initialNodes: Node[] = [{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } }];
const initialEdges: Edge[] = [];
const ConnectionLineFlow = () => {
const [nodes, , onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
return (
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
connectionLineComponent={ConnectionLine}
onConnect={onConnect}
>
<Background variant={BackgroundVariant.Lines} />
</ReactFlow>
);
};
export default ConnectionLineFlow;
+3 -3
View File
@@ -33,8 +33,7 @@ const onNodeClick = (_: MouseEvent, node: Node) => console.log('node click:', no
const onSelectionChange = ({ nodes, edges }: OnSelectionChangeParams) => console.log('selection change', nodes, edges);
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => {
console.log('flow loaded:', reactFlowInstance);
reactFlowInstance.fitView();
console.log('pane ready:', reactFlowInstance);
};
const onMoveStart = (transform?: FlowTransform) => console.log('zoom/move start', transform);
@@ -158,7 +157,7 @@ const nodeColor = (n: Node): string => {
};
const OverviewFlow = () => {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [nodes, , onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
@@ -193,6 +192,7 @@ const OverviewFlow = () => {
onEdgeMouseMove={onEdgeMouseMove}
onEdgeMouseLeave={onEdgeMouseLeave}
onEdgeDoubleClick={onEdgeDoubleClick}
fitViewOnInit
>
<MiniMap nodeStrokeColor={nodeStrokeColor} nodeColor={nodeColor} nodeBorderRadius={2} />
<Controls />
+36
View File
@@ -0,0 +1,36 @@
import { useStore, useStoreApi } from 'react-flow-renderer';
const Sidebar = () => {
const store = useStoreApi();
const nodeInternals = useStore((store) => store.nodeInternals);
const transform = useStore((store) => store.transform);
const selectAll = () => {
nodeInternals.forEach((node) => (node.selected = true));
store.setState({ nodeInternals: new Map(nodeInternals) });
};
return (
<aside>
<div className="description">
This is an example of how you can access the internal state outside of the ReactFlow component.
</div>
<div className="title">Zoom & pan transform</div>
<div className="transform">
[{transform[0].toFixed(2)}, {transform[1].toFixed(2)}, {transform[2].toFixed(2)}]
</div>
<div className="title">Nodes</div>
{Array.from(nodeInternals).map(([, node]) => (
<div key={node.id}>
Node {node.id} - x: {node.position.x.toFixed(2)}, y: {node.position.y.toFixed(2)}
</div>
))}
<div className="selectall">
<button onClick={selectAll}>select all nodes</button>
</div>
</aside>
);
};
export default Sidebar;
+62
View File
@@ -0,0 +1,62 @@
import { MouseEvent } from 'react';
import ReactFlow, {
ReactFlowProvider,
addEdge,
Node,
Controls,
Connection,
Edge,
ConnectionMode,
useNodesState,
useEdgesState,
ReactFlowInstance,
} from 'react-flow-renderer';
import Sidebar from './Sidebar';
import './provider.css';
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => console.log('pane ready:', reactFlowInstance);
const initialNodes: Node[] = [
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } },
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 } },
{ id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 } },
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 } },
];
const initialEdges: Edge[] = [
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e1-3', source: '1', target: '3' },
];
const ProviderFlow = () => {
const [nodes, , onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: Edge | Connection) => setEdges((els) => addEdge(params, els));
return (
<div className="providerflow">
<ReactFlowProvider>
<Sidebar />
<div className="reactflow-wrapper">
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onNodeClick={onNodeClick}
onConnect={onConnect}
onPaneReady={onPaneReady}
connectionMode={ConnectionMode.Loose}
>
<Controls />
</ReactFlow>
</div>
</ReactFlowProvider>
</div>
);
};
export default ProviderFlow;
+45
View File
@@ -0,0 +1,45 @@
.providerflow {
flex-direction: column;
display: flex;
height: 100%;
}
.providerflow aside {
border-right: 1px solid #eee;
padding: 15px 10px;
font-size: 12px;
background: #fcfcfc;
}
.providerflow aside .description {
margin-bottom: 10px;
}
.providerflow aside .title {
font-weight: 700;
margin-bottom: 5px;
}
.providerflow aside .transform {
margin-bottom: 20px;
}
.providerflow .reactflow-wrapper {
flex-grow: 1;
height: 100%;
}
.providerflow .selectall {
margin-top: 10px;
}
@media screen and (min-width: 768px) {
.providerflow {
flex-direction: row;
}
.providerflow aside {
width: 20%;
max-width: 250px;
}
}
+19
View File
@@ -0,0 +1,19 @@
import React, { memo, FC, CSSProperties } from 'react';
import { Handle, Position, NodeProps } from 'react-flow-renderer';
const nodeStyles: CSSProperties = { padding: '10px 15px', border: '1px solid #ddd' };
const CustomNode: FC<NodeProps> = ({ id }) => {
return (
<div style={nodeStyles}>
<div>node {id}</div>
<Handle type="source" id="left" position={Position.Left} />
<Handle type="source" id="right" position={Position.Right} />
<Handle type="source" id="top" position={Position.Top} />
<Handle type="source" id="bottom" position={Position.Bottom} />
</div>
);
};
export default memo(CustomNode);
+226
View File
@@ -0,0 +1,226 @@
import { useCallback } from 'react';
import ReactFlow, {
NodeTypesType,
addEdge,
useZoomPanHelper,
ReactFlowProvider,
Node,
Connection,
Edge,
ConnectionLineType,
ConnectionMode,
updateEdge,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
import CustomNode from './CustomNode';
const initialNodes: Node[] = [
{
id: '00',
type: 'custom',
position: { x: 300, y: 250 },
data: null,
},
{
id: '01',
type: 'custom',
position: { x: 100, y: 50 },
data: null,
},
{
id: '02',
type: 'custom',
position: { x: 500, y: 50 },
data: null,
},
{
id: '03',
type: 'custom',
position: { x: 500, y: 500 },
data: null,
},
{
id: '04',
type: 'custom',
position: { x: 100, y: 500 },
data: null,
},
{
id: '10',
type: 'custom',
position: { x: 300, y: 5 },
data: null,
},
{
id: '20',
type: 'custom',
position: { x: 600, y: 250 },
data: null,
},
{
id: '30',
type: 'custom',
position: { x: 300, y: 600 },
data: null,
},
{
id: '40',
type: 'custom',
position: { x: 5, y: 250 },
data: null,
},
];
const initialEdges: Edge[] = [
{
id: 'e0-1a',
source: '00',
target: '01',
sourceHandle: 'left',
targetHandle: 'bottom',
type: 'default',
},
{
id: 'e0-1b',
source: '00',
target: '01',
sourceHandle: 'top',
targetHandle: 'right',
type: 'default',
},
{
id: 'e0-2a',
source: '00',
target: '02',
sourceHandle: 'top',
targetHandle: 'left',
type: 'default',
},
{
id: 'e0-2b',
source: '00',
target: '02',
sourceHandle: 'right',
targetHandle: 'bottom',
type: 'default',
},
{
id: 'e0-3a',
source: '00',
target: '03',
sourceHandle: 'right',
targetHandle: 'top',
type: 'default',
},
{
id: 'e0-3b',
source: '00',
target: '03',
sourceHandle: 'bottom',
targetHandle: 'left',
type: 'default',
},
{
id: 'e0-4a',
source: '00',
target: '04',
sourceHandle: 'bottom',
targetHandle: 'right',
type: 'default',
},
{
id: 'e0-4b',
source: '00',
target: '04',
sourceHandle: 'left',
targetHandle: 'top',
type: 'default',
},
{
id: 'e0-10',
source: '00',
target: '10',
sourceHandle: 'top',
targetHandle: 'bottom',
type: 'default',
},
{
id: 'e0-20',
source: '00',
target: '20',
sourceHandle: 'right',
targetHandle: 'left',
type: 'default',
},
{
id: 'e0-30',
source: '00',
target: '30',
sourceHandle: 'bottom',
targetHandle: 'top',
type: 'default',
},
{
id: 'e0-40',
source: '00',
target: '40',
sourceHandle: 'left',
targetHandle: 'right',
type: 'default',
},
];
const nodeTypes: NodeTypesType = {
custom: CustomNode,
};
let id = 4;
const getId = () => `${id++}`;
const UpdateNodeInternalsFlow = () => {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: Edge | Connection) => setEdges((els) => addEdge(params, els));
const { project } = useZoomPanHelper();
const onEdgeUpdate = (oldEdge: Edge, newConnection: Connection) =>
setEdges((els) => updateEdge(oldEdge, newConnection, els));
const onPaneClick = useCallback(
(evt) =>
setNodes((nds) =>
nds.concat({
id: getId(),
position: project({ x: evt.clientX, y: evt.clientY - 40 }),
type: 'custom',
data: null,
})
),
[project]
);
return (
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
nodeTypes={nodeTypes}
onConnect={onConnect}
onPaneClick={onPaneClick}
connectionLineType={ConnectionLineType.Bezier}
connectionMode={ConnectionMode.Loose}
onEdgeUpdate={onEdgeUpdate}
/>
);
};
const WrappedFlow = () => (
<ReactFlowProvider>
<UpdateNodeInternalsFlow />
</ReactFlowProvider>
);
export default WrappedFlow;
+89
View File
@@ -0,0 +1,89 @@
import { useCallback } from 'react';
import ReactFlow, {
Node,
addEdge,
Background,
MiniMap,
useZoomPanHelper,
ReactFlowProvider,
Connection,
Edge,
useNodesState,
useEdgesState,
} from 'react-flow-renderer';
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' },
];
let id = 5;
const getId = () => `${id++}`;
const UseZoomPanHelperFlow = () => {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds));
const { project, setCenter, zoomIn, zoomOut } = useZoomPanHelper();
const onPaneClick = useCallback(
(evt) => {
const projectedPosition = project({ x: evt.clientX, y: evt.clientY - 40 });
setNodes((nds) =>
nds.concat({
id: getId(),
position: projectedPosition,
data: {
label: `${projectedPosition.x}-${projectedPosition.y}`,
},
})
);
},
[project]
);
const onNodeClick = useCallback(
(_, element) => {
const { x, y } = element.position;
setCenter(x, y, { zoom: 1 });
},
[setCenter]
);
return (
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onNodeClick={onNodeClick}
onConnect={onConnect}
onPaneClick={onPaneClick}
>
<div style={{ position: 'absolute', left: 0, top: 0, zIndex: 100 }}>
<button onClick={() => zoomIn({ duration: 1200 })}>zoomIn</button>
<button onClick={() => zoomOut({ duration: 0 })}>zoomOut</button>
</div>
<Background />
<MiniMap />
</ReactFlow>
);
};
const WrappedFlow = () => (
<ReactFlowProvider>
<UseZoomPanHelperFlow />
</ReactFlowProvider>
);
export default WrappedFlow;
+20
View File
@@ -17,6 +17,10 @@ import Subflow from './Subflow';
import Interaction from './Interaction';
import Empty from './Empty';
import DragHandle from './DragHandle';
import Undirectional from './Undirectional';
import Provider from './Provider';
import CustomConnectionLine from './CustomConnectionLine';
import UseZoomPanHelper from './UseZoomPanHelper';
import './index.css';
@@ -81,6 +85,22 @@ const routes = [
path: '/draghandle',
component: DragHandle,
},
{
path: '/undirectional',
component: Undirectional,
},
{
path: '/provider',
component: Provider,
},
{
path: '/custom-connectionline',
component: CustomConnectionLine,
},
{
path: '/usezoompanhelper',
component: UseZoomPanHelper,
},
];
const Header = withRouter(({ history, location }) => {