@@ -168,15 +168,11 @@ export function toFlatFlowElements(
168168 return { nodes, edges, startKey } ;
169169}
170170
171- /**
172- * BFS spanning-tree edges from `startKey` (parent → child) for Dagre ranking.
173- * Handles cycles by only recording the first discovery edge.
174- */
175- export function bfsSpanningTreeEdges (
171+ /** Undirected adjacency for the given node ids and edges. */
172+ function buildUndirectedIdAdjacency (
176173 nodeIds : string [ ] ,
177174 edges : Array < { source : string ; target : string } > ,
178- startKey : string ,
179- ) : Array < { source : string ; target : string } > {
175+ ) : Map < string , string [ ] > {
180176 const idSet = new Set ( nodeIds ) ;
181177 const adj = new Map < string , string [ ] > ( ) ;
182178 for ( const id of nodeIds ) {
@@ -187,10 +183,52 @@ export function bfsSpanningTreeEdges(
187183 adj . get ( edge . source ) ! . push ( edge . target ) ;
188184 adj . get ( edge . target ) ! . push ( edge . source ) ;
189185 }
186+ return adj ;
187+ }
190188
189+ /**
190+ * Node ids reachable from `startKey` via undirected edges.
191+ * Falls back to the first node id when `startKey` is missing.
192+ */
193+ export function reachableNodeIds (
194+ nodeIds : string [ ] ,
195+ edges : Array < { source : string ; target : string } > ,
196+ startKey : string ,
197+ ) : Set < string > {
198+ const idSet = new Set ( nodeIds ) ;
199+ const root = idSet . has ( startKey ) ? startKey : ( nodeIds [ 0 ] ?? '' ) ;
200+ if ( ! root ) return new Set ( ) ;
201+
202+ const adj = buildUndirectedIdAdjacency ( nodeIds , edges ) ;
203+ const visited = new Set < string > ( [ root ] ) ;
204+ const queue = [ root ] ;
205+
206+ while ( queue . length > 0 ) {
207+ const cur = queue . shift ( ) ! ;
208+ for ( const nxt of adj . get ( cur ) ?? [ ] ) {
209+ if ( visited . has ( nxt ) ) continue ;
210+ visited . add ( nxt ) ;
211+ queue . push ( nxt ) ;
212+ }
213+ }
214+
215+ return visited ;
216+ }
217+
218+ /**
219+ * BFS spanning-tree edges from `startKey` (parent → child) for Dagre ranking.
220+ * Handles cycles by only recording the first discovery edge.
221+ */
222+ export function bfsSpanningTreeEdges (
223+ nodeIds : string [ ] ,
224+ edges : Array < { source : string ; target : string } > ,
225+ startKey : string ,
226+ ) : Array < { source : string ; target : string } > {
227+ const idSet = new Set ( nodeIds ) ;
191228 const root = idSet . has ( startKey ) ? startKey : ( nodeIds [ 0 ] ?? '' ) ;
192229 if ( ! root ) return [ ] ;
193230
231+ const adj = buildUndirectedIdAdjacency ( nodeIds , edges ) ;
194232 const tree : Array < { source : string ; target : string } > = [ ] ;
195233 const visited = new Set < string > ( [ root ] ) ;
196234 const queue = [ root ] ;
0 commit comments