test(examples): use new api for test examples
This commit is contained in:
@@ -127,29 +127,29 @@ describe('Basic Flow Rendering', () => {
|
||||
});
|
||||
|
||||
it('drags the pane', () => {
|
||||
const styleBeforeDrag = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleBeforeDrag = Cypress.$('.react-flow__viewport').css('transform');
|
||||
|
||||
// for d3 we have to pass the window to the event
|
||||
// https://github.com/cypress-io/cypress/issues/3441
|
||||
cy.window().then((win) => {
|
||||
cy.get('.react-flow__renderer')
|
||||
cy.get('.react-flow__pane')
|
||||
.trigger('mousedown', 'topLeft', { which: 1, view: win })
|
||||
.trigger('mousemove', 'bottomLeft')
|
||||
.trigger('mouseup', { force: true, view: win })
|
||||
.then(() => {
|
||||
const styleAfterDrag = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleAfterDrag = Cypress.$('.react-flow__viewport').css('transform');
|
||||
expect(styleBeforeDrag).to.not.equal(styleAfterDrag);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('zooms the pane', () => {
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
|
||||
cy.get('.react-flow__renderer')
|
||||
cy.get('.react-flow__pane')
|
||||
.trigger('wheel', 'topLeft', { deltaY: -200 })
|
||||
.then(() => {
|
||||
const styleAfterZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleAfterZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
expect(styleBeforeZoom).to.not.equal(styleAfterZoom);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,30 +8,30 @@ describe('Controls Testing', () => {
|
||||
});
|
||||
|
||||
it('zooms in', () => {
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
|
||||
cy.get('.react-flow__controls-zoomin')
|
||||
.click()
|
||||
.then(() => {
|
||||
const styleAfterZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleAfterZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
expect(styleBeforeZoom).to.not.equal(styleAfterZoom);
|
||||
});
|
||||
});
|
||||
|
||||
it('zooms out', () => {
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
|
||||
cy.get('.react-flow__controls-zoomout')
|
||||
.click()
|
||||
.then(() => {
|
||||
const styleAfterZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleAfterZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
expect(styleBeforeZoom).to.not.equal(styleAfterZoom);
|
||||
});
|
||||
});
|
||||
|
||||
// view is already fitted so we drag the pane to un-fit it
|
||||
it('drags the pane', () => {
|
||||
const styleBeforeDrag = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleBeforeDrag = Cypress.$('.react-flow__viewport').css('transform');
|
||||
|
||||
// for d3 we have to pass the window to the event
|
||||
// https://github.com/cypress-io/cypress/issues/3441
|
||||
@@ -41,19 +41,19 @@ describe('Controls Testing', () => {
|
||||
.trigger('mousemove', 'bottomLeft')
|
||||
.trigger('mouseup', { force: true, view: win })
|
||||
.then(() => {
|
||||
const styleAfterDrag = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleAfterDrag = Cypress.$('.react-flow__viewport').css('transform');
|
||||
expect(styleBeforeDrag).to.not.equal(styleAfterDrag);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('fits view', () => {
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
|
||||
cy.get('.react-flow__controls-fitview')
|
||||
.click()
|
||||
.then(() => {
|
||||
const styleAfterZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleAfterZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
expect(styleBeforeZoom).to.not.equal(styleAfterZoom);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,11 +20,6 @@ describe('Empty Flow Rendering', () => {
|
||||
cy.get('body').type('{shift}', { release: true });
|
||||
});
|
||||
|
||||
it('renders an empty mini map', () => {
|
||||
cy.get('.react-flow__minimap');
|
||||
cy.get('.react-flow__minimap-node').should('not.exist');
|
||||
});
|
||||
|
||||
it('adds two nodes', () => {
|
||||
cy.contains('add node').click();
|
||||
cy.contains('add node').click();
|
||||
@@ -41,9 +36,4 @@ describe('Empty Flow Rendering', () => {
|
||||
|
||||
cy.get('.react-flow__edge').should('have.length', 1);
|
||||
});
|
||||
|
||||
it('renders mini map with two nodes', () => {
|
||||
cy.get('.react-flow__minimap');
|
||||
cy.get('.react-flow__minimap-node').should('have.length', 2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,41 +27,41 @@ describe('Graph Utils Testing', () => {
|
||||
});
|
||||
|
||||
it('tests getOutgoers function', () => {
|
||||
const outgoers = getOutgoers(nodes[0], elements);
|
||||
const outgoers = getOutgoers(nodes[0], nodes, edges);
|
||||
expect(outgoers.length).to.be.equal(2);
|
||||
|
||||
const noOutgoers = getOutgoers(nodes[2], elements);
|
||||
const noOutgoers = getOutgoers(nodes[2], nodes, edges);
|
||||
expect(noOutgoers.length).to.be.equal(0);
|
||||
});
|
||||
|
||||
it('tests getIncomers function', () => {
|
||||
const incomers = getIncomers(nodes[2], elements);
|
||||
const incomers = getIncomers(nodes[2], nodes, edges);
|
||||
expect(incomers.length).to.be.equal(2);
|
||||
|
||||
const noIncomers = getIncomers(nodes[0], elements);
|
||||
const noIncomers = getIncomers(nodes[0], nodes, edges);
|
||||
expect(noIncomers.length).to.be.equal(0);
|
||||
});
|
||||
|
||||
describe('tests addEdge function', () => {
|
||||
it('adds edge', () => {
|
||||
const newEdge = { source: '1', target: '4' };
|
||||
const nextElements = addEdge(newEdge, elements);
|
||||
const nextEdges = addEdge(newEdge, edges);
|
||||
|
||||
expect(nextElements.length).to.be.equal(elements.length + 1);
|
||||
expect(nextEdges.length).to.be.equal(edges.length + 1);
|
||||
});
|
||||
|
||||
it('tries to add existing edge', () => {
|
||||
const newEdge = { source: '2', target: '3' };
|
||||
const nextElements = addEdge(newEdge, elements);
|
||||
const nextEdges = addEdge(newEdge, edges);
|
||||
|
||||
expect(nextElements.length).to.be.equal(elements.length);
|
||||
expect(nextEdges.length).to.be.equal(edges.length);
|
||||
});
|
||||
|
||||
it('tries to add invalid edge', () => {
|
||||
const newEdge = { nosource: '1', notarget: '3' };
|
||||
|
||||
try {
|
||||
addEdge(newEdge, elements);
|
||||
addEdge(newEdge, edges);
|
||||
} catch (e) {
|
||||
console.log(e.message);
|
||||
|
||||
|
||||
@@ -3,6 +3,16 @@ describe('Hidden Flow Rendering', () => {
|
||||
cy.visit('/hidden');
|
||||
});
|
||||
|
||||
it('renders empty flow', () => {
|
||||
cy.get('.react-flow__node').should('not.exist');
|
||||
cy.get('.react-flow__edge').should('not.exist');
|
||||
cy.get('.react-flow__minimap-node').should('not.exist');
|
||||
});
|
||||
|
||||
it('toggles isHidden mode', () => {
|
||||
cy.get('.react-flow__ishidden').click();
|
||||
});
|
||||
|
||||
it('renders initial flow', () => {
|
||||
cy.get('.react-flow__renderer');
|
||||
cy.get('.react-flow__node').should('have.length', 4);
|
||||
@@ -10,7 +20,7 @@ describe('Hidden Flow Rendering', () => {
|
||||
cy.get('.react-flow__minimap-node').should('have.length', 4);
|
||||
});
|
||||
|
||||
it('toggles isHidden mode', () => {
|
||||
it('toggles isHidden mode again', () => {
|
||||
cy.get('.react-flow__ishidden').click();
|
||||
});
|
||||
|
||||
@@ -19,14 +29,4 @@ describe('Hidden Flow Rendering', () => {
|
||||
cy.get('.react-flow__edge').should('not.exist');
|
||||
cy.get('.react-flow__minimap-node').should('not.exist');
|
||||
});
|
||||
|
||||
it('toggles isHidden mode again', () => {
|
||||
cy.get('.react-flow__ishidden').click();
|
||||
});
|
||||
|
||||
it('renders initial flow', () => {
|
||||
cy.get('.react-flow__node').should('have.length', 4);
|
||||
cy.get('.react-flow__edge').should('have.length', 3);
|
||||
cy.get('.react-flow__minimap-node').should('have.length', 4);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -120,12 +120,12 @@ describe('Interaction Flow Rendering', () => {
|
||||
});
|
||||
|
||||
it('zooms by scroll', () => {
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
|
||||
cy.get('.react-flow__renderer')
|
||||
cy.get('.react-flow__pane')
|
||||
.trigger('wheel', 'topLeft', { deltaY: 200 })
|
||||
.then(() => {
|
||||
const styleAfterZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleAfterZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
expect(styleBeforeZoom).not.to.equal(styleAfterZoom);
|
||||
});
|
||||
});
|
||||
@@ -136,12 +136,12 @@ describe('Interaction Flow Rendering', () => {
|
||||
|
||||
it('zooms by double click', () => {
|
||||
cy.get('.react-flow__controls-zoomout').click();
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleBeforeZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
|
||||
cy.get('.react-flow__renderer')
|
||||
cy.get('.react-flow__pane')
|
||||
.dblclick()
|
||||
.then(() => {
|
||||
const styleAfterZoom = Cypress.$('.react-flow__nodes').css('transform');
|
||||
const styleAfterZoom = Cypress.$('.react-flow__viewport').css('transform');
|
||||
expect(styleBeforeZoom).not.to.equal(styleAfterZoom);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ describe('Minimap Testing', () => {
|
||||
const viewBoxBeforeZoom = Cypress.$('.react-flow__minimap').attr('viewBox');
|
||||
const maskPathBeforeZoom = Cypress.$('.react-flow__minimap-mask').attr('d');
|
||||
|
||||
cy.get('.react-flow__renderer')
|
||||
cy.get('.react-flow__pane')
|
||||
.trigger('wheel', 'topLeft', { deltaY: -200 })
|
||||
.then(() => {
|
||||
const viewBoxAfterZoom = Cypress.$('.react-flow__minimap').attr('viewBox');
|
||||
@@ -53,7 +53,7 @@ describe('Minimap Testing', () => {
|
||||
// for d3 we have to pass the window to the event
|
||||
// https://github.com/cypress-io/cypress/issues/3441
|
||||
cy.window().then((win) => {
|
||||
cy.get('.react-flow__renderer')
|
||||
cy.get('.react-flow__pane')
|
||||
.trigger('mousedown', 'topLeft', { which: 1, view: win })
|
||||
.trigger('mousemove', 'bottomLeft')
|
||||
.trigger('mouseup', { force: true, view: win })
|
||||
|
||||
+17
-115
@@ -1,130 +1,49 @@
|
||||
import { useState, MouseEvent, useCallback } from 'react';
|
||||
import { useState, MouseEvent } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
addEdge,
|
||||
Background,
|
||||
MiniMap,
|
||||
Controls,
|
||||
BackgroundVariant,
|
||||
FlowElement,
|
||||
Node,
|
||||
Edge,
|
||||
ReactFlowInstance,
|
||||
Connection,
|
||||
MarkerType,
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
ReactFlowInstance,
|
||||
} from 'react-flow-renderer';
|
||||
import DebugNode from './DebugNode';
|
||||
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
||||
const onEdgeClick = (_: MouseEvent, edge: Edge) => console.log('click', edge);
|
||||
const onNodeClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 }, className: 'light' },
|
||||
{
|
||||
id: '4',
|
||||
data: { label: 'Node 4' },
|
||||
position: { x: 100, y: 200 },
|
||||
className: 'light',
|
||||
style: { backgroundColor: 'rgba(255,50, 50, 0.5)', width: 500, height: 300 },
|
||||
},
|
||||
{
|
||||
id: '4a',
|
||||
data: { label: 'Node 4a' },
|
||||
position: { x: 15, y: 15 },
|
||||
className: 'light',
|
||||
parentNode: '4',
|
||||
extent: 'parent',
|
||||
},
|
||||
{
|
||||
id: '4b',
|
||||
data: { label: 'Node 4b' },
|
||||
position: { x: 150, y: 50 },
|
||||
className: 'light',
|
||||
style: { backgroundColor: 'rgba(50, 50, 255, 0.5)', height: 200, width: 300 },
|
||||
parentNode: '4',
|
||||
},
|
||||
{
|
||||
id: '4b1',
|
||||
data: { label: 'Node 4b1' },
|
||||
position: { x: 20, y: 20 },
|
||||
className: 'light',
|
||||
parentNode: '4b',
|
||||
},
|
||||
{
|
||||
id: '4b2',
|
||||
data: { label: 'Node 4b2' },
|
||||
position: { x: 100, y: 100 },
|
||||
className: 'light',
|
||||
parentNode: '4b',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
data: { label: 'Node 5' },
|
||||
position: { x: 650, y: 250 },
|
||||
className: 'light',
|
||||
style: { backgroundColor: 'rgba(20 ,200, 255, 1.5)', width: 400, height: 150 },
|
||||
zIndex: 1000,
|
||||
},
|
||||
{
|
||||
id: '5a',
|
||||
data: { label: 'Node 5a' },
|
||||
position: { x: 25, y: 50 },
|
||||
className: 'light',
|
||||
parentNode: '5',
|
||||
},
|
||||
{
|
||||
id: '5b',
|
||||
data: { label: 'Node 5b' },
|
||||
position: { x: 225, y: 50 },
|
||||
className: 'light',
|
||||
parentNode: '5',
|
||||
},
|
||||
{ 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',
|
||||
markerEnd: { type: MarkerType.Arrow, strokeWidth: 2, width: 15, height: 15, color: '#f00' },
|
||||
},
|
||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
||||
{ id: 'e1-3', source: '1', target: '3' },
|
||||
{ id: 'e3-4', source: '3', target: '4', zIndex: 100 },
|
||||
{ id: 'e3-4b', source: '3', target: '4b' },
|
||||
{ id: 'e4a-4b1', source: '4a', target: '4b1' },
|
||||
{ id: 'e4a-4b2', source: '4a', target: '4b2', zIndex: 100 },
|
||||
{ id: 'e4b1-4b2', source: '4b1', target: '4b2' },
|
||||
{ id: '3-5', source: '3', target: '5' },
|
||||
];
|
||||
|
||||
const nodeTypes = {
|
||||
default: DebugNode,
|
||||
};
|
||||
|
||||
const BasicFlow = () => {
|
||||
const [rfInstance, setRfInstance] = useState<ReactFlowInstance | null>(null);
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||
|
||||
const onConnect = useCallback((connection: Connection) => {
|
||||
setEdges((eds) => {
|
||||
return addEdge(connection, eds);
|
||||
});
|
||||
}, []);
|
||||
const onPaneReady = useCallback((reactFlowInstance: ReactFlowInstance) => setRfInstance(reactFlowInstance), []);
|
||||
const onConnect = (params: Edge | Connection) => setEdges((els) => addEdge(params, els));
|
||||
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => setRfInstance(reactFlowInstance);
|
||||
|
||||
const updatePos = () => {
|
||||
setNodes((nds) => {
|
||||
return nds.map((n) => {
|
||||
n.position = {
|
||||
return nds.map((node) => {
|
||||
node.position = {
|
||||
x: Math.random() * 400,
|
||||
y: Math.random() * 400,
|
||||
};
|
||||
|
||||
return n;
|
||||
return node;
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -134,18 +53,10 @@ const BasicFlow = () => {
|
||||
|
||||
const toggleClassnames = () => {
|
||||
setNodes((nds) => {
|
||||
return nds.map((n) => {
|
||||
n.className = n.className === 'light' ? 'dark' : 'light';
|
||||
return n;
|
||||
});
|
||||
});
|
||||
};
|
||||
return nds.map((node) => {
|
||||
node.className = node.className === 'light' ? 'dark' : 'light';
|
||||
|
||||
const toggleChildNodes = () => {
|
||||
setNodes((nds) => {
|
||||
return nds.map((n) => {
|
||||
n.hidden = !!n.parentNode && !n.hidden;
|
||||
return n;
|
||||
return node;
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -154,24 +65,18 @@ const BasicFlow = () => {
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onPaneReady={onPaneReady}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
onPaneReady={onPaneReady}
|
||||
onNodeClick={onNodeClick}
|
||||
onEdgeClick={onEdgeClick}
|
||||
onConnect={onConnect}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
className="react-flow-basic-example"
|
||||
defaultZoom={1.5}
|
||||
minZoom={0.2}
|
||||
maxZoom={4}
|
||||
onlyRenderVisibleElements={false}
|
||||
nodeTypes={nodeTypes}
|
||||
fitViewOnInit
|
||||
>
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
<Background />
|
||||
<Background variant={BackgroundVariant.Lines} />
|
||||
|
||||
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
|
||||
<button onClick={resetTransform} style={{ marginRight: 5 }}>
|
||||
@@ -183,9 +88,6 @@ const BasicFlow = () => {
|
||||
<button onClick={toggleClassnames} style={{ marginRight: 5 }}>
|
||||
toggle classnames
|
||||
</button>
|
||||
<button style={{ marginRight: 5 }} onClick={toggleChildNodes}>
|
||||
toggleChildNodes
|
||||
</button>
|
||||
<button onClick={logToObject}>toObject</button>
|
||||
</div>
|
||||
</ReactFlow>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import ReactFlow, { Node, Edge, useNodesState, useEdgesState } from 'react-flow-renderer';
|
||||
|
||||
import DragHandleNode from './DragHandleNode';
|
||||
|
||||
const nodeTypes = {
|
||||
dragHandleNode: DragHandleNode,
|
||||
};
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
{
|
||||
id: '2',
|
||||
type: 'dragHandleNode',
|
||||
dragHandle: '.custom-drag-handle',
|
||||
style: { border: '1px solid #ddd', padding: '20px 40px' },
|
||||
position: { x: 200, y: 200 },
|
||||
data: null,
|
||||
},
|
||||
];
|
||||
|
||||
const initialEdges: Edge[] = [];
|
||||
|
||||
const DragHandleFlow = () => {
|
||||
const [nodes, , onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges] = useEdgesState(initialEdges);
|
||||
|
||||
return <ReactFlow nodes={nodes} onNodesChange={onNodesChange} edges={edges} nodeTypes={nodeTypes} />;
|
||||
};
|
||||
|
||||
export default DragHandleFlow;
|
||||
@@ -1,52 +1,51 @@
|
||||
import React, { useState, MouseEvent, CSSProperties } from 'react';
|
||||
import { MouseEvent, CSSProperties } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
removeElements,
|
||||
addEdge,
|
||||
MiniMap,
|
||||
Controls,
|
||||
Background,
|
||||
OnLoadParams,
|
||||
Elements,
|
||||
ElementId,
|
||||
Node,
|
||||
FlowElement,
|
||||
BackgroundVariant,
|
||||
Connection,
|
||||
Edge,
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
ReactFlowInstance,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
const onLoad = (reactFlowInstance: OnLoadParams) => console.log('flow loaded:', reactFlowInstance);
|
||||
const onElementClick = (_: MouseEvent, element: FlowElement) => console.log('click', element);
|
||||
const onPaneReady = (reactFlowInstance: ReactFlowInstance) => console.log('flow loaded:', reactFlowInstance);
|
||||
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
||||
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 [nodes, setNodes, onNodesChange] = useNodesState([]);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
||||
|
||||
const onConnect = (params: Connection | Edge) => setEdges((els) => addEdge(params, els));
|
||||
const addRandomNode = () => {
|
||||
const nodeId: ElementId = (elements.length + 1).toString();
|
||||
const nodeId = (nodes.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));
|
||||
setNodes((nds) => nds.concat(newNode));
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
onLoad={onLoad}
|
||||
onElementClick={onElementClick}
|
||||
onElementsRemove={onElementsRemove}
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onPaneReady={onPaneReady}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
onNodeClick={onNodeClick}
|
||||
onConnect={(p) => onConnect(p)}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
onlyRenderVisibleElements={false}
|
||||
>
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
<Background variant={BackgroundVariant.Lines} />
|
||||
|
||||
@@ -1,37 +1,42 @@
|
||||
import React, { useState, MouseEvent, WheelEvent } from 'react';
|
||||
import { useState, MouseEvent, WheelEvent } from 'react';
|
||||
import ReactFlow, {
|
||||
addEdge,
|
||||
MiniMap,
|
||||
Controls,
|
||||
Elements,
|
||||
Node,
|
||||
FlowElement,
|
||||
Connection,
|
||||
Edge,
|
||||
PanOnScrollMode,
|
||||
FlowTransform,
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
const initialElements: Elements = [
|
||||
const initialNodes: Node[] = [
|
||||
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 } },
|
||||
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 } },
|
||||
{ id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 } },
|
||||
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 } },
|
||||
];
|
||||
|
||||
const initialEdges: Edge[] = [
|
||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
||||
{ id: 'e1-3', source: '1', target: '3' },
|
||||
];
|
||||
|
||||
const 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 onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
||||
const onEdgeClick = (_: MouseEvent, edge: Edge) => console.log('click', edge);
|
||||
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<Elements>(initialElements);
|
||||
const onConnect = (params: Connection | Edge) => setElements((els) => addEdge(params, els));
|
||||
const [nodes, , onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||
const onConnect = (params: Connection | Edge) => setEdges((els) => addEdge(params, els));
|
||||
|
||||
const [isSelectable, setIsSelectable] = useState<boolean>(false);
|
||||
const [isDraggable, setIsDraggable] = useState<boolean>(false);
|
||||
@@ -46,9 +51,14 @@ const InteractionFlow = () => {
|
||||
const [captureZoomScroll, setCaptureZoomScroll] = useState<boolean>(false);
|
||||
const [captureElementClick, setCaptureElementClick] = useState<boolean>(false);
|
||||
|
||||
console.log(11, captureElementClick);
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
elementsSelectable={isSelectable}
|
||||
nodesConnectable={isConnectable}
|
||||
nodesDraggable={isDraggable}
|
||||
@@ -58,7 +68,8 @@ const InteractionFlow = () => {
|
||||
panOnScrollMode={panOnScrollMode}
|
||||
zoomOnDoubleClick={zoomOnDoubleClick}
|
||||
onConnect={onConnect}
|
||||
onElementClick={captureElementClick ? onElementClick : undefined}
|
||||
onNodeClick={captureElementClick ? onNodeClick : undefined}
|
||||
onEdgeClick={captureElementClick ? onEdgeClick : undefined}
|
||||
onNodeDragStart={onNodeDragStart}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
paneMoveable={paneMoveable}
|
||||
@@ -0,0 +1,195 @@
|
||||
import { useState, MouseEvent, useCallback } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
addEdge,
|
||||
Background,
|
||||
MiniMap,
|
||||
Controls,
|
||||
Node,
|
||||
Edge,
|
||||
ReactFlowInstance,
|
||||
Connection,
|
||||
MarkerType,
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from 'react-flow-renderer';
|
||||
import DebugNode from './DebugNode';
|
||||
|
||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
||||
const onEdgeClick = (_: MouseEvent, edge: Edge) => console.log('click', edge);
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 }, className: 'light' },
|
||||
{
|
||||
id: '4',
|
||||
data: { label: 'Node 4' },
|
||||
position: { x: 100, y: 200 },
|
||||
className: 'light',
|
||||
style: { backgroundColor: 'rgba(255,50, 50, 0.5)', width: 500, height: 300 },
|
||||
},
|
||||
{
|
||||
id: '4a',
|
||||
data: { label: 'Node 4a' },
|
||||
position: { x: 15, y: 15 },
|
||||
className: 'light',
|
||||
parentNode: '4',
|
||||
extent: 'parent',
|
||||
},
|
||||
{
|
||||
id: '4b',
|
||||
data: { label: 'Node 4b' },
|
||||
position: { x: 150, y: 50 },
|
||||
className: 'light',
|
||||
style: { backgroundColor: 'rgba(50, 50, 255, 0.5)', height: 200, width: 300 },
|
||||
parentNode: '4',
|
||||
},
|
||||
{
|
||||
id: '4b1',
|
||||
data: { label: 'Node 4b1' },
|
||||
position: { x: 20, y: 20 },
|
||||
className: 'light',
|
||||
parentNode: '4b',
|
||||
},
|
||||
{
|
||||
id: '4b2',
|
||||
data: { label: 'Node 4b2' },
|
||||
position: { x: 100, y: 100 },
|
||||
className: 'light',
|
||||
parentNode: '4b',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
data: { label: 'Node 5' },
|
||||
position: { x: 650, y: 250 },
|
||||
className: 'light',
|
||||
style: { backgroundColor: 'rgba(20 ,200, 255, 1.5)', width: 400, height: 150 },
|
||||
zIndex: 1000,
|
||||
},
|
||||
{
|
||||
id: '5a',
|
||||
data: { label: 'Node 5a' },
|
||||
position: { x: 25, y: 50 },
|
||||
className: 'light',
|
||||
parentNode: '5',
|
||||
},
|
||||
{
|
||||
id: '5b',
|
||||
data: { label: 'Node 5b' },
|
||||
position: { x: 225, y: 50 },
|
||||
className: 'light',
|
||||
parentNode: '5',
|
||||
},
|
||||
{ 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' },
|
||||
];
|
||||
|
||||
const initialEdges: Edge[] = [
|
||||
{
|
||||
id: 'e1-2',
|
||||
source: '1',
|
||||
target: '2',
|
||||
markerEnd: { type: MarkerType.Arrow, strokeWidth: 2, width: 15, height: 15, color: '#f00' },
|
||||
},
|
||||
{ id: 'e1-3', source: '1', target: '3' },
|
||||
{ id: 'e3-4', source: '3', target: '4', zIndex: 100 },
|
||||
{ id: 'e3-4b', source: '3', target: '4b' },
|
||||
{ id: 'e4a-4b1', source: '4a', target: '4b1' },
|
||||
{ id: 'e4a-4b2', source: '4a', target: '4b2', zIndex: 100 },
|
||||
{ id: 'e4b1-4b2', source: '4b1', target: '4b2' },
|
||||
{ id: '3-5', source: '3', target: '5' },
|
||||
];
|
||||
|
||||
const nodeTypes = {
|
||||
default: DebugNode,
|
||||
};
|
||||
|
||||
const BasicFlow = () => {
|
||||
const [rfInstance, setRfInstance] = useState<ReactFlowInstance | null>(null);
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||
|
||||
const onConnect = useCallback((connection: Connection) => {
|
||||
setEdges((eds) => {
|
||||
return addEdge(connection, eds);
|
||||
});
|
||||
}, []);
|
||||
const onPaneReady = useCallback((reactFlowInstance: ReactFlowInstance) => setRfInstance(reactFlowInstance), []);
|
||||
|
||||
const updatePos = () => {
|
||||
setNodes((nds) => {
|
||||
return nds.map((n) => {
|
||||
n.position = {
|
||||
x: Math.random() * 400,
|
||||
y: Math.random() * 400,
|
||||
};
|
||||
|
||||
return n;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const logToObject = () => console.log(rfInstance?.toObject());
|
||||
const resetTransform = () => rfInstance?.setTransform({ x: 0, y: 0, zoom: 1 });
|
||||
|
||||
const toggleClassnames = () => {
|
||||
setNodes((nds) => {
|
||||
return nds.map((n) => {
|
||||
n.className = n.className === 'light' ? 'dark' : 'light';
|
||||
return n;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const toggleChildNodes = () => {
|
||||
setNodes((nds) => {
|
||||
return nds.map((n) => {
|
||||
n.hidden = !!n.parentNode && !n.hidden;
|
||||
return n;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onPaneReady={onPaneReady}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
onNodeClick={onNodeClick}
|
||||
onEdgeClick={onEdgeClick}
|
||||
onConnect={onConnect}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
className="react-flow-basic-example"
|
||||
defaultZoom={1.5}
|
||||
minZoom={0.2}
|
||||
maxZoom={4}
|
||||
onlyRenderVisibleElements={false}
|
||||
nodeTypes={nodeTypes}
|
||||
fitViewOnInit
|
||||
>
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
<Background />
|
||||
|
||||
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
|
||||
<button onClick={resetTransform} style={{ marginRight: 5 }}>
|
||||
reset transform
|
||||
</button>
|
||||
<button onClick={updatePos} style={{ marginRight: 5 }}>
|
||||
change pos
|
||||
</button>
|
||||
<button onClick={toggleClassnames} style={{ marginRight: 5 }}>
|
||||
toggle classnames
|
||||
</button>
|
||||
<button style={{ marginRight: 5 }} onClick={toggleChildNodes}>
|
||||
toggleChildNodes
|
||||
</button>
|
||||
<button onClick={logToObject}>toObject</button>
|
||||
</div>
|
||||
</ReactFlow>
|
||||
);
|
||||
};
|
||||
|
||||
export default BasicFlow;
|
||||
@@ -13,6 +13,10 @@ import NestedNodes from './NestedNodes';
|
||||
import Hidden from './Hidden';
|
||||
import UpdatableEdge from './UpdatableEdge';
|
||||
import TouchDevice from './TouchDevice';
|
||||
import Subflow from './Subflow';
|
||||
import Interaction from './Interaction';
|
||||
import Empty from './Empty';
|
||||
import DragHandle from './DragHandle';
|
||||
|
||||
import './index.css';
|
||||
|
||||
@@ -61,6 +65,22 @@ const routes = [
|
||||
path: '/touch-device',
|
||||
component: TouchDevice,
|
||||
},
|
||||
{
|
||||
path: '/subflow',
|
||||
component: Subflow,
|
||||
},
|
||||
{
|
||||
path: '/interaction',
|
||||
component: Interaction,
|
||||
},
|
||||
{
|
||||
path: '/empty',
|
||||
component: Empty,
|
||||
},
|
||||
{
|
||||
path: '/draghandle',
|
||||
component: DragHandle,
|
||||
},
|
||||
];
|
||||
|
||||
const Header = withRouter(({ history, location }) => {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import ReactFlow from 'react-flow-renderer';
|
||||
|
||||
import DragHandleNode from './DragHandleNode';
|
||||
|
||||
const nodeTypes = {
|
||||
dragHandleNode: DragHandleNode,
|
||||
};
|
||||
|
||||
const elements = [
|
||||
{
|
||||
id: '2',
|
||||
type: 'dragHandleNode',
|
||||
dragHandle: '.custom-drag-handle',
|
||||
style: { border: '1px solid #ddd', padding: '20px 40px' },
|
||||
position: { x: 200, y: 200 },
|
||||
},
|
||||
];
|
||||
|
||||
const DragHandleFlow = () => <ReactFlow elements={elements} nodeTypes={nodeTypes} />;
|
||||
|
||||
export default DragHandleFlow;
|
||||
Reference in New Issue
Block a user