Merge branch 'next' into handle-connection-fixes

This commit is contained in:
peterkogo
2024-02-27 17:02:09 +01:00
28 changed files with 362 additions and 60 deletions
@@ -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}
+14 -2
View File
@@ -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);
}
},
+4 -1
View File
@@ -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;
+1
View File
@@ -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> = {