@@ -29,9 +29,9 @@ const getLayoutedElements = (nodes: any[], edges: any[]) => {
29
29
}
30
30
}
31
31
32
- // 2. Identify root/main nodes (nodes that are not parameters or have no parent).
32
+ // 2. Identify root/main nodes (nodes that are not parameters or have no parent and are not inside a group ).
33
33
const roots = nodes . filter (
34
- n => ! n . data ?. isParameter || ! n . data ?. parentId
34
+ n => ( ! n . data ?. isParameter || ! n . data ?. parentId ) && ! n . parentNode
35
35
) ;
36
36
37
37
// 3. Store calculated center positions for each node by id.
@@ -51,38 +51,47 @@ const getLayoutedElements = (nodes: any[], edges: any[]) => {
51
51
// Store center position for this node.
52
52
pos . set ( node . id , { x : cx , y : cy } ) ;
53
53
54
- // Find and sort direct parameter nodes for this node.
55
- const params = ( children . get ( node . id ) ?? [ ] )
54
+ // Find direct children for this node.
55
+ const allChildren = ( children . get ( node . id ) ?? [ ] )
56
56
. sort ( ( a , b ) => ( a . data ?. paramIndex ?? 0 ) - ( b . data ?. paramIndex ?? 0 ) ) ;
57
+ const sideParams = allChildren . filter ( ( c : any ) => c . type !== 'group' ) ;
58
+ const downGroups = allChildren . filter ( ( c : any ) => c . type === 'group' ) ;
57
59
58
- // Compute the total vertical height of all parameter nodes including spacing.
59
- const paramHeights = params . map ( p => p . measured ?. height ?? 80 ) ;
60
+ // Compute the total vertical height of parameter nodes on the side including spacing.
61
+ const paramHeights = sideParams . map ( p => p . measured ?. height ?? 80 ) ;
60
62
const paramBlockHeight = paramHeights . length
61
63
? paramHeights . reduce ( ( sum , h , i ) => sum + h + ( i ? V_SPACING : 0 ) , 0 )
62
64
: 0 ;
63
65
64
- // The "block" height for the main node is the max of its own height or its parameter block.
65
- const blockHeight = Math . max ( h , paramBlockHeight ) ;
66
-
67
- // Center parameters vertically relative to parent node.
66
+ // Center side parameters vertically relative to parent node.
68
67
let paramY = cy - paramBlockHeight / 2 ;
69
- params . forEach ( ( param , i ) => {
68
+ sideParams . forEach ( ( param : any , i : number ) => {
70
69
const pw = param . measured ?. width ?? 200 ;
71
70
const ph = paramHeights [ i ] ;
72
- // Place parameter node to the right of the parent.
73
71
const px = cx + w / 2 + H_SPACING + pw / 2 ;
74
72
const py = paramY + ph / 2 ;
75
73
76
74
pos . set ( param . id , { x : px , y : py } ) ;
77
75
78
- // Recursively layout any sub-parameters of this parameter node.
79
76
layout ( param , px , py ) ;
80
77
81
78
paramY += ph + V_SPACING ;
82
79
} ) ;
83
80
84
- // Return the bottom y-coordinate of this main node's "block".
85
- return cy + blockHeight / 2 ;
81
+ // Place group parameters below the node.
82
+ let blockBottom = cy + h / 2 ;
83
+ downGroups . forEach ( ( group : any ) => {
84
+ const gh = group . measured ?. height ?? 80 ;
85
+ const gx = cx ;
86
+ const gy = blockBottom + V_SPACING + gh / 2 ;
87
+ pos . set ( group . id , { x : gx , y : gy } ) ;
88
+ layout ( group , gx , gy ) ;
89
+ blockBottom = gy + gh / 2 ;
90
+ } ) ;
91
+
92
+ // The block height is the max of node height, side params and groups below.
93
+ const maxBottom = Math . max ( blockBottom , cy + Math . max ( h , paramBlockHeight ) / 2 ) ;
94
+ return maxBottom ;
86
95
}
87
96
88
97
// 4. Layout all root/main nodes vertically, keeping at least V_SPACING between each.
@@ -96,7 +105,7 @@ const getLayoutedElements = (nodes: any[], edges: any[]) => {
96
105
97
106
// 5. Generate new positioned nodes by shifting from center to top-left.
98
107
const positionedNodes = nodes . map ( node => {
99
- const { x, y} = pos . get ( node . id ) ! ;
108
+ const { x, y} = pos . get ( node . id ) ?? { x : 0 , y : 0 } ;
100
109
const w = node . measured ?. width ?? 200 ;
101
110
const h = node . measured ?. height ?? 80 ;
102
111
return {
0 commit comments