69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
import { useCallback } from 'react';
|
|
import { calculateNodePosition, snapPosition, type XYPosition } from '@xyflow/system';
|
|
|
|
import { type Node } from '../types';
|
|
import { useStoreApi } from './useStore';
|
|
|
|
const selectedAndDraggable = (nodesDraggable: boolean) => (n: Node) =>
|
|
n.selected && (n.draggable || (nodesDraggable && typeof n.draggable === 'undefined'));
|
|
|
|
/**
|
|
* Hook for updating node positions by passing a direction and factor
|
|
*
|
|
* @internal
|
|
* @returns function for updating node positions
|
|
*/
|
|
export function useMoveSelectedNodes() {
|
|
const store = useStoreApi();
|
|
|
|
const moveSelectedNodes = useCallback((params: { direction: XYPosition; factor: number }) => {
|
|
const { nodeExtent, snapToGrid, snapGrid, nodesDraggable, onError, updateNodePositions, nodeLookup, nodeOrigin } =
|
|
store.getState();
|
|
const nodeUpdates = new Map();
|
|
const isSelected = selectedAndDraggable(nodesDraggable);
|
|
|
|
/*
|
|
* by default a node moves 5px on each key press
|
|
* if snap grid is enabled, we use that for the velocity
|
|
*/
|
|
const xVelo = snapToGrid ? snapGrid[0] : 5;
|
|
const yVelo = snapToGrid ? snapGrid[1] : 5;
|
|
|
|
const xDiff = params.direction.x * xVelo * params.factor;
|
|
const yDiff = params.direction.y * yVelo * params.factor;
|
|
|
|
for (const [, node] of nodeLookup) {
|
|
if (!isSelected(node)) {
|
|
continue;
|
|
}
|
|
|
|
let nextPosition = {
|
|
x: node.internals.positionAbsolute.x + xDiff,
|
|
y: node.internals.positionAbsolute.y + yDiff,
|
|
};
|
|
|
|
if (snapToGrid) {
|
|
nextPosition = snapPosition(nextPosition, snapGrid);
|
|
}
|
|
|
|
const { position, positionAbsolute } = calculateNodePosition({
|
|
nodeId: node.id,
|
|
nextPosition,
|
|
nodeLookup,
|
|
nodeExtent,
|
|
nodeOrigin,
|
|
onError,
|
|
});
|
|
|
|
node.position = position;
|
|
node.internals.positionAbsolute = positionAbsolute;
|
|
|
|
nodeUpdates.set(node.id, node);
|
|
}
|
|
|
|
updateNodePositions(nodeUpdates);
|
|
}, []);
|
|
|
|
return moveSelectedNodes;
|
|
}
|