(
options: UseGraphViewerOptions = {},
)
| 263 | * for the OSS reference shell. |
| 264 | */ |
| 265 | export function useGraphViewer( |
| 266 | options: UseGraphViewerOptions = {}, |
| 267 | ): UseGraphViewerResult { |
| 268 | const { |
| 269 | chatHighlightNodes, |
| 270 | extraHighlightSource, |
| 271 | suppressNextAutoFitRef, |
| 272 | autoFitMode = 'schedule', |
| 273 | } = options; |
| 274 | |
| 275 | const canvasRef = useRef<GraphCanvasHandle>(null); |
| 276 | |
| 277 | const { graphData, stats, lastSearchQuery, graphVersion, loadGraph } = |
| 278 | useGraph(); |
| 279 | |
| 280 | const { |
| 281 | selectedNode, |
| 282 | setSelectedNode, |
| 283 | selectedLink, |
| 284 | setSelectedLink, |
| 285 | setNodeHistory, |
| 286 | setHiddenNodeTypes, |
| 287 | setHiddenCommunities, |
| 288 | colorMode, |
| 289 | searchQuery, |
| 290 | setSearchQuery, |
| 291 | hops, |
| 292 | setHops, |
| 293 | focusedCommunityNodes, |
| 294 | setFocusedCommunityNodes, |
| 295 | communitiesEnabled, |
| 296 | setCommunitiesEnabled, |
| 297 | communityData, |
| 298 | filteredGraphData, |
| 299 | highlights, |
| 300 | } = useGraphInteraction(); |
| 301 | |
| 302 | // Stable pointer to the latest graphData. Lets stale closures (imperative |
| 303 | // handle, narrow-dep effects) read fresh data without forcing graphData |
| 304 | // into their dependency arrays. |
| 305 | const graphDataRef = useRef(graphData); |
| 306 | useEffect(() => { |
| 307 | graphDataRef.current = graphData; |
| 308 | }, [graphData]); |
| 309 | |
| 310 | // ─── Auto-fit on graphVersion bump ────────────────────────────────────── |
| 311 | // Mode is consumer-selected via `options.autoFitMode`: |
| 312 | // - 'schedule' (default): `scheduleAutoFit` is throttled and gated by |
| 313 | // the user's pan/zoom state, so it's a no-op if the user has already |
| 314 | // moved the camera (preserves user intent — OSS default). |
| 315 | // - 'unconditional': always re-fits after a 500ms layout-settle delay, |
| 316 | // ignoring user camera state (matches the legacy UI-repo fork behavior). |
| 317 | // Either mode honors `suppressNextAutoFitRef` for one-shot suppression. |
| 318 | useEffect(() => { |
| 319 | if (graphVersion === 0) return; |
| 320 | if (suppressNextAutoFitRef?.current) { |
| 321 | suppressNextAutoFitRef.current = false; |
| 322 | return; |
no test coverage detected