refactor(react): separate user nodes and indernal nodes
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { useCallback } from 'react';
|
||||
import { calculateNodePosition, snapPosition, type XYPosition } from '@xyflow/system';
|
||||
|
||||
import { Node } from '../types';
|
||||
import { type Node } from '../types';
|
||||
import { useStoreApi } from './useStore';
|
||||
|
||||
const selectedAndDraggable = (nodesDraggable: boolean) => (n: Node) =>
|
||||
@@ -17,18 +17,11 @@ export function useMoveSelectedNodes() {
|
||||
const store = useStoreApi();
|
||||
|
||||
const moveSelectedNodes = useCallback((params: { direction: XYPosition; factor: number }) => {
|
||||
const {
|
||||
nodeExtent,
|
||||
nodes,
|
||||
snapToGrid,
|
||||
snapGrid,
|
||||
nodesDraggable,
|
||||
onError,
|
||||
updateNodePositions,
|
||||
nodeLookup,
|
||||
nodeOrigin,
|
||||
} = store.getState();
|
||||
const selectedNodes = nodes.filter(selectedAndDraggable(nodesDraggable));
|
||||
const { nodeExtent, snapToGrid, snapGrid, nodesDraggable, onError, updateNodePositions, nodeLookup, nodeOrigin } =
|
||||
store.getState();
|
||||
const nodeUpdates = [];
|
||||
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;
|
||||
@@ -37,32 +30,34 @@ export function useMoveSelectedNodes() {
|
||||
const xDiff = params.direction.x * xVelo * params.factor;
|
||||
const yDiff = params.direction.y * yVelo * params.factor;
|
||||
|
||||
const nodeUpdates = selectedNodes.map((node) => {
|
||||
if (node.computed?.positionAbsolute) {
|
||||
let nextPosition = {
|
||||
x: node.computed.positionAbsolute.x + xDiff,
|
||||
y: node.computed.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.computed.positionAbsolute = positionAbsolute;
|
||||
for (const [, node] of nodeLookup) {
|
||||
if (!isSelected(node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return node;
|
||||
});
|
||||
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.push(node);
|
||||
}
|
||||
|
||||
updateNodePositions(nodeUpdates);
|
||||
}, []);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { internalsSymbol } from '@xyflow/system';
|
||||
|
||||
import { useStore } from './useStore';
|
||||
import type { ReactFlowState } from '../types';
|
||||
|
||||
@@ -8,13 +6,13 @@ export type UseNodesInitializedOptions = {
|
||||
};
|
||||
|
||||
const selector = (options: UseNodesInitializedOptions) => (s: ReactFlowState) => {
|
||||
if (s.nodes.length === 0) {
|
||||
if (s.nodeLookup.size === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const node of s.nodes) {
|
||||
for (const [, node] of s.nodeLookup) {
|
||||
if (options.includeHiddenNodes || !node.hidden) {
|
||||
if (node[internalsSymbol]?.handleBounds === undefined) {
|
||||
if (node.internals.handleBounds === undefined) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
|
||||
}, []);
|
||||
|
||||
const getNode = useCallback<Instance.GetNode<NodeType>>((id) => {
|
||||
return store.getState().nodeLookup.get(id) as NodeType;
|
||||
return store.getState().nodeLookup.get(id)?.internals.userProvidedNode as NodeType;
|
||||
}, []);
|
||||
|
||||
const getEdges = useCallback<Instance.GetEdges<EdgeType>>(() => {
|
||||
@@ -227,7 +227,7 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
|
||||
const node =
|
||||
isNode(nodeOrRect) && nodeHasDimensions(nodeOrRect)
|
||||
? nodeOrRect
|
||||
: (store.getState().nodeLookup.get(nodeOrRect.id) as NodeType);
|
||||
: (store.getState().nodeLookup.get(nodeOrRect.id)?.internals.userProvidedNode as NodeType);
|
||||
|
||||
return node ? nodeToRect(node) : null;
|
||||
}, []);
|
||||
@@ -242,7 +242,9 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
|
||||
}
|
||||
|
||||
return (nodes || store.getState().nodes).filter((n) => {
|
||||
if (!isRect && (n.id === nodeOrRect!.id || !n.computed?.positionAbsolute)) {
|
||||
const internalNode = store.getState().nodeLookup.get(n.id);
|
||||
|
||||
if (internalNode && !isRect && (n.id === nodeOrRect!.id || !internalNode.internals.positionAbsolute)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user