diff --git a/examples/react/src/examples/Undirectional/index.tsx b/examples/react/src/examples/Undirectional/index.tsx index d9391541..c4cf14a5 100644 --- a/examples/react/src/examples/Undirectional/index.tsx +++ b/examples/react/src/examples/Undirectional/index.tsx @@ -183,7 +183,7 @@ const getId = () => `${id++}`; const UpdateNodeInternalsFlow = () => { const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); - const { project } = useReactFlow(); + const { screenToFlowPosition } = useReactFlow(); const onConnect = useCallback((params: Edge | Connection) => setEdges((els) => addEdge(params, els)), [setEdges]); const onEdgeUpdate = useCallback( @@ -196,12 +196,12 @@ const UpdateNodeInternalsFlow = () => { setNodes((nds) => nds.concat({ id: getId(), - position: project({ x: evt.clientX, y: evt.clientY - 40 }), + position: screenToFlowPosition({ x: evt.clientX, y: evt.clientY }), type: 'custom', data: null, }) ), - [project, setNodes] + [screenToFlowPosition, setNodes] ); return ( diff --git a/examples/react/src/examples/UseReactFlow/index.tsx b/examples/react/src/examples/UseReactFlow/index.tsx index 584e6e7b..69f3c762 100644 --- a/examples/react/src/examples/UseReactFlow/index.tsx +++ b/examples/react/src/examples/UseReactFlow/index.tsx @@ -57,7 +57,7 @@ const UseZoomPanHelperFlow = () => { const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); const onConnect = (params: Connection | Edge) => setEdges((eds) => addEdge(params, eds)); const { - project, + screenToFlowPosition, setCenter, zoomIn, zoomOut, @@ -72,9 +72,9 @@ const UseZoomPanHelperFlow = () => { const onPaneClick = useCallback( (evt: MouseEvent) => { - const projectedPosition = project({ + const projectedPosition = screenToFlowPosition({ x: evt.clientX, - y: evt.clientY - 40, + y: evt.clientY, }); setNodes((nds) => @@ -87,7 +87,7 @@ const UseZoomPanHelperFlow = () => { }) ); }, - [project, setNodes] + [screenToFlowPosition, setNodes] ); const onNodeClick = useCallback( diff --git a/examples/react/src/examples/UseUpdateNodeInternals/index.tsx b/examples/react/src/examples/UseUpdateNodeInternals/index.tsx index 7de6cb9b..371d58b6 100644 --- a/examples/react/src/examples/UseUpdateNodeInternals/index.tsx +++ b/examples/react/src/examples/UseUpdateNodeInternals/index.tsx @@ -36,20 +36,20 @@ const UpdateNodeInternalsFlow = () => { const [edges, setEdges, onEdgesChange] = useEdgesState([]); const onConnect = useCallback((params: Edge | Connection) => setEdges((els) => addEdge(params, els)), [setEdges]); - const { project } = useReactFlow(); + const { screenToFlowPosition } = useReactFlow(); const onPaneClick = useCallback( (evt: MouseEvent) => setNodes((nds) => nds.concat({ id: getId(), - position: project({ x: evt.clientX, y: evt.clientY - 40 }), + position: screenToFlowPosition({ x: evt.clientX, y: evt.clientY }), data: { label: 'new node' }, targetPosition: Position.Left, sourcePosition: Position.Right, }) ), - [project, setNodes] + [screenToFlowPosition, setNodes] ); return ( diff --git a/examples/svelte/src/routes/examples/drag-n-drop/Flow.svelte b/examples/svelte/src/routes/examples/drag-n-drop/Flow.svelte index 661b7f5e..2826a8ea 100644 --- a/examples/svelte/src/routes/examples/drag-n-drop/Flow.svelte +++ b/examples/svelte/src/routes/examples/drag-n-drop/Flow.svelte @@ -69,10 +69,10 @@ return null; } - const type = event.dataTransfer.getData('application/svelteflow'); - const position = svelteFlow.project({ + const type = event.dataTransfer.getData('application/svelteflow') || 'default'; + const position = svelteFlow.screenToFlowPosition({ x: event.clientX, - y: event.clientY - 40 + y: event.clientY }); const newNode: Node = { id: `${Math.random()}`, @@ -81,7 +81,7 @@ data: { label: `${type} node` } }; - svelteFlow.nodes.update((nds) => nds.concat(newNode)); + nodes.update((nds) => nds.concat(newNode)); }; $: { diff --git a/packages/react/src/additional-components/MiniMap/MiniMap.tsx b/packages/react/src/additional-components/MiniMap/MiniMap.tsx index 9109a910..49e02573 100644 --- a/packages/react/src/additional-components/MiniMap/MiniMap.tsx +++ b/packages/react/src/additional-components/MiniMap/MiniMap.tsx @@ -3,7 +3,7 @@ import { memo, useEffect, useRef, type MouseEvent, useCallback } from 'react'; import cc from 'classcat'; import { shallow } from 'zustand/shallow'; -import { getRectOfNodes, getBoundsOfRects, XYMinimap, type Rect, type XYMinimapInstance } from '@xyflow/system'; +import { getNodesBounds, getBoundsOfRects, XYMinimap, type Rect, type XYMinimapInstance } from '@xyflow/system'; import { useStore, useStoreApi } from '../../hooks/useStore'; import Panel from '../../components/Panel'; @@ -25,7 +25,7 @@ const selector = (s: ReactFlowState) => { return { viewBB, - boundingRect: s.nodes.length > 0 ? getBoundsOfRects(getRectOfNodes(s.nodes, s.nodeOrigin), viewBB) : viewBB, + boundingRect: s.nodes.length > 0 ? getBoundsOfRects(getNodesBounds(s.nodes, s.nodeOrigin), viewBB) : viewBB, rfId: s.rfId, nodeOrigin: s.nodeOrigin, panZoom: s.panZoom, diff --git a/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx b/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx index 8710f88a..fc0c309f 100644 --- a/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx +++ b/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx @@ -1,7 +1,7 @@ import { useCallback, CSSProperties } from 'react'; import cc from 'classcat'; import { shallow } from 'zustand/shallow'; -import { getRectOfNodes, Transform, Rect, Position, internalsSymbol } from '@xyflow/system'; +import { getNodesBounds, Transform, Rect, Position, internalsSymbol } from '@xyflow/system'; import { Node, ReactFlowState } from '../../types'; import { useStore } from '../../hooks/useStore'; @@ -105,7 +105,7 @@ function NodeToolbar({ return null; } - const nodeRect: Rect = getRectOfNodes(nodes, nodeOrigin); + const nodeRect: Rect = getNodesBounds(nodes, nodeOrigin); const zIndex: number = Math.max(...nodes.map((node) => (node[internalsSymbol]?.z || 1) + 1)); const wrapperStyle: CSSProperties = { diff --git a/packages/react/src/components/NodesSelection/index.tsx b/packages/react/src/components/NodesSelection/index.tsx index f22c35ee..ec88fccd 100644 --- a/packages/react/src/components/NodesSelection/index.tsx +++ b/packages/react/src/components/NodesSelection/index.tsx @@ -6,7 +6,7 @@ import { memo, useRef, useEffect, type MouseEvent, type KeyboardEvent } from 'react'; import cc from 'classcat'; import { shallow } from 'zustand/shallow'; -import { getRectOfNodes } from '@xyflow/system'; +import { getNodesBounds } from '@xyflow/system'; import { useStore, useStoreApi } from '../../hooks/useStore'; import useDrag from '../../hooks/useDrag'; @@ -22,7 +22,7 @@ export type NodesSelectionProps = { const selector = (s: ReactFlowState) => { const selectedNodes = s.nodes.filter((n) => n.selected); - const { width, height, x, y } = getRectOfNodes(selectedNodes, s.nodeOrigin); + const { width, height, x, y } = getNodesBounds(selectedNodes, s.nodeOrigin); return { width, diff --git a/packages/react/src/hooks/useViewportHelper.ts b/packages/react/src/hooks/useViewportHelper.ts index 1872d414..f1099b43 100644 --- a/packages/react/src/hooks/useViewportHelper.ts +++ b/packages/react/src/hooks/useViewportHelper.ts @@ -1,7 +1,7 @@ import { useMemo } from 'react'; import { pointToRendererPoint, - getTransformForBounds, + getViewportForBounds, fitView, type XYPosition, rendererPointToPoint, @@ -76,50 +76,40 @@ const useViewportHelper = (): ViewportHelperFunctions => { }, fitBounds: (bounds, options) => { const { width, height, minZoom, maxZoom, panZoom } = store.getState(); - const [x, y, zoom] = getTransformForBounds(bounds, width, height, minZoom, maxZoom, options?.padding ?? 0.1); + const viewport = getViewportForBounds(bounds, width, height, minZoom, maxZoom, options?.padding ?? 0.1); - panZoom?.setViewport( - { - x, - y, - zoom, - }, - { duration: options?.duration } - ); + panZoom?.setViewport(viewport, { duration: options?.duration }); }, - project: (position: XYPosition) => { - const { transform, snapToGrid, snapGrid } = store.getState(); - return pointToRendererPoint(position, transform, snapToGrid, snapGrid); - }, - screenToFlowCoordinate: (position: XYPosition) => { + screenToFlowPosition: (position: XYPosition) => { const { transform, snapToGrid, snapGrid, domNode } = store.getState(); - if (domNode) { - const { x: domX, y: domY } = domNode.getBoundingClientRect(); - const correctedPosition = { - x: position.x - domX, - y: position.y - domY, - }; - - return pointToRendererPoint(correctedPosition, transform, snapToGrid, snapGrid || [1, 1]); + if (!domNode) { + return position; } - return { x: 0, y: 0 }; + const { x: domX, y: domY } = domNode.getBoundingClientRect(); + + const correctedPosition = { + x: position.x - domX, + y: position.y - domY, + }; + + return pointToRendererPoint(correctedPosition, transform, snapToGrid, snapGrid || [1, 1]); }, - flowToScreenCoordinate: (position: XYPosition) => { + flowToScreenPosition: (position: XYPosition) => { const { transform, domNode } = store.getState(); - if (domNode) { - const { x: domX, y: domY } = domNode.getBoundingClientRect(); - const rendererPosition = rendererPointToPoint(position, transform); - - return { - x: rendererPosition.x + domX, - y: rendererPosition.y + domY, - }; + if (!domNode) { + return position; } - return { x: 0, y: 0 }; + const { x: domX, y: domY } = domNode.getBoundingClientRect(); + const rendererPosition = rendererPointToPoint(position, transform); + + return { + x: rendererPosition.x + domX, + y: rendererPosition.y + domY, + }; }, viewportInitialized: panZoomInitialized, }; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 37a6bc74..75b86f24 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -85,6 +85,6 @@ export { getSmoothStepPath, type GetStraightPathParams, getStraightPath, - getTransformForBounds, - getRectOfNodes, + getViewportForBounds, + getNodesBounds, } from '@xyflow/system'; diff --git a/packages/react/src/store/initialState.ts b/packages/react/src/store/initialState.ts index 156d8d76..04d30a1c 100644 --- a/packages/react/src/store/initialState.ts +++ b/packages/react/src/store/initialState.ts @@ -2,8 +2,8 @@ import { infiniteExtent, ConnectionMode, updateNodes, - getRectOfNodes, - getTransformForBounds, + getNodesBounds, + getViewportForBounds, Transform, } from '@xyflow/system'; @@ -32,8 +32,9 @@ const getInitialState = ({ width: node.size?.width, height: node.size?.height, })); - const bounds = getRectOfNodes(nodesWithDimensions, [0, 0]); - transform = getTransformForBounds(bounds, width, height, 0.5, 2, 0.1); + const bounds = getNodesBounds(nodesWithDimensions, [0, 0]); + const { x, y, z } = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1); + transform = [x, y, z]; } return { diff --git a/packages/react/src/types/general.ts b/packages/react/src/types/general.ts index 2b2945a6..225e159c 100644 --- a/packages/react/src/types/general.ts +++ b/packages/react/src/types/general.ts @@ -11,7 +11,7 @@ import { GetViewport, SetCenter, FitBounds, - Project, + XYPosition, } from '@xyflow/system'; import type { NodeChange, EdgeChange, Node, WrapNodeProps, Edge, EdgeProps, WrapEdgeProps, ReactFlowInstance } from '.'; @@ -54,8 +54,7 @@ export type ViewportHelperFunctions = { fitView: FitView; setCenter: SetCenter; fitBounds: FitBounds; - project: Project; - screenToFlowCoordinate: Project; - flowToScreenCoordinate: Project; + screenToFlowPosition: (position: XYPosition) => XYPosition; + flowToScreenPosition: (position: XYPosition) => XYPosition; viewportInitialized: boolean; }; diff --git a/packages/svelte/src/lib/components/NodeSelection/NodeSelection.svelte b/packages/svelte/src/lib/components/NodeSelection/NodeSelection.svelte index 1a409938..98c48d8c 100644 --- a/packages/svelte/src/lib/components/NodeSelection/NodeSelection.svelte +++ b/packages/svelte/src/lib/components/NodeSelection/NodeSelection.svelte @@ -1,5 +1,5 @@ {#if selectedNodes && $selectionRectMode === 'nodes'}