Merge branch 'next' into handle-connection-fixes
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { ComponentType, memo } from 'react';
|
||||
import { NodeOrigin, getNodePositionWithOrigin } from '@xyflow/system';
|
||||
import { NodeOrigin, getNodeDimensions, getNodePositionWithOrigin, nodeHasDimensions } from '@xyflow/system';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
import { useStore } from '../../hooks/useStore';
|
||||
@@ -94,16 +94,19 @@ function NodeComponentWrapperInner<NodeType extends Node>({
|
||||
y,
|
||||
};
|
||||
}, shallow);
|
||||
if (!node || node.hidden || !(node.computed?.width || node.width) || !(node.computed?.height || node.height)) {
|
||||
|
||||
if (!node || node.hidden || !nodeHasDimensions(node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { width, height } = getNodeDimensions(node);
|
||||
|
||||
return (
|
||||
<NodeComponent
|
||||
x={x}
|
||||
y={y}
|
||||
width={node.computed?.width ?? node.width ?? 0}
|
||||
height={node.computed?.height ?? node.height ?? 0}
|
||||
width={width}
|
||||
height={height}
|
||||
style={node.style}
|
||||
selected={!!node.selected}
|
||||
className={nodeClassNameFunc(node)}
|
||||
|
||||
@@ -5,9 +5,11 @@ import {
|
||||
clampPosition,
|
||||
elementSelectionKeys,
|
||||
errorMessages,
|
||||
getNodeDimensions,
|
||||
getPositionWithOrigin,
|
||||
internalsSymbol,
|
||||
isInputDOMNode,
|
||||
nodeHasDimensions,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import { useStore, useStoreApi } from '../../hooks/useStore';
|
||||
@@ -16,7 +18,7 @@ import { ARIA_NODE_DESC_KEY } from '../A11yDescriptions';
|
||||
import { useDrag } from '../../hooks/useDrag';
|
||||
import { useMoveSelectedNodes } from '../../hooks/useMoveSelectedNodes';
|
||||
import { handleNodeClick } from '../Nodes/utils';
|
||||
import { arrowKeyDiffs, builtinNodeTypes } from './utils';
|
||||
import { arrowKeyDiffs, builtinNodeTypes, getNodeInlineStyleDimensions } from './utils';
|
||||
import type { Node, NodeWrapperProps } from '../../types';
|
||||
|
||||
export function NodeWrapper<NodeType extends Node>({
|
||||
@@ -79,11 +81,9 @@ export function NodeWrapper<NodeType extends Node>({
|
||||
const prevTargetPosition = useRef(node.targetPosition);
|
||||
const prevType = useRef(nodeType);
|
||||
|
||||
const width = node.width ?? undefined;
|
||||
const height = node.height ?? undefined;
|
||||
const computedWidth = node.computed?.width;
|
||||
const computedHeight = node.computed?.height;
|
||||
const initialized = (!!computedWidth && !!computedHeight) || (!!width && !!height);
|
||||
const nodeDimensions = getNodeDimensions(node);
|
||||
const inlineDimensions = getNodeInlineStyleDimensions(node);
|
||||
const initialized = nodeHasDimensions(node);
|
||||
const hasHandleBounds = !!node[internalsSymbol]?.handleBounds;
|
||||
|
||||
const moveSelectedNodes = useMoveSelectedNodes();
|
||||
@@ -143,8 +143,7 @@ export function NodeWrapper<NodeType extends Node>({
|
||||
const positionAbsoluteOrigin = getPositionWithOrigin({
|
||||
x: positionAbsoluteX,
|
||||
y: positionAbsoluteY,
|
||||
width: computedWidth ?? width ?? 0,
|
||||
height: computedHeight ?? height ?? 0,
|
||||
...nodeDimensions,
|
||||
origin: node.origin || nodeOrigin,
|
||||
});
|
||||
const hasPointerEvents = isSelectable || isDraggable || onClick || onMouseEnter || onMouseMove || onMouseLeave;
|
||||
@@ -226,8 +225,7 @@ export function NodeWrapper<NodeType extends Node>({
|
||||
pointerEvents: hasPointerEvents ? 'all' : 'none',
|
||||
visibility: initialized ? 'visible' : 'hidden',
|
||||
...node.style,
|
||||
width: width ?? node.style?.width,
|
||||
height: height ?? node.style?.height,
|
||||
...inlineDimensions,
|
||||
}}
|
||||
data-id={id}
|
||||
data-testid={`rf__node-${id}`}
|
||||
@@ -248,8 +246,6 @@ export function NodeWrapper<NodeType extends Node>({
|
||||
id={id}
|
||||
data={node.data}
|
||||
type={nodeType}
|
||||
width={computedWidth}
|
||||
height={computedHeight}
|
||||
positionAbsoluteX={positionAbsoluteX}
|
||||
positionAbsoluteY={positionAbsoluteY}
|
||||
selected={node.selected}
|
||||
@@ -259,6 +255,7 @@ export function NodeWrapper<NodeType extends Node>({
|
||||
dragging={dragging}
|
||||
dragHandle={node.dragHandle}
|
||||
zIndex={zIndex}
|
||||
{...nodeDimensions}
|
||||
/>
|
||||
</Provider>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { InputNode } from '../Nodes/InputNode';
|
||||
import { DefaultNode } from '../Nodes/DefaultNode';
|
||||
import { GroupNode } from '../Nodes/GroupNode';
|
||||
import { OutputNode } from '../Nodes/OutputNode';
|
||||
import type { NodeTypes } from '../../types';
|
||||
import type { Node, NodeTypes } from '../../types';
|
||||
|
||||
export const arrowKeyDiffs: Record<string, XYPosition> = {
|
||||
ArrowUp: { x: 0, y: -1 },
|
||||
@@ -20,3 +20,22 @@ export const builtinNodeTypes: NodeTypes = {
|
||||
output: OutputNode as ComponentType<NodeProps>,
|
||||
group: GroupNode as ComponentType<NodeProps>,
|
||||
};
|
||||
|
||||
export function getNodeInlineStyleDimensions<NodeType extends Node = Node>(
|
||||
node: NodeType
|
||||
): {
|
||||
width: number | string | undefined;
|
||||
height: number | string | undefined;
|
||||
} {
|
||||
if (!node.computed) {
|
||||
return {
|
||||
width: node.width ?? node.initialWidth ?? node.style?.width,
|
||||
height: node.height ?? node.initialHeight ?? node.style?.height,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
width: node.width ?? node.style?.width,
|
||||
height: node.height ?? node.style?.height,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ const reactFlowFieldsToTrack = [
|
||||
'selectNodesOnDrag',
|
||||
'nodeDragThreshold',
|
||||
'onBeforeDelete',
|
||||
'debug',
|
||||
] as const;
|
||||
|
||||
type ReactFlowFieldsToTrack = (typeof reactFlowFieldsToTrack)[number];
|
||||
|
||||
@@ -139,6 +139,7 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
|
||||
width,
|
||||
height,
|
||||
colorMode = 'light',
|
||||
debug,
|
||||
...rest
|
||||
}: ReactFlowProps<NodeType, EdgeType>,
|
||||
ref: ForwardedRef<ReactFlowRefType>
|
||||
@@ -274,6 +275,7 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
|
||||
selectNodesOnDrag={selectNodesOnDrag}
|
||||
nodeDragThreshold={nodeDragThreshold}
|
||||
onBeforeDelete={onBeforeDelete}
|
||||
debug={debug}
|
||||
/>
|
||||
<SelectionListener onSelectionChange={onSelectionChange} />
|
||||
{children}
|
||||
|
||||
@@ -89,6 +89,7 @@ const createRFStore = ({
|
||||
fitViewOnInitOptions,
|
||||
domNode,
|
||||
nodeOrigin,
|
||||
debug,
|
||||
} = get();
|
||||
const changes: NodeDimensionChange[] = [];
|
||||
|
||||
@@ -130,6 +131,9 @@ const createRFStore = ({
|
||||
set({ nodes: nextNodes, fitViewDone: nextFitViewDone });
|
||||
|
||||
if (changes?.length > 0) {
|
||||
if (debug) {
|
||||
console.log('React Flow: trigger node changes', changes);
|
||||
}
|
||||
onNodesChange?.(changes);
|
||||
}
|
||||
},
|
||||
@@ -149,7 +153,7 @@ const createRFStore = ({
|
||||
get().triggerNodeChanges(changes);
|
||||
},
|
||||
triggerNodeChanges: (changes) => {
|
||||
const { onNodesChange, setNodes, nodes, hasDefaultNodes } = get();
|
||||
const { onNodesChange, setNodes, nodes, hasDefaultNodes, debug } = get();
|
||||
|
||||
if (changes?.length) {
|
||||
if (hasDefaultNodes) {
|
||||
@@ -157,11 +161,15 @@ const createRFStore = ({
|
||||
setNodes(updatedNodes);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
console.log('React Flow: trigger node changes', changes);
|
||||
}
|
||||
|
||||
onNodesChange?.(changes);
|
||||
}
|
||||
},
|
||||
triggerEdgeChanges: (changes) => {
|
||||
const { onEdgesChange, setEdges, edges, hasDefaultEdges } = get();
|
||||
const { onEdgesChange, setEdges, edges, hasDefaultEdges, debug } = get();
|
||||
|
||||
if (changes?.length) {
|
||||
if (hasDefaultEdges) {
|
||||
@@ -169,6 +177,10 @@ const createRFStore = ({
|
||||
setEdges(updatedEdges);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
console.log('React Flow: trigger edge changes', changes);
|
||||
}
|
||||
|
||||
onEdgesChange?.(changes);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -43,7 +43,9 @@ const getInitialState = ({
|
||||
let transform: Transform = [0, 0, 1];
|
||||
|
||||
if (fitView && width && height) {
|
||||
const nodesWithDimensions = nextNodes.filter((node) => node.width && node.height);
|
||||
const nodesWithDimensions = nextNodes.filter(
|
||||
(node) => (node.width || node.initialWidth) && (node.height || node.initialHeight)
|
||||
);
|
||||
// @todo users nodeOrigin should be used here
|
||||
const bounds = getNodesBounds(nodesWithDimensions, { nodeOrigin: [0, 0] });
|
||||
const { x, y, zoom } = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
|
||||
@@ -113,6 +115,7 @@ const getInitialState = ({
|
||||
onSelectionChangeHandlers: [],
|
||||
|
||||
lib: 'react',
|
||||
debug: false,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -503,6 +503,11 @@ export interface ReactFlowProps<NodeType extends Node = Node, EdgeType extends E
|
||||
* @example 'system' | 'light' | 'dark'
|
||||
*/
|
||||
colorMode?: ColorMode;
|
||||
/** If set true, some debug information will be logged to the console like which events are fired.
|
||||
*
|
||||
* @default undefined
|
||||
*/
|
||||
debug?: boolean;
|
||||
}
|
||||
|
||||
export type ReactFlowRefType = HTMLDivElement;
|
||||
|
||||
@@ -146,6 +146,7 @@ export type ReactFlowStore<NodeType extends Node = Node, EdgeType extends Edge =
|
||||
isValidConnection?: IsValidConnection<EdgeType>;
|
||||
|
||||
lib: string;
|
||||
debug: boolean;
|
||||
};
|
||||
|
||||
export type ReactFlowActions<NodeType extends Node, EdgeType extends Edge> = {
|
||||
|
||||
Reference in New Issue
Block a user