@@ -62,6 +62,47 @@ export function clampPositionToContainer(
6262 }
6363}
6464
65+ /**
66+ * Calculates container dimensions based on child block positions.
67+ * Single source of truth for container sizing - ensures consistency between
68+ * live drag updates and final dimension calculations.
69+ *
70+ * @param childPositions - Array of child positions with their dimensions
71+ * @returns Calculated width and height for the container
72+ */
73+ export function calculateContainerDimensions (
74+ childPositions : Array < { x : number ; y : number ; width : number ; height : number } >
75+ ) : { width : number ; height : number } {
76+ if ( childPositions . length === 0 ) {
77+ return {
78+ width : CONTAINER_DIMENSIONS . DEFAULT_WIDTH ,
79+ height : CONTAINER_DIMENSIONS . DEFAULT_HEIGHT ,
80+ }
81+ }
82+
83+ let maxRight = 0
84+ let maxBottom = 0
85+
86+ for ( const child of childPositions ) {
87+ maxRight = Math . max ( maxRight , child . x + child . width )
88+ maxBottom = Math . max ( maxBottom , child . y + child . height )
89+ }
90+
91+ const width = Math . max (
92+ CONTAINER_DIMENSIONS . DEFAULT_WIDTH ,
93+ CONTAINER_DIMENSIONS . LEFT_PADDING + maxRight + CONTAINER_DIMENSIONS . RIGHT_PADDING
94+ )
95+ const height = Math . max (
96+ CONTAINER_DIMENSIONS . DEFAULT_HEIGHT ,
97+ CONTAINER_DIMENSIONS . HEADER_HEIGHT +
98+ CONTAINER_DIMENSIONS . TOP_PADDING +
99+ maxBottom +
100+ CONTAINER_DIMENSIONS . BOTTOM_PADDING
101+ )
102+
103+ return { width, height }
104+ }
105+
65106/**
66107 * Hook providing utilities for node position, hierarchy, and dimension calculations
67108 */
@@ -306,36 +347,16 @@ export function useNodeUtilities(blocks: Record<string, any>) {
306347 ( id ) => currentBlocks [ id ] ?. data ?. parentId === nodeId
307348 )
308349
309- if ( childBlockIds . length === 0 ) {
310- return {
311- width : CONTAINER_DIMENSIONS . DEFAULT_WIDTH ,
312- height : CONTAINER_DIMENSIONS . DEFAULT_HEIGHT ,
313- }
314- }
315-
316- let maxRight = 0
317- let maxBottom = 0
318-
319- for ( const childId of childBlockIds ) {
320- const child = currentBlocks [ childId ]
321- if ( ! child ?. position ) continue
322-
323- const { width : childWidth , height : childHeight } = getBlockDimensions ( childId )
324-
325- maxRight = Math . max ( maxRight , child . position . x + childWidth )
326- maxBottom = Math . max ( maxBottom , child . position . y + childHeight )
327- }
328-
329- const width = Math . max (
330- CONTAINER_DIMENSIONS . DEFAULT_WIDTH ,
331- maxRight + CONTAINER_DIMENSIONS . RIGHT_PADDING
332- )
333- const height = Math . max (
334- CONTAINER_DIMENSIONS . DEFAULT_HEIGHT ,
335- maxBottom + CONTAINER_DIMENSIONS . BOTTOM_PADDING
336- )
350+ const childPositions = childBlockIds
351+ . map ( ( childId ) => {
352+ const child = currentBlocks [ childId ]
353+ if ( ! child ?. position ) return null
354+ const { width, height } = getBlockDimensions ( childId )
355+ return { x : child . position . x , y : child . position . y , width, height }
356+ } )
357+ . filter ( ( p ) : p is NonNullable < typeof p > => p !== null )
337358
338- return { width , height }
359+ return calculateContainerDimensions ( childPositions )
339360 } ,
340361 [ getBlockDimensions ]
341362 )
0 commit comments