merge next
This commit is contained in:
@@ -10,18 +10,24 @@ const selector = (s: ReactFlowStore) => ({
|
||||
position: s.connectionStartHandle ? s.connectionPosition : null,
|
||||
});
|
||||
|
||||
type UseConnectionResult = {
|
||||
/** The start handle where the user interaction started or null */
|
||||
startHandle: ReactFlowStore['connectionStartHandle'];
|
||||
/** The target handle that's inside the connection radius or null */
|
||||
endHandle: ReactFlowStore['connectionEndHandle'];
|
||||
/** The current connection status 'valid', 'invalid' or null*/
|
||||
status: ReactFlowStore['connectionStatus'];
|
||||
/** The current connection position or null */
|
||||
position: ReactFlowStore['connectionPosition'] | null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook for accessing the ongoing connection.
|
||||
*
|
||||
* @public
|
||||
* @returns ongoing connection: startHandle, endHandle, status, position
|
||||
* @returns ongoing connection
|
||||
*/
|
||||
export function useConnection(): {
|
||||
startHandle: ReactFlowStore['connectionStartHandle'];
|
||||
endHandle: ReactFlowStore['connectionEndHandle'];
|
||||
status: ReactFlowStore['connectionStatus'];
|
||||
position: ReactFlowStore['connectionPosition'] | null;
|
||||
} {
|
||||
export function useConnection(): UseConnectionResult {
|
||||
const ongoingConnection = useStore(selector, shallow);
|
||||
|
||||
return ongoingConnection;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { handleNodeClick } from '../components/Nodes/utils';
|
||||
import { useStoreApi } from './useStore';
|
||||
|
||||
type UseDragParams = {
|
||||
nodeRef: RefObject<Element>;
|
||||
nodeRef: RefObject<HTMLDivElement>;
|
||||
disabled?: boolean;
|
||||
noDragClassName?: string;
|
||||
handleSelector?: string;
|
||||
@@ -39,7 +39,7 @@ export function useDrag({
|
||||
handleNodeClick({
|
||||
id,
|
||||
store,
|
||||
nodeRef: nodeRef as RefObject<HTMLDivElement>,
|
||||
nodeRef,
|
||||
});
|
||||
},
|
||||
onDragStart: () => {
|
||||
|
||||
@@ -13,7 +13,7 @@ type useHandleConnectionsParams = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to check if a <Handle /> is connected to another <Handle /> and get the connections.
|
||||
* Hook to check if a <Handle /> is connected to another <Handle /> and get the connections.
|
||||
*
|
||||
* @public
|
||||
* @param param.type - handle type 'source' or 'target'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback } from 'react';
|
||||
import { XYPosition, calcNextPosition, snapPosition } from '@xyflow/system';
|
||||
import { calculateNodePosition, snapPosition, type XYPosition } from '@xyflow/system';
|
||||
|
||||
import { Node } from '../types';
|
||||
import { useStoreApi } from './useStore';
|
||||
@@ -17,7 +17,17 @@ export function useMoveSelectedNodes() {
|
||||
const store = useStoreApi();
|
||||
|
||||
const moveSelectedNodes = useCallback((params: { direction: XYPosition; factor: number }) => {
|
||||
const { nodeExtent, nodes, snapToGrid, snapGrid, nodesDraggable, onError, updateNodePositions } = store.getState();
|
||||
const {
|
||||
nodeExtent,
|
||||
nodes,
|
||||
snapToGrid,
|
||||
snapGrid,
|
||||
nodesDraggable,
|
||||
onError,
|
||||
updateNodePositions,
|
||||
nodeLookup,
|
||||
nodeOrigin,
|
||||
} = store.getState();
|
||||
const selectedNodes = nodes.filter(selectedAndDraggable(nodesDraggable));
|
||||
// by default a node moves 5px on each key press
|
||||
// if snap grid is enabled, we use that for the velocity
|
||||
@@ -30,27 +40,24 @@ export function useMoveSelectedNodes() {
|
||||
const nodeUpdates = selectedNodes.map((node) => {
|
||||
if (node.computed?.positionAbsolute) {
|
||||
let nextPosition = {
|
||||
x: node.computed?.positionAbsolute.x + xDiff,
|
||||
y: node.computed?.positionAbsolute.y + yDiff,
|
||||
x: node.computed.positionAbsolute.x + xDiff,
|
||||
y: node.computed.positionAbsolute.y + yDiff,
|
||||
};
|
||||
|
||||
if (snapToGrid) {
|
||||
nextPosition = snapPosition(nextPosition, snapGrid);
|
||||
}
|
||||
|
||||
const { positionAbsolute, position } = calcNextPosition(
|
||||
node,
|
||||
const { position, positionAbsolute } = calculateNodePosition({
|
||||
nodeId: node.id,
|
||||
nextPosition,
|
||||
nodes,
|
||||
nodeLookup,
|
||||
nodeExtent,
|
||||
undefined,
|
||||
onError
|
||||
);
|
||||
nodeOrigin,
|
||||
onError,
|
||||
});
|
||||
|
||||
node.position = position;
|
||||
if (!node.computed) {
|
||||
node.computed = {};
|
||||
}
|
||||
node.computed.positionAbsolute = positionAbsolute;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,15 @@ const selector = (options: UseNodesInitializedOptions) => (s: ReactFlowState) =>
|
||||
return false;
|
||||
}
|
||||
|
||||
return s.nodes
|
||||
.filter((n) => (options.includeHiddenNodes ? true : !n.hidden))
|
||||
.every((n) => n[internalsSymbol]?.handleBounds !== undefined);
|
||||
for (const node of s.nodes) {
|
||||
if (options.includeHiddenNodes || !node.hidden) {
|
||||
if (node[internalsSymbol]?.handleBounds === undefined) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const defaultOptions = {
|
||||
|
||||
@@ -11,7 +11,7 @@ export type UseOnSelectionChangeOptions = {
|
||||
* Hook for registering an onSelectionChange handler.
|
||||
*
|
||||
* @public
|
||||
* @params params.onChange - The handler to register
|
||||
* @param params.onChange - The handler to register
|
||||
*/
|
||||
export function useOnSelectionChange({ onChange }: UseOnSelectionChangeOptions) {
|
||||
const store = useStoreApi();
|
||||
|
||||
@@ -86,31 +86,31 @@ const useViewportHelper = (): ViewportHelperFunctions => {
|
||||
|
||||
panZoom?.setViewport(viewport, { duration: options?.duration });
|
||||
},
|
||||
screenToFlowPosition: (position: XYPosition, options: { snapToGrid: boolean } = { snapToGrid: true }) => {
|
||||
screenToFlowPosition: (clientPosition: XYPosition, options: { snapToGrid: boolean } = { snapToGrid: true }) => {
|
||||
const { transform, snapGrid, domNode } = store.getState();
|
||||
|
||||
if (!domNode) {
|
||||
return position;
|
||||
return clientPosition;
|
||||
}
|
||||
|
||||
const { x: domX, y: domY } = domNode.getBoundingClientRect();
|
||||
|
||||
const correctedPosition = {
|
||||
x: position.x - domX,
|
||||
y: position.y - domY,
|
||||
x: clientPosition.x - domX,
|
||||
y: clientPosition.y - domY,
|
||||
};
|
||||
|
||||
return pointToRendererPoint(correctedPosition, transform, options.snapToGrid, snapGrid);
|
||||
},
|
||||
flowToScreenPosition: (position: XYPosition) => {
|
||||
flowToScreenPosition: (flowPosition: XYPosition) => {
|
||||
const { transform, domNode } = store.getState();
|
||||
|
||||
if (!domNode) {
|
||||
return position;
|
||||
return flowPosition;
|
||||
}
|
||||
|
||||
const { x: domX, y: domY } = domNode.getBoundingClientRect();
|
||||
const rendererPosition = rendererPointToPoint(position, transform);
|
||||
const rendererPosition = rendererPointToPoint(flowPosition, transform);
|
||||
|
||||
return {
|
||||
x: rendererPosition.x + domX,
|
||||
|
||||
Reference in New Issue
Block a user