refactor(react): handle parent expand in store instead of applyChanges
This commit is contained in:
@@ -88,9 +88,11 @@ export function NodeWrapper<NodeType extends Node>({
|
||||
const moveSelectedNodes = useMoveSelectedNodes();
|
||||
|
||||
useEffect(() => {
|
||||
const currNode = nodeRef.current;
|
||||
|
||||
return () => {
|
||||
if (nodeRef.current) {
|
||||
resizeObserver?.unobserve(nodeRef.current);
|
||||
if (currNode) {
|
||||
resizeObserver?.unobserve(currNode);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
@@ -122,7 +124,7 @@ export function NodeWrapper<NodeType extends Node>({
|
||||
if (targetPosChanged) {
|
||||
prevTargetPosition.current = node.targetPosition;
|
||||
}
|
||||
store.getState().updateNodeDimensions(new Map([[id, { id, nodeElement: nodeRef.current, forceUpdate: true }]]));
|
||||
store.getState().updateNodeDimensions(new Map([[id, { id, nodeElement: nodeRef.current, force: true }]]));
|
||||
}
|
||||
}, [id, nodeType, node.sourcePosition, node.targetPosition]);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useEffect, useMemo, useRef } from 'react';
|
||||
|
||||
import { ReactFlowState } from '../../types';
|
||||
import { useStore } from '../../hooks/useStore';
|
||||
import { NodeDimensionUpdate } from '@xyflow/system';
|
||||
|
||||
const selector = (s: ReactFlowState) => s.updateNodeDimensions;
|
||||
|
||||
@@ -15,14 +16,13 @@ export function useResizeObserver() {
|
||||
}
|
||||
|
||||
const observer = new ResizeObserver((entries: ResizeObserverEntry[]) => {
|
||||
const updates = new Map();
|
||||
const updates = new Map<string, NodeDimensionUpdate>();
|
||||
|
||||
entries.forEach((entry: ResizeObserverEntry) => {
|
||||
const id = entry.target.getAttribute('data-id') as string;
|
||||
updates.set(id, {
|
||||
id,
|
||||
nodeElement: entry.target as HTMLDivElement,
|
||||
forceUpdate: true,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ export function useUpdateNodeInternals(): UpdateNodeInternals {
|
||||
const nodeElement = domNode?.querySelector(`.react-flow__node[data-id="${updateId}"]`) as HTMLDivElement;
|
||||
|
||||
if (nodeElement) {
|
||||
updates.set(updateId, { id: updateId, nodeElement, forceUpdate: true });
|
||||
updates.set(updateId, { id: updateId, nodeElement, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ export { useNodesData } from './hooks/useNodesData';
|
||||
export { useConnection } from './hooks/useConnection';
|
||||
export { useNodeId } from './contexts/NodeIdContext';
|
||||
|
||||
export { applyNodeChanges, applyEdgeChanges, handleParentExpand } from './utils/changes';
|
||||
export { applyNodeChanges, applyEdgeChanges } from './utils/changes';
|
||||
export { isNode, isEdge } from './utils/general';
|
||||
|
||||
export * from './additional-components';
|
||||
|
||||
@@ -5,9 +5,10 @@ import {
|
||||
adoptUserProvidedNodes,
|
||||
updateAbsolutePositions,
|
||||
panBy as panBySystem,
|
||||
Dimensions,
|
||||
updateNodeDimensions as updateNodeDimensionsSystem,
|
||||
updateConnectionLookup,
|
||||
handleParentExpand,
|
||||
NodeChange,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import { applyEdgeChanges, applyNodeChanges, createSelectionChange, getSelectionChanges } from '../utils/changes';
|
||||
@@ -16,12 +17,12 @@ import type {
|
||||
ReactFlowState,
|
||||
Node,
|
||||
Edge,
|
||||
NodeDimensionChange,
|
||||
EdgeSelectionChange,
|
||||
NodeSelectionChange,
|
||||
NodePositionChange,
|
||||
UnselectNodesAndEdgesParams,
|
||||
FitViewOptions,
|
||||
InternalNode,
|
||||
} from '../types';
|
||||
|
||||
const createRFStore = ({
|
||||
@@ -91,23 +92,10 @@ const createRFStore = ({
|
||||
nodeOrigin,
|
||||
debug,
|
||||
} = get();
|
||||
const changes: NodeDimensionChange[] = [];
|
||||
|
||||
const updatedNodes = updateNodeDimensionsSystem(
|
||||
updates,
|
||||
nodeLookup,
|
||||
domNode,
|
||||
nodeOrigin,
|
||||
(id: string, dimensions: Dimensions) => {
|
||||
changes.push({
|
||||
id: id,
|
||||
type: 'dimensions',
|
||||
dimensions,
|
||||
});
|
||||
}
|
||||
);
|
||||
const changes = updateNodeDimensionsSystem(updates, nodeLookup, domNode, nodeOrigin);
|
||||
|
||||
if (!updatedNodes) {
|
||||
if (changes.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -137,17 +125,30 @@ const createRFStore = ({
|
||||
}
|
||||
},
|
||||
updateNodePositions: (nodeDragItems, dragging = false) => {
|
||||
const changes = nodeDragItems.map((node) => {
|
||||
const change: NodePositionChange = {
|
||||
const { nodeLookup } = get();
|
||||
const triggerChangeNodes: InternalNode[] = [];
|
||||
|
||||
const changes: NodeChange[] = nodeDragItems.map((node) => {
|
||||
const internalNode = nodeLookup.get(node.id);
|
||||
const change: NodeChange = {
|
||||
id: node.id,
|
||||
type: 'position',
|
||||
position: node.position,
|
||||
dragging,
|
||||
};
|
||||
|
||||
if (internalNode?.expandParent) {
|
||||
triggerChangeNodes.push(internalNode);
|
||||
}
|
||||
|
||||
return change;
|
||||
});
|
||||
|
||||
if (triggerChangeNodes.length > 0) {
|
||||
const parentExpandChanges = handleParentExpand(triggerChangeNodes, nodeLookup);
|
||||
changes.push(...parentExpandChanges);
|
||||
}
|
||||
|
||||
get().triggerNodeChanges(changes);
|
||||
},
|
||||
triggerNodeChanges: (changes) => {
|
||||
|
||||
@@ -10,51 +10,6 @@ import type {
|
||||
InternalNode,
|
||||
} from '../types';
|
||||
|
||||
export function handleParentExpand(updatedElements: any[], updateItem: any) {
|
||||
for (const [index, item] of updatedElements.entries()) {
|
||||
if (item.id === updateItem.parentNode) {
|
||||
const parent = { ...item };
|
||||
parent.computed ??= {};
|
||||
|
||||
const extendWidth = updateItem.position.x + updateItem.computed.width - parent.computed.width;
|
||||
const extendHeight = updateItem.position.y + updateItem.computed.height - parent.computed.height;
|
||||
|
||||
if (extendWidth > 0 || extendHeight > 0 || updateItem.position.x < 0 || updateItem.position.y < 0) {
|
||||
parent.width = parent.width ?? parent.computed.width;
|
||||
parent.height = parent.height ?? parent.computed.height;
|
||||
|
||||
if (extendWidth > 0) {
|
||||
parent.width += extendWidth;
|
||||
}
|
||||
|
||||
if (extendHeight > 0) {
|
||||
parent.height += extendHeight;
|
||||
}
|
||||
|
||||
if (updateItem.position.x < 0) {
|
||||
const xDiff = Math.abs(updateItem.position.x);
|
||||
parent.position.x = parent.position.x - xDiff;
|
||||
parent.width += xDiff;
|
||||
updateItem.position.x = 0;
|
||||
}
|
||||
|
||||
if (updateItem.position.y < 0) {
|
||||
const yDiff = Math.abs(updateItem.position.y);
|
||||
parent.position.y = parent.position.y - yDiff;
|
||||
parent.height += yDiff;
|
||||
updateItem.position.y = 0;
|
||||
}
|
||||
|
||||
parent.computed.width = parent.width;
|
||||
parent.computed.height = parent.height;
|
||||
|
||||
updatedElements[index] = parent;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function applies changes to nodes or edges that are triggered by React Flow internally.
|
||||
// When you drag a node for example, React Flow will send a position change update.
|
||||
// This function then applies the changes and returns the updated elements.
|
||||
@@ -111,7 +66,7 @@ function applyChanges(changes: any[], elements: any[]): any[] {
|
||||
const updatedElement = { ...element };
|
||||
|
||||
for (const change of changes) {
|
||||
applyChange(change, updatedElement, updatedElements);
|
||||
applyChange(change, updatedElement);
|
||||
}
|
||||
|
||||
updatedElements.push(updatedElement);
|
||||
@@ -121,7 +76,7 @@ function applyChanges(changes: any[], elements: any[]): any[] {
|
||||
}
|
||||
|
||||
// Applies a single change to an element. This is a *mutable* update.
|
||||
function applyChange(change: any, element: any, elements: any[] = []): any {
|
||||
function applyChange(change: any, element: any): any {
|
||||
switch (change.type) {
|
||||
case 'select': {
|
||||
element.selected = change.selected;
|
||||
@@ -137,9 +92,6 @@ function applyChange(change: any, element: any, elements: any[] = []): any {
|
||||
element.dragging = change.dragging;
|
||||
}
|
||||
|
||||
if (element.expandParent) {
|
||||
handleParentExpand(elements, element);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -159,10 +111,6 @@ function applyChange(change: any, element: any, elements: any[] = []): any {
|
||||
element.resizing = change.resizing;
|
||||
}
|
||||
|
||||
if (element.expandParent) {
|
||||
handleParentExpand(elements, element);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user