(
blocks: Record<string, BlockState>,
edges: Edge[],
options: LayoutOptions = {}
)
| 23 | * Positions blocks in layers based on their connections (edges). |
| 24 | */ |
| 25 | export function applyAutoLayout( |
| 26 | blocks: Record<string, BlockState>, |
| 27 | edges: Edge[], |
| 28 | options: LayoutOptions = {} |
| 29 | ): LayoutResult { |
| 30 | try { |
| 31 | logger.info('Starting auto layout', { |
| 32 | blockCount: Object.keys(blocks).length, |
| 33 | edgeCount: edges.length, |
| 34 | }) |
| 35 | |
| 36 | const blocksCopy: Record<string, BlockState> = structuredClone(blocks) |
| 37 | |
| 38 | const horizontalSpacing = options.horizontalSpacing ?? DEFAULT_HORIZONTAL_SPACING |
| 39 | const verticalSpacing = options.verticalSpacing ?? DEFAULT_VERTICAL_SPACING |
| 40 | |
| 41 | prepareContainerDimensions( |
| 42 | blocksCopy, |
| 43 | edges, |
| 44 | layoutBlocksCore, |
| 45 | horizontalSpacing, |
| 46 | verticalSpacing, |
| 47 | options.gridSize |
| 48 | ) |
| 49 | |
| 50 | const { root: rootBlockIds } = getBlocksByParent(blocksCopy) |
| 51 | const layoutRootIds = filterLayoutEligibleBlockIds(rootBlockIds, blocksCopy) |
| 52 | |
| 53 | const rootBlocks: Record<string, BlockState> = {} |
| 54 | for (const id of layoutRootIds) { |
| 55 | rootBlocks[id] = blocksCopy[id] |
| 56 | } |
| 57 | |
| 58 | const rootEdges = edges.filter( |
| 59 | (edge) => layoutRootIds.includes(edge.source) && layoutRootIds.includes(edge.target) |
| 60 | ) |
| 61 | |
| 62 | const subflowDepths = calculateSubflowDepths(blocksCopy, edges, assignLayers) |
| 63 | |
| 64 | if (Object.keys(rootBlocks).length > 0) { |
| 65 | const { nodes } = layoutBlocksCore(rootBlocks, rootEdges, { |
| 66 | isContainer: false, |
| 67 | layoutOptions: options, |
| 68 | subflowDepths, |
| 69 | }) |
| 70 | |
| 71 | for (const node of nodes.values()) { |
| 72 | blocksCopy[node.id].position = node.position |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | layoutContainers(blocksCopy, edges, options) |
| 77 | |
| 78 | resolveNoteOverlaps(blocksCopy, verticalSpacing) |
| 79 | |
| 80 | logger.info('Auto layout completed successfully', { |
| 81 | blockCount: Object.keys(blocksCopy).length, |
| 82 | }) |
no test coverage detected