( graph: Graph, layoutReady: boolean, visualState: VisualState, layoutConfig: LayoutConfig, _degreeMap: Map<string, number>, isLargeGraph: boolean, )
| 71 | * Never touches x/y positions. |
| 72 | */ |
| 73 | export function useGraphVisuals( |
| 74 | graph: Graph, |
| 75 | layoutReady: boolean, |
| 76 | visualState: VisualState, |
| 77 | layoutConfig: LayoutConfig, |
| 78 | _degreeMap: Map<string, number>, |
| 79 | isLargeGraph: boolean, |
| 80 | ): void { |
| 81 | const themeKey = useThemeKey(); |
| 82 | |
| 83 | useEffect(() => { |
| 84 | if (!layoutReady || graph.order === 0) return; |
| 85 | |
| 86 | const { |
| 87 | colorMode, |
| 88 | highlightNodes, |
| 89 | highlightLinks, |
| 90 | labelNodes, |
| 91 | selectedNodeId, |
| 92 | } = visualState; |
| 93 | |
| 94 | const { getNodeColor, getLinkColor } = layoutConfig; |
| 95 | const hasHighlight = highlightNodes.size > 0; |
| 96 | |
| 97 | // Batched node update — single event |
| 98 | graph.updateEachNodeAttributes((_id, attrs) => { |
| 99 | const isHighlighted = !hasHighlight || highlightNodes.has(_id); |
| 100 | const isSelected = _id === selectedNodeId; |
| 101 | const showLabel = !hasHighlight || labelNodes.has(_id); |
| 102 | const baseColor = |
| 103 | ((colorMode === 'community' |
| 104 | ? attrs._communityColor |
| 105 | : attrs._typeColor) as string | undefined) ?? |
| 106 | getNodeColor(attrs.nodeType as string); |
| 107 | |
| 108 | // _baseSize and _originalLabel are set once at graph construction |
| 109 | // (useGraphInstance) so they always reflect the true source values. |
| 110 | const baseSize = (attrs._baseSize as number) ?? attrs.size; |
| 111 | const originalLabel = |
| 112 | (attrs._originalLabel as string | null) ?? attrs.label; |
| 113 | |
| 114 | attrs.color = isHighlighted |
| 115 | ? baseColor |
| 116 | : dimColor(baseColor, NODE_OPACITY_DIMMED); |
| 117 | attrs.size = |
| 118 | hasHighlight && !isHighlighted |
| 119 | ? baseSize * NODE_SIZE_DIMMED_SCALE |
| 120 | : baseSize; |
| 121 | attrs.borderColor = isSelected ? baseColor : undefined; |
| 122 | attrs.borderSize = isSelected ? 3 : 0; |
| 123 | attrs.label = hasHighlight && !isHighlighted ? null : originalLabel; |
| 124 | attrs.forceLabel = showLabel && hasHighlight; |
| 125 | attrs.zIndex = isSelected ? 2 : isHighlighted && hasHighlight ? 1 : 0; |
| 126 | // highlighted → renders on the hover layer (above edges canvas) |
| 127 | attrs.highlighted = hasHighlight && isHighlighted; |
| 128 | return attrs; |
| 129 | }); |
| 130 |
nothing calls this directly
no test coverage detected