UNPKG

@matthewgapp/solidjs-flow

Version:

React Flow - A highly customizable React library for building node-based editors and interactive flow charts.

66 lines (51 loc) 2.06 kB
// 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 = (params: { direction: XYPosition; factor: number }) => { const { nodeExtent, snapToGrid, snapGrid, nodesDraggable, onError, updateNodePositions, nodeLookup, nodeOrigin } = store; const nodeUpdates = new Map(); const isSelected = selectedAndDraggable(nodesDraggable.get()); // 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.get()[0] : 5; const yVelo = snapToGrid ? snapGrid.get()[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.get()); } const { position, positionAbsolute } = calculateNodePosition({ nodeId: node.id, nextPosition, nodeLookup, nodeExtent: nodeExtent.get(), nodeOrigin: nodeOrigin.get(), onError: onError.get(), }); node.position = position; node.internals.positionAbsolute = positionAbsolute; nodeUpdates.set(node.id, node); } updateNodePositions(nodeUpdates); }; return moveSelectedNodes; }