(node: FlowNode)
| 50 | |
| 51 | // Calculate node dimensions based on type and content |
| 52 | export function getNodeDimensions(node: FlowNode): { width: number; height: number } { |
| 53 | // Prefer measured size from ReactFlow when available (post-render). |
| 54 | // This is the most reliable way to avoid overlaps when nodes auto-grow. |
| 55 | const anyNode = node as unknown as { |
| 56 | width?: number; |
| 57 | height?: number; |
| 58 | measured?: { width?: number; height?: number }; |
| 59 | }; |
| 60 | const mw = anyNode.measured?.width; |
| 61 | const mh = anyNode.measured?.height; |
| 62 | if (typeof mw === 'number' && mw > 0 && typeof mh === 'number' && mh > 0) { |
| 63 | return { width: mw, height: mh }; |
| 64 | } |
| 65 | if (typeof anyNode.width === 'number' && anyNode.width > 0 && typeof anyNode.height === 'number' && anyNode.height > 0) { |
| 66 | return { width: anyNode.width, height: anyNode.height }; |
| 67 | } |
| 68 | |
| 69 | const nodeType = node.type; |
| 70 | const data = node.data; |
| 71 | |
| 72 | if (nodeType === 'if') { |
| 73 | const { thenSteps, elseSteps } = data as IfNodeData; |
| 74 | const branchHeight = Math.max( |
| 75 | calculateNestedStepsHeight(thenSteps) + 60, |
| 76 | calculateNestedStepsHeight(elseSteps) + 60, |
| 77 | 60, |
| 78 | ); |
| 79 | return { width: 320, height: Math.max(60 + branchHeight + 48, 150) }; |
| 80 | } |
| 81 | |
| 82 | if (nodeType === 'while' || nodeType === 'for_each') { |
| 83 | const { loopSteps } = data as WhileNodeData; |
| 84 | const loopHeight = calculateNestedStepsHeight(loopSteps); |
| 85 | return { width: 220, height: Math.max(78 + Math.max(loopHeight + 48, 72) + 48, 150) }; |
| 86 | } |
| 87 | |
| 88 | if (nodeType === 'switch') { |
| 89 | const { cases, defaultSteps } = data as SwitchNodeData; |
| 90 | let totalCasesHeight = 0; |
| 91 | const caseCount = cases ? Object.keys(cases).length : 0; |
| 92 | if (cases) { |
| 93 | for (const caseSteps of Object.values(cases)) { |
| 94 | totalCasesHeight += calculateNestedStepsHeight(caseSteps) + 50; |
| 95 | } |
| 96 | } |
| 97 | const defaultHeight = calculateNestedStepsHeight(defaultSteps) + 50; |
| 98 | return { width: 350, height: Math.max(100 + totalCasesHeight + defaultHeight + 40, 200 + caseCount * 60) }; |
| 99 | } |
| 100 | |
| 101 | if (nodeType === 'gather') { |
| 102 | const gatherData = data as unknown as { calls?: unknown[]; module?: string }; |
| 103 | const callsCount = gatherData.calls?.length || 0; |
| 104 | // Base height ~80px + (calls * 30px per call); when module is set, submodule viewer adds more |
| 105 | const baseHeight = 100 + (callsCount * 30); |
| 106 | const expandedHeight = gatherData.module || callsCount > 0 ? baseHeight + 220 : baseHeight; |
| 107 | return { width: DEFAULT_NODE_WIDTH, height: Math.max(expandedHeight, DEFAULT_NODE_HEIGHT) }; |
| 108 | } |
| 109 |
no test coverage detected