diff --git a/examples/react/src/App/routes.ts b/examples/react/src/App/routes.ts index 52f80979..d781ff4d 100644 --- a/examples/react/src/App/routes.ts +++ b/examples/react/src/App/routes.ts @@ -59,6 +59,7 @@ import DevTools from '../examples/DevTools'; import Redux from '../examples/Redux'; import MovingHandles from '../examples/MovingHandles'; import DetachedHandle from '../examples/DetachedHandle'; +import Middlewares from '../examples/Middlewares'; export interface IRoute { name: string; @@ -232,6 +233,11 @@ const routes: IRoute[] = [ path: 'layouting', component: Layouting, }, + { + name: 'Middlewares', + path: 'middlewares', + component: Middlewares, + }, { name: 'Multi setNodes', path: 'multi-setnodes', diff --git a/examples/react/src/examples/Middlewares/index.tsx b/examples/react/src/examples/Middlewares/index.tsx new file mode 100644 index 00000000..b3950b3d --- /dev/null +++ b/examples/react/src/examples/Middlewares/index.tsx @@ -0,0 +1,125 @@ +import { useCallback } from 'react'; +import { + ReactFlow, + MiniMap, + Background, + BackgroundVariant, + Controls, + ReactFlowProvider, + Node, + Edge, + useReactFlow, + Panel, + useNodesState, + useEdgesState, + addEdge, + Connection, + useNodeChangeMiddleware, + NodeChange, +} from '@xyflow/react'; +import { initialNodes, initialEdges } from '../CancelConnection/data'; + +const a = { id: 'a', data: { label: 'A' }, position: { x: 250, y: 5 } }; +const b = { id: 'b', data: { label: 'B' }, position: { x: 100, y: 100 } }; +const c = { id: 'c', data: { label: 'C' }, position: { x: 400, y: 100 } }; + +function RestrictExtent({ + minX = -Infinity, + minY = -Infinity, + maxX = Infinity, + maxY = Infinity, +}: { + minX?: number; + minY?: number; + maxX?: number; + maxY?: number; +}) { + useNodeChangeMiddleware( + useCallback( + (changes: NodeChange[]) => { + return changes.map((change) => { + const { type } = change; + if (type === 'position') { + const { position } = change; + if (position) { + position.x = Math.min(Math.max(position.x, minX), maxX); + position.y = Math.min(Math.max(position.y, minY), maxY); + change.position = position; + } + } else if (type === 'add' || type === 'replace') { + const { item } = change; + if (item) { + item.position.x = Math.min(Math.max(item.position.x, minX), maxX); + item.position.y = Math.min(Math.max(item.position.y, minY), maxY); + change.item = item; + } + } + + return change; + }); + }, + [minX, minY, maxX, maxY] + ) + ); + + return null; +} + +const SetNotesBatchingFlow = () => { + const { setNodes, updateNode } = useReactFlow(); + + const [nodes, , onNodesChange] = useNodesState(initialNodes); + const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); + const onConnect = useCallback((params: Connection | Edge) => setEdges((eds) => addEdge(params, eds)), [setEdges]); + + const triggerMultipleSetNodes = useCallback(() => { + setNodes([a]); + setNodes((nodes) => [...nodes, b]); + setNodes((nodes) => [...nodes, c]); + setNodes((nodes) => + nodes.map((node) => + node.id === 'a' ? { ...node, position: { x: node.position.x + 2000, y: node.position.y + 20 } } : node + ) + ); + }, []); + + const triggerMultipleUpdateNodes = useCallback(() => { + triggerMultipleSetNodes(); + updateNode('a', (a) => ({ position: { x: a.position.x + 20, y: a.position.y + 20 } })); + updateNode('b', (b) => ({ position: { x: b.position.x + 20, y: b.position.y + 20 } })); + updateNode('c', (c) => ({ position: { x: c.position.x + 20, y: c.position.y + 20 } })); + updateNode('a', (a) => ({ data: { ...a.data, label: `A ${Date.now()}` } })); + updateNode('b', (b) => ({ data: { ...b.data, label: `B ${Date.now()}` } })); + updateNode('c', (c) => ({ data: { ...c.data, label: `C ${Date.now()}` } })); + }, []); + + return ( + + + + + + + + + + + ); +}; + +export default function App() { + return ( + + + + ); +} diff --git a/examples/react/src/examples/Overview/index.tsx b/examples/react/src/examples/Overview/index.tsx index 8e6a3441..7add02f0 100644 --- a/examples/react/src/examples/Overview/index.tsx +++ b/examples/react/src/examples/Overview/index.tsx @@ -193,37 +193,6 @@ const nodeColor = (n: Node): string => { return '#fff'; }; -function RestrictExtent({ - minX = -Infinity, - minY = -Infinity, - maxX = Infinity, - maxY = Infinity, -}: { - minX?: number; - minY?: number; - maxX?: number; - maxY?: number; -}) { - useNodeChangeMiddleware( - useCallback( - (changes: NodeChange[]) => { - return changes.map((change) => { - if (change.type === 'position' && change.position) { - const { position } = change; - position.x = Math.min(Math.max(position.x, minX), maxX); - position.y = Math.min(Math.max(position.y, minY), maxY); - change.position = position; - } - return change; - }); - }, - [minX, minY, maxX, maxY] - ) - ); - - return null; -} - const OverviewFlow = () => { const [nodes, , onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); @@ -267,9 +236,8 @@ const OverviewFlow = () => { maxZoom={Infinity} onBeforeDelete={onBeforeDelete} onDelete={onDelete} - // onPaneMouseMove={onPaneMouseMove} + onPaneMouseMove={onPaneMouseMove} > - diff --git a/packages/react/src/components/BatchProvider/index.tsx b/packages/react/src/components/BatchProvider/index.tsx index d70d6fa8..28f3aa4b 100644 --- a/packages/react/src/components/BatchProvider/index.tsx +++ b/packages/react/src/components/BatchProvider/index.tsx @@ -53,8 +53,6 @@ export function BatchProvider[]; - console.log('this workds'); - for (const middleware of nodeChangeMiddleware.values()) { changes = middleware(changes); }