( _graph: Graph, _layoutReady: boolean, allNodes: GraphNode[], allLinks: GraphLink[], searchQuery: string, selectedNodeId: string | null, hops: number, filterState: FilterState, )
| 34 | * and excluding links whose endpoints belong to hidden node types. |
| 35 | */ |
| 36 | export function useHighlights( |
| 37 | _graph: Graph, |
| 38 | _layoutReady: boolean, |
| 39 | allNodes: GraphNode[], |
| 40 | allLinks: GraphLink[], |
| 41 | searchQuery: string, |
| 42 | selectedNodeId: string | null, |
| 43 | hops: number, |
| 44 | filterState: FilterState, |
| 45 | ): { |
| 46 | highlightNodes: Set<string>; |
| 47 | highlightLinks: Set<string>; |
| 48 | labelNodes: Set<string>; |
| 49 | hopMap: Map<string, number>; |
| 50 | } { |
| 51 | // Build a node-type lookup so we can filter out hidden endpoint types. |
| 52 | const nodeTypeMap = useMemo(() => { |
| 53 | const map = new Map<string, string>(); |
| 54 | for (const node of allNodes) { |
| 55 | map.set(node.id, node.type); |
| 56 | } |
| 57 | return map; |
| 58 | }, [allNodes]); |
| 59 | |
| 60 | // Build adjacency from allLinks, respecting filter state. |
| 61 | const adjacency = useMemo(() => { |
| 62 | const map = new Map<string, { neighbor: string; linkKey: string }[]>(); |
| 63 | for (const link of allLinks) { |
| 64 | // Skip hidden link types. |
| 65 | if (filterState.hiddenLinkTypes.has(link.label)) continue; |
| 66 | |
| 67 | const sourceId = endpointId(link.source); |
| 68 | const targetId = endpointId(link.target); |
| 69 | |
| 70 | // Skip links where either endpoint is a hidden node type. |
| 71 | const sourceType = nodeTypeMap.get(sourceId); |
| 72 | const targetType = nodeTypeMap.get(targetId); |
| 73 | if (sourceType && filterState.hiddenNodeTypes.has(sourceType)) continue; |
| 74 | if (targetType && filterState.hiddenNodeTypes.has(targetType)) continue; |
| 75 | |
| 76 | const linkKey = `${sourceId}-${targetId}`; |
| 77 | if (!map.has(sourceId)) map.set(sourceId, []); |
| 78 | if (!map.has(targetId)) map.set(targetId, []); |
| 79 | map.get(sourceId)!.push({ neighbor: targetId, linkKey }); |
| 80 | map.get(targetId)!.push({ neighbor: sourceId, linkKey }); |
| 81 | } |
| 82 | return map; |
| 83 | }, [ |
| 84 | allLinks, |
| 85 | filterState.hiddenLinkTypes, |
| 86 | filterState.hiddenNodeTypes, |
| 87 | nodeTypeMap, |
| 88 | ]); |
| 89 | |
| 90 | // Compute highlights via search and/or BFS from selected node. |
| 91 | return useMemo(() => { |
| 92 | const highlightNodes = new Set<string>(); |
| 93 | const highlightLinks = new Set<string>(); |
no test coverage detected