diff --git a/example/src/NestedNodes/index.tsx b/example/src/NestedNodes/index.tsx new file mode 100644 index 00000000..232578e0 --- /dev/null +++ b/example/src/NestedNodes/index.tsx @@ -0,0 +1,186 @@ +import { useState, MouseEvent, useCallback } from 'react'; + +import ReactFlow, { + addEdge, + Background, + applyNodeChanges, + applyEdgeChanges, + MiniMap, + Controls, + Node, + Edge, + NodeChange, + EdgeChange, + OnLoadParams, + Connection, +} from 'react-flow-renderer'; + +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: '2', + data: { label: 'Node 2' }, + position: { x: 100, y: 100 }, + className: 'light', + style: { backgroundColor: 'rgba(255, 0, 0, 0.8)', width: 200, height: 200 }, + }, + { + id: '2a', + data: { label: 'Node 2a' }, + position: { x: 10, y: 50 }, + parentNode: '2', + }, + { id: '3', data: { label: 'Node 3' }, position: { x: 320, y: 100 }, className: 'light' }, + { + id: '4', + data: { label: 'Node 4' }, + position: { x: 320, y: 200 }, + className: 'light', + style: { backgroundColor: 'rgba(255, 0, 0, 0.7)', width: 300, height: 300 }, + }, + { + id: '4a', + data: { label: 'Node 4a' }, + position: { x: 15, y: 65 }, + className: 'light', + parentNode: '4', + extent: 'parent', + }, + { + id: '4b', + data: { label: 'Node 4b' }, + position: { x: 15, y: 120 }, + className: 'light', + style: { backgroundColor: 'rgba(255, 0, 255, 0.7)', height: 150, width: 270 }, + parentNode: '4', + }, + { + id: '4b1', + data: { label: 'Node 4b1' }, + position: { x: 20, y: 40 }, + className: 'light', + parentNode: '4b', + }, + { + id: '4b2', + data: { label: 'Node 4b2' }, + position: { x: 100, y: 100 }, + className: 'light', + parentNode: '4b', + }, +]; + +const initialEdges: Edge[] = [ + { id: 'e1-2', source: '1', target: '2', animated: true }, + { id: 'e1-3', source: '1', target: '3' }, + { id: 'e2a-4a', source: '2a', target: '4a' }, + { id: 'e3-4', source: '3', target: '4' }, + { id: 'e3-4b', source: '3', target: '4b' }, + { id: 'e4a-4b1', source: '4a', target: '4b1' }, + { id: 'e4a-4b2', source: '4a', target: '4b2' }, + { id: 'e4b1-4b2', source: '4b1', target: '4b2' }, +]; + +function shuffle() { + return Math.random() - Math.random(); +} + +const NestedFlow = () => { + const [rfInstance, setRfInstance] = useState(null); + const [nodes, setNodes] = useState(initialNodes); + const [edges, setEdges] = useState(initialEdges); + + const onConnect = useCallback((params: Edge | Connection) => { + setEdges((eds) => { + return addEdge(params, eds); + }); + }, []); + const onLoad = useCallback((reactFlowInstance: OnLoadParams) => 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.isHidden = !!n.parentNode && !n.isHidden; + return n; + }); + }); + }; + + const onNodesChange = useCallback((changes: NodeChange[]) => { + setNodes((ns) => applyNodeChanges(changes, ns)); + }, []); + + const onEdgesChange = useCallback((changes: EdgeChange[]) => { + setEdges((es) => applyEdgeChanges(changes, es)); + }, []); + + return ( + + + + + +
+ + + + + +
+
+ ); +}; + +export default NestedFlow; diff --git a/example/src/index.tsx b/example/src/index.tsx index 1f44867f..b23fc09c 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -8,12 +8,13 @@ import Stress from './Stress'; import CustomNode from './CustomNode'; import FloatingEdges from './FloatingEdges'; import Layouting from './Layouting'; +import NestedNodes from './NestedNodes'; import './index.css'; const routes = [ { - path: '/basic', + path: '/', component: Basic, }, { @@ -36,6 +37,10 @@ const routes = [ path: '/layouting', component: Layouting, }, + { + path: '/nested-nodes', + component: NestedNodes, + }, ]; const Header = withRouter(({ history, location }) => { diff --git a/src/store/utils.ts b/src/store/utils.ts index 928adf45..7ab8c1a6 100644 --- a/src/store/utils.ts +++ b/src/store/utils.ts @@ -38,7 +38,7 @@ export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals) height: node.height || null, position: node.position, positionAbsolute: node.position, - treeLevel: node.zIndex || 0, + treeLevel: node.isDragging || node.isSelected ? 1000 : node.zIndex || 0, }; if (node.parentNode) { internals.parentNode = node.parentNode; @@ -51,9 +51,11 @@ export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals) const updatedInternals: NodeInternalsItem = nextNodeInternals.get(node.id)!; if (node.parentNode) { + const parentNodeInternal = nextNodeInternals.get(node.parentNode); + const positionAbsoluteAndTreeLevel = getAbsolutePosAndTreeLevel(node, nextNodeInternals, { ...node.position, - treeLevel: node.zIndex || 0, + treeLevel: node.zIndex || updatedInternals?.treeLevel || parentNodeInternal?.treeLevel || 0, }); const { treeLevel, x, y } = positionAbsoluteAndTreeLevel; @@ -66,11 +68,11 @@ export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals) updatedInternals.treeLevel = treeLevel; } - if ((node.isDragging || node.isSelected) && !parentNodes[node.id]) { - nextNodeInternals.set(node.id, { ...updatedInternals, treeLevel: 1000 }); - } else { - nextNodeInternals.set(node.id, { ...updatedInternals, treeLevel: updatedInternals?.treeLevel || 0 }); - } + // if (node.isDragging || node.isSelected) { + // nextNodeInternals.set(node.id, { ...updatedInternals, treeLevel: 1000 }); + // } else { + // nextNodeInternals.set(node.id, { ...updatedInternals, treeLevel: updatedInternals?.treeLevel || 0 }); + // } }); return nextNodeInternals;