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
@@ -1,19 +0,0 @@
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;
@@ -1,33 +0,0 @@
import React, { useState } from 'react';
import ReactFlow, {
removeElements,
addEdge,
Background,
BackgroundVariant,
Elements,
Connection,
Edge,
} from 'react-flow-renderer';
import ConnectionLine from './ConnectionLine';
const initialElements: Elements = [{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } }];
const ConnectionLineFlow = () => {
const [elements, setElements] = useState<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;
-36
View File
@@ -1,36 +0,0 @@
import React from 'react';
import { useStoreState, useStoreActions } from 'react-flow-renderer';
const Sidebar = () => {
const nodes = useStoreState((store) => store.nodes);
const transform = useStoreState((store) => store.transform);
const setSelectedElements = useStoreActions((actions) => actions.setSelectedElements);
const selectAll = () => {
setSelectedElements(nodes.map((node) => ({ id: node.id, type: node.type })));
};
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>
{nodes.map((node) => (
<div key={node.id}>
Node {node.id} - x: {node.__rf.position.x.toFixed(2)}, y: {node.__rf.position.y.toFixed(2)}
</div>
))}
<div className="selectall">
<button onClick={selectAll}>select all nodes</button>
</div>
</aside>
);
};
export default Sidebar;
-57
View File
@@ -1,57 +0,0 @@
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 = (_: MouseEvent, element: FlowElement) => console.log('click', element);
const onLoad = (reactFlowInstance: OnLoadParams) => console.log('flow loaded:', reactFlowInstance);
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 } },
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 } },
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e1-3', source: '1', target: '3' },
];
const ProviderFlow = () => {
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">
<ReactFlowProvider>
<Sidebar />
<div className="reactflow-wrapper">
<ReactFlow
elements={elements}
onElementClick={onElementClick}
onConnect={onConnect}
onElementsRemove={onElementsRemove}
onLoad={onLoad}
connectionMode={ConnectionMode.Loose}
>
<Controls />
</ReactFlow>
</div>
</ReactFlowProvider>
</div>
);
};
export default ProviderFlow;
-45
View File
@@ -1,45 +0,0 @@
.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;
}
}
@@ -1,19 +0,0 @@
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);
-207
View File
@@ -1,207 +0,0 @@
import React, { useState, useCallback } from 'react';
import ReactFlow, {
NodeTypesType,
addEdge,
useZoomPanHelper,
ReactFlowProvider,
Elements,
Connection,
Edge,
ElementId,
ConnectionLineType,
ConnectionMode,
updateEdge,
} from 'react-flow-renderer';
import CustomNode from './CustomNode';
const initialElements: Elements = [
{
id: '00',
type: 'custom',
position: { x: 300, y: 250 },
},
{
id: '01',
type: 'custom',
position: { x: 100, y: 50 },
},
{
id: '02',
type: 'custom',
position: { x: 500, y: 50 },
},
{
id: '03',
type: 'custom',
position: { x: 500, y: 500 },
},
{
id: '04',
type: 'custom',
position: { x: 100, y: 500 },
},
{
id: '10',
type: 'custom',
position: { x: 300, y: 5 },
},
{
id: '20',
type: 'custom',
position: { x: 600, y: 250 },
},
{
id: '30',
type: 'custom',
position: { x: 300, y: 600 },
},
{
id: '40',
type: 'custom',
position: { x: 5, y: 250 },
},
{
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 = (): ElementId => `${id++}`;
const UpdateNodeInternalsFlow = () => {
const [elements, setElements] = useState<Elements>(initialElements);
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge({ ...params, type: 'default' }, els));
const { project } = useZoomPanHelper();
const onEdgeUpdate = (oldEdge: Edge, newConnection: Connection) =>
setElements((els) => updateEdge(oldEdge, newConnection, els));
const onPaneClick = useCallback(
(evt) =>
setElements((els) =>
els.concat({
id: getId(),
position: project({ x: evt.clientX, y: evt.clientY - 40 }),
type: 'custom',
})
),
[project]
);
return (
<ReactFlow
elements={elements}
nodeTypes={nodeTypes}
onConnect={onConnect}
onPaneClick={onPaneClick}
connectionLineType={ConnectionLineType.Bezier}
connectionMode={ConnectionMode.Loose}
onEdgeUpdate={onEdgeUpdate}
/>
);
};
const WrappedFlow = () => (
<ReactFlowProvider>
<UpdateNodeInternalsFlow />
</ReactFlowProvider>
);
export default WrappedFlow;
-78
View File
@@ -1,78 +0,0 @@
import React, { useEffect, useState } from 'react';
import ReactFlow, { Elements } from 'react-flow-renderer';
import './updatenode.css';
const initialElements: Elements = [
{ id: '1', data: { label: '-' }, position: { x: 100, y: 100 } },
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 200 } },
{ id: 'e1-2', source: '1', target: '2' },
];
const UpdateNode = () => {
const [elements, setElements] = useState<Elements>(initialElements);
const [nodeName, setNodeName] = useState<string>('Node 1');
const [nodeBg, setNodeBg] = useState<string>('#eee');
const [nodeHidden, setNodeHidden] = useState<boolean>(false);
useEffect(() => {
setElements((els) =>
els.map((el) => {
if (el.id === '1') {
// it's important that you create a new object here in order to notify react flow about the change
el.data = {
...el.data,
label: nodeName,
};
}
return el;
})
);
}, [nodeName, setElements]);
useEffect(() => {
setElements((els) =>
els.map((el) => {
if (el.id === '1') {
// it's important that you create a new object here in order to notify react flow about the change
el.style = { ...el.style, backgroundColor: nodeBg };
}
return el;
})
);
}, [nodeBg, setElements]);
useEffect(() => {
setElements((els) =>
els.map((el) => {
if (el.id === '1' || el.id === 'e1-2') {
// when you update a simple type you can just update the value
el.isHidden = nodeHidden;
}
return el;
})
);
}, [nodeHidden, setElements]);
return (
<ReactFlow elements={elements} defaultZoom={1.5} minZoom={0.2} maxZoom={4}>
<div className="updatenode__controls">
<label>label:</label>
<input value={nodeName} onChange={(evt) => setNodeName(evt.target.value)} />
<label className="updatenode__bglabel">background:</label>
<input value={nodeBg} onChange={(evt) => setNodeBg(evt.target.value)} />
<div className="updatenode__checkboxwrapper">
<label>hidden:</label>
<input type="checkbox" checked={nodeHidden} onChange={(evt) => setNodeHidden(evt.target.checked)} />
</div>
</div>
</ReactFlow>
);
};
export default UpdateNode;
@@ -1,21 +0,0 @@
.updatenode__controls {
position: absolute;
right: 10px;
top: 10px;
z-index: 4;
font-size: 12px;
}
.updatenode__controls label {
display: block;
}
.updatenode__bglabel {
margin-top: 10px;
}
.updatenode__checkboxwrapper {
margin-top: 10px;
display: flex;
align-items: center;
}
@@ -1,83 +0,0 @@
import React, { useState, useCallback } from 'react';
import ReactFlow, {
removeElements,
addEdge,
Background,
MiniMap,
useZoomPanHelper,
ReactFlowProvider,
Elements,
ElementId,
Connection,
Edge,
} from 'react-flow-renderer';
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' },
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 }, className: 'light' },
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e1-3', source: '1', target: '3' },
];
let id = 5;
const getId = (): ElementId => `${id++}`;
const UseZoomPanHelperFlow = () => {
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, setCenter, zoomIn, zoomOut } = useZoomPanHelper();
const onPaneClick = useCallback(
(evt) => {
const projectedPosition = project({ x: evt.clientX, y: evt.clientY - 40 });
setElements((els) =>
els.concat({
id: getId(),
position: projectedPosition,
data: {
label: `${projectedPosition.x}-${projectedPosition.y}`,
},
})
);
},
[project]
);
const onElementClick = useCallback(
(_, element) => {
const { x, y } = element.position;
setCenter(x, y, 1);
},
[setCenter]
);
return (
<ReactFlow
elements={elements}
onElementClick={onElementClick}
onElementsRemove={onElementsRemove}
onConnect={onConnect}
onPaneClick={onPaneClick}
>
<div style={{ position: 'absolute', left: 0, top: 0, zIndex: 100 }}>
<button onClick={() => zoomIn(1200)}>zoomIn</button>
<button onClick={() => zoomOut(0)}>zoomOut</button>
</div>
<Background />
<MiniMap />
</ReactFlow>
);
};
const WrappedFlow = () => (
<ReactFlowProvider>
<UseZoomPanHelperFlow />
</ReactFlowProvider>
);
export default WrappedFlow;