feat(autoPan): add props, handle scale
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import type { MouseEvent as ReactMouseEvent } from 'react';
|
||||
import { StoreApi } from 'zustand';
|
||||
|
||||
import { clamp, getHostForElement, getVelocity } from '../../utils';
|
||||
import { getHostForElement, getVelocity } from '../../utils';
|
||||
import { ConnectionMode } from '../../types';
|
||||
import type { OnConnect, Connection, HandleType, ReactFlowState, XYPosition } from '../../types';
|
||||
|
||||
@@ -100,13 +100,13 @@ export function handleMouseDown({
|
||||
}): void {
|
||||
// when react-flow is used inside a shadow root we can't use document
|
||||
const doc = getHostForElement(event.target as HTMLElement);
|
||||
const { onConnectStart, connectionMode, domNode } = getState();
|
||||
const { onConnectStart, connectionMode, domNode, autoPanOnConnect } = getState();
|
||||
let connectionPosition: XYPosition | null = null;
|
||||
let requestAnimationFrameId = 0;
|
||||
|
||||
// when the user is moving the mouse close to the edge of the canvas while connecting we move the canvas
|
||||
const updateViewport = (): void => {
|
||||
if (!connectionPosition || !containerBounds) {
|
||||
if (!connectionPosition || !containerBounds || !autoPanOnConnect) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ export function handleMouseDown({
|
||||
const handleType = elementEdgeUpdaterType ? elementEdgeUpdaterType : elementBelowIsTarget ? 'target' : 'source';
|
||||
const containerBounds = domNode.getBoundingClientRect();
|
||||
let recentHoveredHandle: Element;
|
||||
|
||||
connectionPosition = {
|
||||
x: event.clientX - containerBounds.left,
|
||||
y: event.clientY - containerBounds.top,
|
||||
|
||||
@@ -45,6 +45,8 @@ type StoreUpdaterProps = Pick<
|
||||
| 'noPanClassName'
|
||||
| 'nodeOrigin'
|
||||
| 'elevateNodesOnSelect'
|
||||
| 'autoPanOnConnect'
|
||||
| 'autoPanOnNodeDrag'
|
||||
> & { rfId: string };
|
||||
|
||||
const selector = (s: ReactFlowState) => ({
|
||||
@@ -119,6 +121,8 @@ const StoreUpdater = ({
|
||||
noPanClassName,
|
||||
nodeOrigin,
|
||||
rfId,
|
||||
autoPanOnConnect,
|
||||
autoPanOnNodeDrag,
|
||||
}: StoreUpdaterProps) => {
|
||||
const {
|
||||
setNodes,
|
||||
@@ -172,6 +176,8 @@ const StoreUpdater = ({
|
||||
useDirectStoreUpdater('noPanClassName', noPanClassName, store.setState);
|
||||
useDirectStoreUpdater('nodeOrigin', nodeOrigin, store.setState);
|
||||
useDirectStoreUpdater('rfId', rfId, store.setState);
|
||||
useDirectStoreUpdater('autoPanOnConnect', autoPanOnConnect, store.setState);
|
||||
useDirectStoreUpdater('autoPanOnNodeDrag', autoPanOnNodeDrag, store.setState);
|
||||
|
||||
useStoreUpdater<Node[]>(nodes, setNodes);
|
||||
useStoreUpdater<Edge[]>(edges, setEdges);
|
||||
|
||||
@@ -160,6 +160,8 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
||||
elevateNodesOnSelect = true,
|
||||
elevateEdgesOnSelect = false,
|
||||
disableKeyboardA11y = false,
|
||||
autoPanOnConnect = true,
|
||||
autoPanOnNodeDrag = true,
|
||||
style,
|
||||
id,
|
||||
...rest
|
||||
@@ -287,6 +289,8 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
||||
noPanClassName={noPanClassName}
|
||||
nodeOrigin={nodeOrigin}
|
||||
rfId={rfId}
|
||||
autoPanOnConnect={autoPanOnConnect}
|
||||
autoPanOnNodeDrag={autoPanOnNodeDrag}
|
||||
/>
|
||||
<SelectionListener onSelectionChange={onSelectionChange} />
|
||||
{children}
|
||||
|
||||
@@ -114,8 +114,10 @@ function useDrag({
|
||||
const yMovement = getVelocity(centerPosition.current.y, 35, containerBounds.current.height - 35) * 20;
|
||||
|
||||
if (xMovement !== 0 || yMovement !== 0) {
|
||||
lastPos.current.x = (lastPos.current.x ?? 0) + xMovement * -1;
|
||||
lastPos.current.y = (lastPos.current.y ?? 0) + yMovement * -1;
|
||||
const scale = store.getState().transform[2];
|
||||
|
||||
lastPos.current.x = (lastPos.current.x ?? 0) - xMovement / scale;
|
||||
lastPos.current.y = (lastPos.current.y ?? 0) - yMovement / scale;
|
||||
|
||||
updateNodes(lastPos.current as XYPosition);
|
||||
|
||||
@@ -175,8 +177,9 @@ function useDrag({
|
||||
})
|
||||
.on('drag', (event: UseDragEvent) => {
|
||||
const pointerPos = getPointerPosition(event);
|
||||
const { autoPanOnNodeDrag } = store.getState();
|
||||
|
||||
if (!animationFrameStarted.current) {
|
||||
if (!animationFrameStarted.current && autoPanOnNodeDrag) {
|
||||
animationFrameStarted.current = true;
|
||||
updateViewport();
|
||||
}
|
||||
@@ -199,6 +202,7 @@ function useDrag({
|
||||
setDragging(false);
|
||||
animationFrameStarted.current = false;
|
||||
cancelAnimationFrame(requestAnimationFrameId.current);
|
||||
|
||||
if (dragItems.current) {
|
||||
const { updateNodePositions, nodeInternals, onNodeDragStop, onSelectionDragStop } = store.getState();
|
||||
const onStop = nodeId ? onNodeDragStop : wrapSelectionDragFunc(onSelectionDragStop);
|
||||
|
||||
@@ -56,6 +56,8 @@ const initialState: ReactFlowStore = {
|
||||
connectOnClick: true,
|
||||
|
||||
ariaLiveMessage: '',
|
||||
autoPanOnConnect: true,
|
||||
autoPanOnNodeDrag: true,
|
||||
};
|
||||
|
||||
export default initialState;
|
||||
|
||||
@@ -139,6 +139,8 @@ export type ReactFlowProps = HTMLAttributes<HTMLDivElement> & {
|
||||
elevateNodesOnSelect?: boolean;
|
||||
elevateEdgesOnSelect?: boolean;
|
||||
disableKeyboardA11y?: boolean;
|
||||
autoPanOnNodeDrag?: boolean;
|
||||
autoPanOnConnect?: boolean;
|
||||
};
|
||||
|
||||
export type ReactFlowRefType = HTMLDivElement;
|
||||
|
||||
@@ -210,6 +210,8 @@ export type ReactFlowStore = {
|
||||
onSelectionChange?: OnSelectionChangeFunc;
|
||||
|
||||
ariaLiveMessage: string;
|
||||
autoPanOnConnect: boolean;
|
||||
autoPanOnNodeDrag: boolean;
|
||||
};
|
||||
|
||||
export type ReactFlowActions = {
|
||||
|
||||
Reference in New Issue
Block a user