@@ -11,7 +11,7 @@ import type { NodeChange } from '@xyflow/react'
1111import { useUnit } from 'effector-react'
1212import { useCallback } from 'react'
1313import { $activeFlowMetadata } from '@/store/flow'
14- import { $nodes , removeNodeFromFlow , updateNodePosition , updateNodeUI } from '@/store/nodes'
14+ import { $nodes , removeNodeFromFlow , updateNodePosition , updateNodePositionOnly , updateNodeUI } from '@/store/nodes'
1515import { positionInterpolator } from '@/store/nodes/position-interpolation-advanced'
1616import { roundPosition } from './useFlowUtils'
1717
@@ -59,6 +59,13 @@ export function useNodeChanges() {
5959
6060 positionInterpolator . clearNodeState ( node . id )
6161
62+ // Use position-only update during drag to avoid $nodes cascade
63+ updateNodePositionOnly ( {
64+ nodeId : change . id ,
65+ position : roundPosition ( change . position as Position ) ,
66+ } )
67+
68+ // Also trigger server sync (throttled separately at 500ms)
6269 updateNodePosition ( {
6370 flowId : activeFlow . id ! ,
6471 nodeId : change . id ,
@@ -70,41 +77,15 @@ export function useNodeChanges() {
7077
7178 case 'dimensions' :
7279 {
73- const node = currentNodes [ change . id ]
74- if ( ! node )
75- return
76-
77- if ( node . metadata . category === 'group' ) {
78- // ignore group node dimension changes, is is handled by the group node itself
79- return
80- }
81-
82- if ( ! change . dimensions || ! change . dimensions . width || ! change . dimensions . height ) {
83- console . warn ( `[useNodeChanges] Invalid dimensions change:` , change )
84- return
85- }
86- const isSameDimensions
87- = node . metadata . ui ?. dimensions ?. width === change . dimensions . width
88- && node . metadata . ui ?. dimensions ?. height === change . dimensions . height
89-
90- const isNodeDimensionInitialized
91- = node . metadata . ui ?. dimensions !== undefined
92- && node . metadata . ui ?. dimensions ?. width !== undefined
93- && node . metadata . ui ?. dimensions ?. height !== undefined
94-
95- if ( isSameDimensions ) { // || !isNodeDimensionInitialized) {
96- return
97- }
98-
99- updateNodeUI ( {
100- flowId : activeFlow . id ! ,
101- nodeId : change . id ,
102- ui : {
103- dimensions : change . dimensions ,
104- } ,
105- version : node . getVersion ( ) ,
106- } )
107-
80+ // SKIP all dimension changes from XYFlow's onNodesChange
81+ // XYFlow reports measured DOM sizes which conflict with resize handle positions
82+ //
83+ // Dimension sources are now:
84+ // - Width: NodeResizeControl onResize handler (user intent)
85+ // - Height: useElementResize content detection (for regular nodes)
86+ // - Both: NodeResizer onResize handler (for GroupNode)
87+ //
88+ // GroupNode is also skipped here as it handles dimensions in its own component
10889 break
10990 }
11091
@@ -117,7 +98,7 @@ export function useNodeChanges() {
11798 updateNodeUI ( {
11899 flowId : activeFlow . id ! ,
119100 nodeId : change . id ,
120- version : node . getVersion ( ) + 1 ,
101+ version : 0 ,
121102 ui : {
122103 state : {
123104 isSelected : change . selected ,
0 commit comments