From 8014fb0f444e62c1f90b05b03cee5b170b55b453 Mon Sep 17 00:00:00 2001 From: moklick Date: Wed, 22 Dec 2021 14:19:57 +0100 Subject: [PATCH] test(examples): use new api for test examples --- cypress/integration/flow/basic.spec.js | 12 +- cypress/integration/flow/controls.spec.js | 16 +- cypress/integration/flow/empty.spec.js | 10 - cypress/integration/flow/graph-utils.spec.js | 18 +- cypress/integration/flow/hidden.spec.js | 22 +- cypress/integration/flow/interaction.spec.js | 12 +- cypress/integration/flow/minimap.spec.js | 4 +- example/src/Basic/index.tsx | 132 ++---------- .../DragHandle/DragHandleNode.tsx | 0 example/src/DragHandle/index.tsx | 29 +++ example/{src_oldapi => src}/Empty/index.tsx | 37 ++-- .../{src_oldapi => src}/Interaction/index.tsx | 29 ++- example/src/{Basic => Subflow}/DebugNode.tsx | 0 example/src/Subflow/index.tsx | 195 ++++++++++++++++++ example/src/index.tsx | 20 ++ example/src_oldapi/DragHandle/index.tsx | 21 -- 16 files changed, 341 insertions(+), 216 deletions(-) rename example/{src_oldapi => src}/DragHandle/DragHandleNode.tsx (100%) create mode 100644 example/src/DragHandle/index.tsx rename example/{src_oldapi => src}/Empty/index.tsx (52%) rename example/{src_oldapi => src}/Interaction/index.tsx (90%) rename example/src/{Basic => Subflow}/DebugNode.tsx (100%) create mode 100644 example/src/Subflow/index.tsx delete mode 100644 example/src_oldapi/DragHandle/index.tsx diff --git a/cypress/integration/flow/basic.spec.js b/cypress/integration/flow/basic.spec.js index 804d6e2b..46837083 100644 --- a/cypress/integration/flow/basic.spec.js +++ b/cypress/integration/flow/basic.spec.js @@ -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); }); }); diff --git a/cypress/integration/flow/controls.spec.js b/cypress/integration/flow/controls.spec.js index 98e0def9..76cd6b99 100644 --- a/cypress/integration/flow/controls.spec.js +++ b/cypress/integration/flow/controls.spec.js @@ -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); }); }); diff --git a/cypress/integration/flow/empty.spec.js b/cypress/integration/flow/empty.spec.js index 52c32b16..25861e45 100644 --- a/cypress/integration/flow/empty.spec.js +++ b/cypress/integration/flow/empty.spec.js @@ -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); - }); }); diff --git a/cypress/integration/flow/graph-utils.spec.js b/cypress/integration/flow/graph-utils.spec.js index e6df1455..61fd2e54 100644 --- a/cypress/integration/flow/graph-utils.spec.js +++ b/cypress/integration/flow/graph-utils.spec.js @@ -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); diff --git a/cypress/integration/flow/hidden.spec.js b/cypress/integration/flow/hidden.spec.js index fdb0827f..20a95d43 100644 --- a/cypress/integration/flow/hidden.spec.js +++ b/cypress/integration/flow/hidden.spec.js @@ -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); - }); }); diff --git a/cypress/integration/flow/interaction.spec.js b/cypress/integration/flow/interaction.spec.js index 0c695924..e9abb2e7 100644 --- a/cypress/integration/flow/interaction.spec.js +++ b/cypress/integration/flow/interaction.spec.js @@ -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); }); }); diff --git a/cypress/integration/flow/minimap.spec.js b/cypress/integration/flow/minimap.spec.js index c9235ea8..c7aaec4f 100644 --- a/cypress/integration/flow/minimap.spec.js +++ b/cypress/integration/flow/minimap.spec.js @@ -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 }) diff --git a/example/src/Basic/index.tsx b/example/src/Basic/index.tsx index 97a113b2..836b6cfb 100644 --- a/example/src/Basic/index.tsx +++ b/example/src/Basic/index.tsx @@ -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(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 = () => { - - - +
-
diff --git a/example/src_oldapi/DragHandle/DragHandleNode.tsx b/example/src/DragHandle/DragHandleNode.tsx similarity index 100% rename from example/src_oldapi/DragHandle/DragHandleNode.tsx rename to example/src/DragHandle/DragHandleNode.tsx diff --git a/example/src/DragHandle/index.tsx b/example/src/DragHandle/index.tsx new file mode 100644 index 00000000..c9f67f5d --- /dev/null +++ b/example/src/DragHandle/index.tsx @@ -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 ; +}; + +export default DragHandleFlow; diff --git a/example/src_oldapi/Empty/index.tsx b/example/src/Empty/index.tsx similarity index 52% rename from example/src_oldapi/Empty/index.tsx rename to example/src/Empty/index.tsx index 9bfc7c25..d7645a2b 100644 --- a/example/src_oldapi/Empty/index.tsx +++ b/example/src/Empty/index.tsx @@ -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([]); - 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 ( onConnect(p)} onNodeDragStop={onNodeDragStop} onlyRenderVisibleElements={false} > - diff --git a/example/src_oldapi/Interaction/index.tsx b/example/src/Interaction/index.tsx similarity index 90% rename from example/src_oldapi/Interaction/index.tsx rename to example/src/Interaction/index.tsx index 2ca7900c..0daf76fb 100644 --- a/example/src_oldapi/Interaction/index.tsx +++ b/example/src/Interaction/index.tsx @@ -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(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(false); const [isDraggable, setIsDraggable] = useState(false); @@ -46,9 +51,14 @@ const InteractionFlow = () => { const [captureZoomScroll, setCaptureZoomScroll] = useState(false); const [captureElementClick, setCaptureElementClick] = useState(false); + console.log(11, captureElementClick); + return ( { panOnScrollMode={panOnScrollMode} zoomOnDoubleClick={zoomOnDoubleClick} onConnect={onConnect} - onElementClick={captureElementClick ? onElementClick : undefined} + onNodeClick={captureElementClick ? onNodeClick : undefined} + onEdgeClick={captureElementClick ? onEdgeClick : undefined} onNodeDragStart={onNodeDragStart} onNodeDragStop={onNodeDragStop} paneMoveable={paneMoveable} diff --git a/example/src/Basic/DebugNode.tsx b/example/src/Subflow/DebugNode.tsx similarity index 100% rename from example/src/Basic/DebugNode.tsx rename to example/src/Subflow/DebugNode.tsx diff --git a/example/src/Subflow/index.tsx b/example/src/Subflow/index.tsx new file mode 100644 index 00000000..97a113b2 --- /dev/null +++ b/example/src/Subflow/index.tsx @@ -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(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 ( + + + + + +
+ + + + + +
+
+ ); +}; + +export default BasicFlow; diff --git a/example/src/index.tsx b/example/src/index.tsx index 5588eee0..d81cad1f 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -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 }) => { diff --git a/example/src_oldapi/DragHandle/index.tsx b/example/src_oldapi/DragHandle/index.tsx deleted file mode 100644 index b5620243..00000000 --- a/example/src_oldapi/DragHandle/index.tsx +++ /dev/null @@ -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 = () => ; - -export default DragHandleFlow;