diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e8fc86..c8aa8c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,73 +2,77 @@ All notable changes to OrbitGraph are documented in this file. -The project follows [Semantic Versioning](https://semver.org/). Package versions are released together for `@orbitgraph/core`, `@orbitgraph/three`, and `@orbitgraph/react`. +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project follows [Semantic Versioning](https://semver.org/). -## [1.1.0] - 2026-07-21 +## [1.2.0] ### Added -- Hybrid desktop, touch, and keyboard camera navigation with configurable movement and zoom limits. -- Optional responsive mobile camera controls with large zoom and reset targets, enabled automatically on coarse-pointer devices. -- Keyboard accessibility for visible graph nodes, including focus indication, node activation, expansion, collapse, and selection clearing. -- PNG export and download for the current rendered graph view. -- Complete or visible graph data export and download as JSON. -- React `OrbitGraphHandle` ref API for camera, exploration, export, and loading-state actions. -- React callbacks for lazy-loading state and keyboard focus changes. -- React component, mobile controls, keyboard navigation, and export test coverage. +- Optional `createGraphQLDataSource()` adapter in `@orbitgraph/three` for mapping GraphQL responses to `GraphDataSource`. +- Generic GraphQL request abstraction that supports built-in `fetch` or an existing GraphQL client without adding a GraphQL client dependency. +- Structured remote-loading errors through `GraphLoadError` and `GraphLoadingState.error`. +- `onDiagnostic` callback for application logging, telemetry, and error reporting. +- Direct `onDiagnostic` prop in `@orbitgraph/react`. +- Error coverage for node and neighborhood lazy-loading failures. +- Graph analytics APIs for degree, in-degree, out-degree, PageRank, betweenness centrality, and community detection. +- `graph.analytics` controller in `@orbitgraph/three` with `all` and `visible` data scopes. +- Worker-backed force physics for supported browsers, with a local simulation fallback. ### Changed -- Refactored the Three.js facade into focused runtime, data-store, lazy-loader, view-synchronizer, and interaction modules. -- Updated documentation and examples for camera, accessibility, responsive controls, and exports. +- Remote requests continue to reject their original promise after OrbitGraph emits loading state and diagnostics, preserving application-level retry and recovery control. +- Force-directed layouts can run outside the browser main thread through module Workers. -## [1.0.0] - 2026-07-20 +## [1.1.0] ### Added -- Progressive graph exploration through `initialView` modes: `all`, `node`, `neighborhood`, and `type`. -- Exploration controls, history, shortest-path focus, lazy data loading, persisted view state, and multiple layouts. -- Vanilla and React examples, benchmark tooling, CI validation, API docs, contribution guide, security policy, and community files. +- Improved camera navigation with desktop and touch-friendly controls. +- Keyboard navigation and visible keyboard focus support. +- PNG and JSON export utilities. +- Responsive mobile graph controls. +- React imperative ref support for exploration, camera, loading, and export actions. +- React component test coverage in the validation workflow. +- Additional examples and documentation for interaction, exports, accessibility, and mobile usage. ### Changed -- Hidden exploration data is excluded from rendering and force simulation. -- Search and filters refine the explored subset instead of revealing hidden data. -- Renderer and physics behavior were optimized for large graphs. +- Refactored the Three.js runtime into smaller focused controllers and synchronizers. +- Improved CI validation to run workspace builds and tests on pull requests. -## [0.5.0] - 2026-07-20 +## [1.0.0] ### Added -- Optional animated relationship flow and interactive performance benchmark. +- Initial stable release of OrbitGraph. +- TypeScript monorepo packages for `@orbitgraph/core`, `@orbitgraph/three`, and `@orbitgraph/react`. +- Interactive 3D force-directed graph rendering with Three.js. +- Node and relationship selection, hover behavior, search, type filters, and minimum relationship weight filters. +- Progressive graph exploration with initial views, expansion, collapse, navigation history, and path focus. +- Optional animated relationship flow. +- Vanilla JavaScript, React, benchmark, and playground examples. +- Documentation, API reference, contribution guide, security policy, Code of Conduct, issue templates, and pull request validation. -### Changed - -- Reused renderer geometries and materials and reduced expensive link visuals for large graphs. - -## [0.4.0] - 2026-07-20 +### Performance -### Added - -- Initial `@orbitgraph/react` package, package READMEs, API docs, and consumer examples. +- Large graph benchmark with generated data sets from 100 to 10,000 nodes. +- Hidden exploration data excluded from active rendering and physics simulation. -## [0.3.0] - 2026-07-20 +## [0.5.0] ### Added -- Labels, arrows, hover events, selections, metadata, search, filters, and incremental update APIs. +- Loading state callbacks for lazy graph data. +- Exploration improvements and related React bindings. -## [0.2.0] - 2026-07-20 +## [0.4.0] ### Added -- Three.js graph renderer with 3D force layout, orbit controls, zoom, drag, and pinning. +- Initial exploration API, incremental view updates, and expanded package documentation. -## [0.1.0] - 2026-07-20 +## [0.3.0] ### Added -- Initial `@orbitgraph/core` and `@orbitgraph/three` releases. - -[Unreleased]: https://github.com/Manuel1471/OrbitGraph/compare/1.0.0...HEAD -[1.0.0]: https://github.com/Manuel1471/OrbitGraph/releases/tag/1.0.0 \ No newline at end of file +- First public multi-package release with core graph types, Three.js rendering, and React bindings. diff --git a/README.MD b/README.MD index ab2925e..e2a81c8 100644 --- a/README.MD +++ b/README.MD @@ -1,130 +1,156 @@ # OrbitGraph -> Explore connected data in 3D — start small, follow relationships, and reveal only what matters. +> Explore connected data in 3D — load only what matters, reveal relationships progressively, and explain the structure visually. ![OrbitGraph preview](./assets/example.png) -## Start here - -| I want to... | Go to | -| --- | --- | -| Render my first graph | [Quick start](#quick-start) | -| Copy API recipes | [API guide](./docs/api/README.md) | -| Explore a large graph progressively | [Relationship exploration](./docs/guides/relationship-exploration.md) | -| Use touch, keyboard, camera, and exports | [Interaction guide](./docs/guides/interaction-and-export.md) | -| Test graph size and FPS | [Performance guide](./docs/guides/performance.md) | - -## Features - -- 3D force-directed graph layouts with orbit, pan, zoom, drag, and pin interactions -- Progressive exploration: start from a node, neighborhood, or type instead of rendering all data -- Search, type filters, link-weight filtering, selections, labels, paths, and exploration history -- Responsive touch gestures plus optional large mobile camera controls -- Keyboard navigation with visible focus and accessible canvas labels -- Optional animated relationship flow -- PNG screenshots and complete or visible JSON exports -- Vanilla JavaScript and React support +OrbitGraph is a TypeScript library for interactive relationship graphs. It combines Three.js rendering, force-directed layouts, progressive exploration, analytics, remote data loading, and React bindings in a small set of focused packages. ## Install -### Vanilla JavaScript - ```bash npm install @orbitgraph/core @orbitgraph/three three ``` -### React +
+Using React? ```bash npm install @orbitgraph/core @orbitgraph/three @orbitgraph/react three ``` -## Quick start +
+ +## Start with a useful view ```ts import { createOrbitGraph } from "@orbitgraph/three"; import type { GraphData } from "@orbitgraph/core"; const data: GraphData = { - nodes: [ - { id: "team", label: "Product Team", type: "group", color: "#22d3ee" }, - { id: "workspace", label: "Workspace", type: "resource", color: "#a855f7" }, - ], - links: [ - { source: "team", target: "workspace", type: "manages", weight: 1 }, - ], + nodes: [ + { id: "team", label: "Product Team", type: "team", color: "#22d3ee" }, + { id: "api", label: "Public API", type: "service", color: "#3b82f6" }, + ], + links: [ + { id: "team-owns-api", source: "team", target: "api", type: "owns", weight: 0.95 }, + ], }; const container = document.querySelector("#graph"); if (!container) { - throw new Error("Graph container was not found."); + throw new Error("Graph container was not found."); } const graph = createOrbitGraph(container, { - mobileControls: { enabled: "auto" }, - accessibility: { ariaLabel: "Product relationships" }, + initialView: { mode: "node", nodeId: "team" }, + labels: { + mode: "important", + importantNodeIds: ["team"], + showNodeType: true, + }, + miniMap: { + enabled: true, + interactive: true, + }, }); graph.setData(data); +graph.expandNode("team", { direction: "outgoing" }); ``` -## Explore large graphs progressively +Hidden nodes are kept out of WebGL and the active physics simulation until exploration reveals them. + +## What OrbitGraph includes + +- 3D force-directed, radial, grid, and hierarchical layouts. +- Progressive exploration from a node, neighborhood, or node type. +- Local search, type filters, link-weight filters, history, and path focus. +- Worker-backed physics with automatic main-thread fallback. +- Optional remote loading through `GraphDataSource` and a GraphQL adapter. +- Degree, PageRank, betweenness, and community detection. +- Visual presentation APIs for analytics: color, scale, glow, and legends you control. +- Intelligent persistent labels, hover labels, and an interactive mini-map. +- Desktop keyboard movement, keyboard graph navigation, touch controls, and mobile controls. +- Node/link events, selection, diagnostics, loading state, PNG export, JSON export, and view-state persistence. +- Vanilla JavaScript and React support. + +## Packages + +| Package | Purpose | +| --- | --- | +| [`@orbitgraph/core`](./packages/core) | Data types, analytics, communities, and data-source contracts. | +| [`@orbitgraph/three`](./packages/three) | Three.js renderer and imperative graph API. | +| [`@orbitgraph/react`](./packages/react) | React component and ref-based actions. | + +## Explore and analyze ```ts -const graph = createOrbitGraph(container, { - initialView: { - mode: "neighborhood", - nodeId: "team", - depth: 1, - direction: "outgoing", - }, +const pageRank = graph.analytics.pageRank({ scope: "visible" }); + +graph.presentation.setNodeStyles({ + "api": { + color: "#facc15", + scale: 1.6, + glow: 0.9, + }, }); -graph.setData(data); -graph.expandNode("team", { depth: 1, direction: "outgoing" }); +const communities = await graph.analytics.detectCommunitiesAsync({ + scope: "visible", + weighted: true, +}); ``` -Nodes outside the explored subset are not mounted in WebGL or the force simulation. +Analytics calculate data; they never change your graph automatically. Your application decides how results should appear. -## Interaction and export +## Remote data ```ts -graph.focusNode("workspace"); -graph.resetCamera(); +const graph = createOrbitGraph(container, { + dataSource: { + async getNode(nodeId) { + return fetch(`/api/nodes/${nodeId}`).then((response) => response.json()); + }, + async getNeighborhood({ nodeId, limit = 25, offset = 0 }) { + return fetch(`/api/nodes/${nodeId}/neighbors?limit=${limit}&offset=${offset}`) + .then((response) => response.json()); + }, + }, +}); -await graph.downloadPNG("product-network.png"); -graph.downloadJSON({ scope: "visible", fileName: "visible-network.json" }); +await graph.loadNeighborhood("team", { limit: 25, offset: 0 }); ``` -Keyboard navigation is enabled by default. Use arrow keys to move focus, `Enter` to focus a node, `+` to expand, `-` to collapse, and `Escape` to clear the current selection. +## Documentation + +- [Complete API reference](./docs/api/API.md) +- [Core package documentation](./packages/core/README.md) +- [Three.js package documentation](./packages/three/README.md) +- [React package documentation](./packages/react/README.md) +- [Changelog](./CHANGELOG.md) +- [Contributing](./CONTRIBUTING.md) -## Benchmark and examples +## Examples ```bash -npm run build +npm install +npm run dev:vanilla +npm run dev:react npm run dev:benchmark ``` -| Example | Purpose | -| --- | --- | -| [`examples/vanilla`](./examples/vanilla) | Direct TypeScript/browser integration | -| [`examples/react`](./examples/react) | React component, callbacks, and refs | -| [`examples/benchmark`](./examples/benchmark) | Generated graphs and FPS comparison | +The Vanilla and React examples demonstrate remote relationship pages, analytics, community visualization, labels, mini-map navigation, selection details, loading states, diagnostics, and exports. ## Development ```bash -npm install npm run typecheck npm run test:run npm run build ``` -## Roadmap - -See [ROADMAP.md](./ROADMAP.md). The next planned release focuses on Worker-based graph computation and graph analytics. - ## License -MIT \ No newline at end of file +MIT diff --git a/docs/api/API.md b/docs/api/API.md new file mode 100644 index 0000000..0d648c0 --- /dev/null +++ b/docs/api/API.md @@ -0,0 +1,647 @@ +# OrbitGraph API Reference + +OrbitGraph is a TypeScript library for exploring connected data in interactive 3D. It is designed for relationship graphs that can start small, load data on demand, and reveal only the connections a user needs. + +This reference covers the public APIs provided by the `@orbitgraph/core`, `@orbitgraph/three`, and `@orbitgraph/react` packages. + +## Contents + +- [Installation](#installation) +- [Packages](#packages) +- [Quick start](#quick-start) +- [Data model](#data-model) +- [Creating a graph](#creating-a-graph) +- [Options](#options) +- [Instance API](#instance-api) +- [Exploration](#exploration) +- [Search and filters](#search-and-filters) +- [Remote and GraphQL data](#remote-and-graphql-data) +- [Layouts and physics](#layouts-and-physics) +- [Camera, touch, and keyboard controls](#camera-touch-and-keyboard-controls) +- [Labels and mini-map](#labels-and-mini-map) +- [Analytics and visual presentation](#analytics-and-visual-presentation) +- [Events, loading, and diagnostics](#events-loading-and-diagnostics) +- [Export and view state](#export-and-view-state) +- [React](#react) +- [Performance guidance](#performance-guidance) + +## Installation + +### Three.js / Vanilla JavaScript + +```bash +npm install @orbitgraph/core @orbitgraph/three three +``` + +### React + +```bash +npm install @orbitgraph/core @orbitgraph/three @orbitgraph/react three +``` + +## Packages + +| Package | Use it for | +| --- | --- | +| `@orbitgraph/core` | Types, graph utilities, analytics, community detection, and data-source contracts. | +| `@orbitgraph/three` | The Three.js/WebGL renderer and imperative graph instance. | +| `@orbitgraph/react` | The declarative React component and its imperative ref API. | + +## Quick start + +```ts +import { createOrbitGraph } from "@orbitgraph/three"; +import type { GraphData } from "@orbitgraph/core"; + +const data: GraphData = { + nodes: [ + { id: "team", label: "Product Team", type: "team", color: "#22d3ee" }, + { id: "api", label: "Public API", type: "service", color: "#3b82f6" }, + ], + links: [ + { id: "team-owns-api", source: "team", target: "api", type: "owns", weight: 0.95 }, + ], +}; + +const container = document.querySelector("#graph"); + +if (!container) { + throw new Error("Graph container was not found."); +} + +const graph = createOrbitGraph(container, { + backgroundColor: "#050816", + labels: { mode: "important", importantNodeIds: ["team"] }, + miniMap: { enabled: true, interactive: true }, +}); + +graph.setData(data); +``` + +Call `graph.destroy()` when the container is permanently removed. + +## Data model + +### `GraphNode` + +```ts +type GraphNode = { + id: string; + label?: string; + type?: string; + size?: number; + color?: string; + data?: Record; +}; +``` + +`id` must be unique. `type` is useful for filtering, labels, styling, and grouping. `data` preserves arbitrary JSON-compatible metadata and is returned in interaction callbacks. + +### `GraphLink` + +```ts +type GraphLink = { + id?: string; + source: string; + target: string; + weight?: number; + type?: string; + color?: string; + data?: Record; +}; +``` + +Links are directed from `source` to `target`. A `weight` normally ranges from `0` to `1`; it affects link appearance and force-layout behavior. + +### `GraphData` + +```ts +type GraphData = { + nodes: GraphNode[]; + links: GraphLink[]; +}; +``` + +Every link should reference nodes present in the same data set. OrbitGraph can generate a relationship ID when one is omitted, but explicit IDs are recommended for updates and remote data. + +## Creating a graph + +```ts +import { createOrbitGraph } from "@orbitgraph/three"; + +const graph = createOrbitGraph(container, options); +``` + +`createOrbitGraph()` returns an `OrbitGraph` instance. The full data set stays in memory, while exploration and filters determine the subset mounted in WebGL and the force simulation. + +## Options + +```ts +type OrbitGraphOptions = { + backgroundColor?: string; + nodeColor?: string; + nodeSize?: number; + linkColor?: string; + linkOpacity?: number; + + initialView?: GraphInitialView; + layout?: GraphLayout; + layoutOptions?: GraphLayoutOptions; + dataSource?: GraphDataSource; + + linkFlow?: LinkFlowOptions; + camera?: OrbitGraphCameraOptions; + physics?: OrbitGraphPhysicsOptions; + accessibility?: GraphAccessibilityOptions; + mobileControls?: GraphMobileControlsOptions; + labels?: GraphLabelsOptions; + miniMap?: GraphMiniMapOptions; + + onNodeClick?: (event: NodeClickEvent) => void; + onLinkClick?: (event: LinkClickEvent) => void; + onNodeHover?: (event: NodeHoverEvent) => void; + onLinkHover?: (event: LinkHoverEvent) => void; + onSelectionChange?: (selection: GraphSelection) => void; + onVisibleDataChange?: (data: VisibleGraphData) => void; + onLoadingChange?: (state: GraphLoadingState) => void; + onDiagnostic?: (diagnostic: GraphDiagnostic) => void; + onKeyboardFocusChange?: (node: GraphNode | null) => void; +}; +``` + +### Initial views + +`initialView` decides what is visible immediately after `setData()`. + +```ts +// Render every node and link. +{ mode: "all" } + +// Render exactly one known node. +{ mode: "node", nodeId: "team" } + +// Render a node and its relationship neighborhood. +{ + mode: "neighborhood", + nodeId: "team", + depth: 2, + direction: "outgoing", + relationshipTypes: ["owns", "uses"], +} + +// Render a limited category of nodes. +{ mode: "type", nodeType: "service", maxNodes: 100 } +``` + +`direction` is one of `"incoming"`, `"outgoing"`, or `"both"`. + +### Link flow + +```ts +linkFlow: { + enabled: true, + maxParticles: 100, + particleSize: 0.08, + particleSpeed: 0.12, +} +``` + +Animated flow is optional. Disable it for the lowest rendering cost on large graphs. + +## Instance API + +### Data + +```ts +graph.setData(data); + +graph.addNode(node); +graph.removeNode(nodeId); + +graph.addLink(link); +graph.removeLink(linkId); +``` + +`setData()` replaces the complete loaded graph, clears temporary analytics styles, clears exploration history, and returns to the configured initial view. + +### Exploration + +```ts +graph.setInitialView({ mode: "node", nodeId: "team" }); + +graph.expandNode("team", { + depth: 1, + direction: "outgoing", + relationshipTypes: ["owns", "uses"], + limit: 25, + offset: 0, +}); + +graph.collapseNode("team"); +graph.resetExploration(); +graph.showAll(); +``` + +`expandNode()` accepts `GraphExpansionOptions`: + +| Option | Meaning | +| --- | --- | +| `depth` | Number of relationship levels to reveal. Defaults to `1`. | +| `direction` | `incoming`, `outgoing`, or `both`. Defaults to `both`. | +| `relationshipTypes` | Optional relationship types to include. | +| `limit` | Optional page size for immediate local expansion. | +| `offset` | Optional relationship offset for immediate local expansion. | + +Additional exploration helpers: + +```ts +graph.focusPath("team", "database", { direction: "outgoing" }); +graph.goBack(); +graph.goForward(); + +const state = graph.getNodeExplorationState("team"); +const history = graph.getExplorationHistory(); +``` + +`getNodeExplorationState()` is useful for custom Expand buttons. It reports whether the node is expanded, visible neighbors, hidden neighbors, and whether expansion is available. + +## Search and filters + +Filters refine the explored subset; they never expose hidden nodes. + +```ts +graph.search("payments"); +graph.toggleTypeFilter("service"); +graph.setTypeFilters(["team", "service"]); +graph.setMinimumLinkWeight(0.7); +graph.clearFilters(); +``` + +## Remote and GraphQL data + +### Generic data source + +Use `GraphDataSource` for on-demand loading. It keeps your API client independent from OrbitGraph. + +```ts +import type { GraphDataSource } from "@orbitgraph/core"; + +const dataSource: GraphDataSource = { + async getNode(nodeId) { + const response = await fetch(`/api/graph/nodes/${nodeId}`); + return response.json(); + }, + + async getNeighborhood({ nodeId, direction, limit, offset }) { + const params = new URLSearchParams({ + direction: direction ?? "both", + limit: String(limit ?? 25), + offset: String(offset ?? 0), + }); + const response = await fetch(`/api/graph/nodes/${nodeId}/neighbors?${params}`); + return response.json(); + }, +}; + +const graph = createOrbitGraph(container, { dataSource }); +``` + +```ts +await graph.loadNode("team"); + +const result = await graph.loadNeighborhood("team", { + direction: "outgoing", + limit: 25, + offset: 0, +}); +``` + +`loadNeighborhood()` merges the received nodes and links, refreshes the visual view, and caches the request. Pass `force: true` in load options when the same page must be requested again. + +### GraphQL + +`@orbitgraph/three` also exports `createGraphQLDataSource()`. It is an optional adapter: OrbitGraph itself does not require GraphQL. + +Use it to map your query response into `GraphNode`, `GraphLink`, and `GraphNeighborhoodResult`, then pass the resulting data source through `dataSource`. + +```ts +import { createGraphQLDataSource } from "@orbitgraph/three"; + +const dataSource = createGraphQLDataSource({ + endpoint: "/graphql", + // Configure your documents and map each response to OrbitGraph data. +}); +``` + +See the GraphQL data-source type definitions in your editor for the response mapping configuration required by your schema. + +## Layouts and physics + +```ts +graph.setLayout("force"); + +graph.setLayout("radial", { spacing: 14 }); +graph.setLayout("grid", { spacing: 12 }); +graph.setLayout("hierarchical", { + rootId: "team", + direction: "outgoing", + spacing: 16, +}); +``` + +Supported layouts are `"force"`, `"radial"`, `"grid"`, and `"hierarchical"`. + +### Worker physics + +```ts +const graph = createOrbitGraph(container, { + physics: { + worker: true, + tickRate: 60, + }, +}); +``` + +Physics uses a module Web Worker when the browser supports it, preserving UI responsiveness while D3 calculates force-layout positions. It automatically falls back to the main thread for SSR, test environments, unsupported browsers, or worker initialization failures. + +### Pinning + +Users can drag a node to pin it. Release it programmatically with: + +```ts +graph.unpinNode("team"); +``` + +## Camera, touch, and keyboard controls + +```ts +const graph = createOrbitGraph(container, { + camera: { + minDistance: 2, + maxDistance: 1_000, + movementSpeed: 18, + boostMultiplier: 2.5, + keyboardNavigation: true, + }, +}); + +graph.focusNode("team"); +graph.resetCamera(); +``` + +Desktop controls: + +- Left drag: orbit. +- Right drag: pan. +- Mouse wheel: zoom. +- `W`, `A`, `S`, `D`: move horizontally when keyboard camera navigation is enabled. +- `Q` and `E`: move vertically. +- `Shift`: movement boost. + +Touch controls: + +- One finger: orbit. +- Two fingers: pan and pinch-to-zoom. + +Keyboard graph navigation is configured through `accessibility`. It supports focus movement across visible nodes, activation, expansion, collapse, camera focus, and clearing selection. Use `onKeyboardFocusChange` to mirror keyboard focus in external UI. + +## Labels and mini-map + +### Intelligent labels + +```ts +labels: { + mode: "important", + importantNodeIds: ["team", "payments-api"], + maxVisible: 20, + showNodeType: true, + fontScale: 1, +} +``` + +| Option | Description | +| --- | --- | +| `mode` | `hover`, `selected`, `important`, or `all`. | +| `importantNodeIds` | Nodes that should retain a label in `important` mode. | +| `maxVisible` | Limit for persistent labels, preventing visual overload. | +| `showNodeType` | Draw the node type as a smaller second line. | +| `fontScale` | Adjust label text and padding scale. | + +The hover label remains available independently, so users can inspect a node even when persistent labels are intentionally limited. + +### Mini-map + +```ts +miniMap: { + enabled: true, + position: "bottom-right", + width: 180, + height: 120, + interactive: true, + showViewport: true, + ariaLabel: "Graph overview", +} +``` + +The mini-map visualizes the currently visible graph rather than the hidden source data. With `interactive: true`, clicking it moves the camera target. + +## Analytics and visual presentation + +The graph instance exposes two focused controllers: + +```ts +graph.analytics; +graph.presentation; +``` + +### Centrality + +```ts +const degree = graph.analytics.degree({ scope: "visible" }); +const pageRank = graph.analytics.pageRank({ scope: "visible" }); +const betweenness = graph.analytics.betweenness({ + scope: "visible", + normalized: true, +}); +``` + +`scope` is `"all"` by default or `"visible"` for the explored and filtered subset. + +- `degree()` returns degree, in-degree, out-degree, and weighted variants for every node. +- `pageRank()` returns ranking scores and convergence metadata. +- `betweenness()` returns bridge importance for every node. + +### Communities + +```ts +const result = await graph.analytics.detectCommunitiesAsync({ + scope: "visible", + weighted: true, +}); + +console.log(result.communities); +``` + +Use `detectCommunities()` for synchronous execution on small graphs. Prefer `detectCommunitiesAsync()` in interactive interfaces because it yields between passes. For very large graphs, run analysis in application-managed background work. + +### Turning metrics into a visual explanation + +Analytics deliberately do not mutate the graph automatically. Apply temporary styles through `presentation`: + +```ts +const pageRank = graph.analytics.pageRank({ scope: "visible" }); + +graph.presentation.setNodeStyles({ + "payments-api": { + color: "#facc15", + scale: 1.65, + glow: 0.9, + }, +}); + +graph.presentation.clearNodeStyles(); +``` + +This separation lets your application decide whether a metric affects color, size, glow, a legend, a details panel, or nothing at all. + +## Events, loading, and diagnostics + +### Selection and pointer events + +```ts +const graph = createOrbitGraph(container, { + onNodeClick: ({ node }) => console.log(node), + onLinkClick: ({ link }) => console.log(link), + onNodeHover: ({ node }) => console.log(node), + onLinkHover: ({ link }) => console.log(link), + onSelectionChange: (selection) => console.log(selection), +}); +``` + +`GraphSelection` is one of: + +```ts +type GraphSelection = + | { kind: "node"; node: GraphNode } + | { kind: "link"; link: GraphLink } + | null; +``` + +### Visible data + +```ts +onVisibleDataChange: ({ nodes, links }) => { + visibleCount.textContent = `${nodes.length} nodes · ${links.length} links`; +} +``` + +This callback reports the data currently mounted after exploration and filters. It is the right source for counters, mini summaries, and visible-scope analytics UI. + +### Loading and diagnostics + +```ts +onLoadingChange: (state) => { + if (state.loading) { + console.log(`Loading ${state.operation} for ${state.nodeId}`); + } +}, + +onDiagnostic: (diagnostic) => { + console.error(diagnostic.code, diagnostic.message); +}, +``` + +```ts +const state = graph.getLoadingState(); +// { +// loading: boolean, +// operation: "node" | "neighborhood" | null, +// nodeId: string | null, +// error: GraphLoadError | null, +// } +``` + +Use diagnostics to show application-level retry messages. OrbitGraph does not display network errors by itself, which keeps your product’s error handling and wording under your control. + +## Export and view state + +### Images and JSON + +```ts +const png = await graph.exportPNG(); +await graph.downloadPNG("architecture.png"); + +const fullJSON = graph.exportJSON({ scope: "all" }); +const visibleJSON = graph.exportJSON({ scope: "visible" }); +graph.downloadJSON({ scope: "visible", fileName: "explored-subgraph.json" }); +``` + +### Persisting user exploration + +```ts +const viewState = graph.exportViewState(); +localStorage.setItem("graph-view", JSON.stringify(viewState)); + +const saved = localStorage.getItem("graph-view"); + +if (saved) { + graph.importViewState(JSON.parse(saved)); +} +``` + +View state includes exploration, filters, layout, and layout options. It does not replace your graph data; load data first, then restore the view. + +## React + +```tsx +import { useRef } from "react"; +import { OrbitGraph, type OrbitGraphHandle } from "@orbitgraph/react"; +import type { GraphData } from "@orbitgraph/core"; + +export function GraphView({ data }: { data: GraphData }) { + const graphRef = useRef(null); + + return ( + <> + + + console.log(selection)} + onDiagnostic={(diagnostic) => console.error(diagnostic)} + /> + + ); +} +``` + +The ref exposes the same user-facing actions as the Three.js instance, including exploration, camera movement, remote loading, exports, loading state, analytics, and presentation controllers. + +Keep graph data declarative through the `data` prop. Use the ref for imperative user actions such as expanding a branch, exporting, or focusing a node. + +## Performance guidance + +- Start with `initialView: { mode: "node" }`, `neighborhood`, or `type` for large data sets. +- Hidden nodes are excluded from WebGL mounting and the active physics simulation. +- Keep collision forces enabled for smaller graphs; OrbitGraph automatically disables the expensive collision force above its threshold. +- Leave animated link flow disabled unless it adds meaningful value. +- Keep persistent labels capped with `labels.maxVisible`. +- Use the Worker physics mode for responsive interaction while larger force layouts settle. +- Use `loadNeighborhood()` with `limit` and `offset` instead of loading an entire remote graph at once. +- Run community detection asynchronously in interactive UI and prefer `scope: "visible"` when users are exploring a subset. + +## Lifecycle + +```ts +graph.destroy(); +``` + +Always call `destroy()` when removing a non-React graph. It releases rendering resources, controls, events, active physics work, workers, overlays, and the canvas element. diff --git a/docs/api/README.md b/docs/api/README.md deleted file mode 100644 index 6f56ede..0000000 --- a/docs/api/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# OrbitGraph API guide - -This reference is organized around actions you can copy into an application. - -## Create and load - -```ts -const graph = createOrbitGraph(container, options); -graph.setData(data); -``` - -## Explore - -```ts -graph.expandNode("team", { depth: 1, direction: "outgoing" }); -graph.collapseNode("team"); -graph.resetExploration(); -graph.showAll(); - -graph.goBack(); -graph.goForward(); -graph.focusPath("team", "service"); -``` - -## Search and filter - -```ts -graph.search("workspace"); -graph.toggleTypeFilter("service"); -graph.setTypeFilters(["group", "service"]); -graph.setMinimumLinkWeight(0.7); -graph.clearFilters(); -``` - -## Camera, touch, and keyboard - -```ts -const graph = createOrbitGraph(container, { - camera: { - keyboardNavigation: true, - minDistance: 2, - maxDistance: 1000, - }, - mobileControls: { - enabled: "auto", - position: "bottom-right", - }, - accessibility: { - ariaLabel: "Interactive relationship graph", - }, -}); - -graph.focusNode("team"); -graph.resetCamera(); -graph.unpinNode("team"); -``` - -## Export - -```ts -const png = await graph.exportPNG(); -await graph.downloadPNG("network.png"); - -const completeJSON = graph.exportJSON(); -const visibleJSON = graph.exportJSON({ scope: "visible" }); -graph.downloadJSON({ scope: "visible", fileName: "visible-network.json" }); -``` - -## Events - -```ts -createOrbitGraph(container, { - onNodeClick: ({ node }) => {}, - onLinkClick: ({ link }) => {}, - onSelectionChange: (selection) => {}, - onVisibleDataChange: ({ nodes, links }) => {}, - onLoadingChange: (state) => {}, - onKeyboardFocusChange: (node) => {}, -}); -``` - -## React - -```tsx -const graphRef = useRef(null); - -; - -graphRef.current?.expandNode("team"); -await graphRef.current?.downloadPNG("network.png"); -``` - -See the package README for the complete React prop and ref API. \ No newline at end of file diff --git a/docs/api/assets/highlight.css b/docs/api/assets/highlight.css index a39d918..d3f7b80 100644 --- a/docs/api/assets/highlight.css +++ b/docs/api/assets/highlight.css @@ -5,30 +5,32 @@ --dark-hl-1: #D4D4D4; --light-hl-2: #A31515; --dark-hl-2: #CE9178; - --light-hl-3: #AF00DB; - --dark-hl-3: #C586C0; - --light-hl-4: #001080; - --dark-hl-4: #9CDCFE; - --light-hl-5: #0000FF; - --dark-hl-5: #569CD6; - --light-hl-6: #0070C1; - --dark-hl-6: #4FC1FF; - --light-hl-7: #267F99; - --dark-hl-7: #4EC9B0; - --light-hl-8: #098658; - --dark-hl-8: #B5CEA8; - --light-hl-9: #800000; - --dark-hl-9: #808080; - --light-hl-10: #800000; - --dark-hl-10: #569CD6; - --light-hl-11: #E50000; - --dark-hl-11: #9CDCFE; - --light-hl-12: #0000FF; - --dark-hl-12: #CE9178; + --light-hl-3: #800000; + --dark-hl-3: #808080; + --light-hl-4: #800000; + --dark-hl-4: #569CD6; + --light-hl-5: #E50000; + --dark-hl-5: #9CDCFE; + --light-hl-6: #0000FF; + --dark-hl-6: #CE9178; + --light-hl-7: #AF00DB; + --dark-hl-7: #C586C0; + --light-hl-8: #001080; + --dark-hl-8: #9CDCFE; + --light-hl-9: #0000FF; + --dark-hl-9: #569CD6; + --light-hl-10: #0070C1; + --dark-hl-10: #4FC1FF; + --light-hl-11: #267F99; + --dark-hl-11: #4EC9B0; + --light-hl-12: #098658; + --dark-hl-12: #B5CEA8; --light-hl-13: #000000FF; --dark-hl-13: #D4D4D4; --light-hl-14: #000000; --dark-hl-14: #C8C8C8; + --light-hl-15: #008000; + --dark-hl-15: #6A9955; --light-code-background: #FFFFFF; --dark-code-background: #1E1E1E; } @@ -49,6 +51,7 @@ --hl-12: var(--light-hl-12); --hl-13: var(--light-hl-13); --hl-14: var(--light-hl-14); + --hl-15: var(--light-hl-15); --code-background: var(--light-code-background); } } @@ -68,6 +71,7 @@ --hl-12: var(--dark-hl-12); --hl-13: var(--dark-hl-13); --hl-14: var(--dark-hl-14); + --hl-15: var(--dark-hl-15); --code-background: var(--dark-code-background); } } @@ -87,6 +91,7 @@ --hl-12: var(--light-hl-12); --hl-13: var(--light-hl-13); --hl-14: var(--light-hl-14); + --hl-15: var(--light-hl-15); --code-background: var(--light-code-background); } @@ -106,6 +111,7 @@ --hl-12: var(--dark-hl-12); --hl-13: var(--dark-hl-13); --hl-14: var(--dark-hl-14); + --hl-15: var(--dark-hl-15); --code-background: var(--dark-code-background); } @@ -124,4 +130,5 @@ .hl-12 { color: var(--hl-12); } .hl-13 { color: var(--hl-13); } .hl-14 { color: var(--hl-14); } +.hl-15 { color: var(--hl-15); } pre, code, math[display='block'] { background: var(--code-background); } diff --git a/docs/api/assets/navigation.js b/docs/api/assets/navigation.js index 4698517..f618d09 100644 --- a/docs/api/assets/navigation.js +++ b/docs/api/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "eJydl11v2jAUhv9Lrulo6dYx7iZWxqatdEXipqom45wSCyeO7BMKmvbf5wRB4nzgk10iP37e42PLxM9/AoQ9BpNgA4gi2VwZZBohDAZByjCyA6HiWQwJmmENeRdhLC23FUkYTMa34/Hd9fjv4GxMQb8qHbOEQ5utMuwzaZAMhUpMJNIr2KdS6eJ3m7aL9WVwpWFoNC+dsQozCWaYj/y2I65hNAh4JGSoIQkmz2fNV83SqHRwyYypOopx13QzqtZRAJ85B2PEWkiBh0VarKeU4iFtKNtm1Aq+/vTx5sOoHvWFIbuszgmyaqkyXd3vLuGRo2mFBu5ud6v1hJGk9/uUJcbSpO7WaWrE6fDNhUGlD0tk6OlNx6QegaDP1ZLz6nN6xfVI6SVXGpdcpX71CSSJZ0IiqeYKSBJ/SwQKJlcC3i6LKyBJ/H25eDiuknRWGzgp5Ac7qAwvm49MDx2pXgelyUWy9TgtQVMpFtq/NMJxqJIk9U9lL2OYqgS1kobUitYppLAHEJtorXSkVJhXSorrmNQ78FcG+kCPKvDeIU9gMuk5oE2eFqNCz+bnBFlVucIJ56ptBinq0Tpn9rPHEEJclqwnnaIKSBIvQVL+zs+YT5rfd49axPZS3XW3waEoyhWT2WVdQfhU+U00lYJv73f287TT52IU6UyqN9/+1DiKdq529mPAW2uJ+aT5+SY0wMUoUkKlLuaTLvRaYHH2piwGzXzd7eDpMfSA3ur84+LyvdDC+vQrYR8YEvzPhjrYLn5xXniMY/vzqxgiv7/KZc1ZEsrG+ktbnaQ391GrtLFrbeICpHtL5Y5pwdayQ+sab91OYqSh4yFbDP1HJ5vP2dLUVZX7qOV2GQhtxtcsKW75qrNOu+a793a9L/8Au8zEMg==" \ No newline at end of file +window.navigationData = "eJytmV1T2zgUhv9LrqG0tNtluWMpLO3wEcgMN53OjmKfxhoUySvJQGan/72yQ2zJlnyOWy4Tv+d5ZVkfR0df/59ZeLaz41nOLNs3qtIZmNnerGS2qP9VWbUGac2B//xNYdfCiR64zGfHR++Pjj6+Pfqx17JWYC2Xq31jmbaQx3A9CUbk0oJmmeVK7jOZ78NzqbSNgeNKjF+C/q70mskMYlDvMUbSIFhtbgpe1uZC6eZ3DJvSYh6Z0nBgdNYx1yqvBJiD+sm/7klIONybZQUXuQY5O/7aYv7RrCw6RiaYMT6jeR6S3h367fgb7BOAlGDMTdm8SEezm9JnDaW9Jr796893fxx68FO1XleS280nsNB8T8wjGTHd6g5MJewEp20AZtT06EnmppDhSy4cAHunZATJqm3nOL+VkaCf3EowzqsVZNSiWVNw4FZHw8JKA1yB1TxDujaQ0uCcraQylmcIudURsXo7kjDqi4wEPXsumTSEqRNVUy12y9YFN1bpzcIyi3zPRNAEQ9Bta8l+/ZhJdhNcJsHd5rTIVImjd0IS+JwLS2qzJySBP7tlgjNxz+FpHOwJSeAvi5vr7VuSxupATjK5ZEsQVypHOqWV0aHoBjiUEuEbVaU3Ik8zAUdsqyelwbl8QJhOQUMplp9prTTC28nIUJdzEmaFrySjb1yWyPAVPJCS4Fdc8itWkr5aqJ2CnyvD8db3xDQD5TIXOFXSakWcKNEQktk18FWxVLpQKt92NcEuETTZ8LYCjeRaA/lkEyQ3TehpNujSeE1dFWuht80TJl0sgmQ1d8xzd6gyBJNQS8aTRpEnJIEXICgpXyvDoPWeONd87WbmY7obAhUFec9ENY5rFBiqXvtPBc8ezh7d4TfJC2UU6LlQT9j36eko2Av16BJGtK2dDIPW45vQAaGMAiW0NJRh0Bu95HZ7MmRrt1NhvZvQ023oBpPR82Jj3NGO7hAG0I3qTHd8AYpoMfycreCOyQes+T0dFYtsJaEMg95zw5cC8BpBX4iBMyaySrje8opIp24YayaC0sb3SjbrpGc1Hhoaf/wQ80zUEsa8RmoKcY9dP9PwO/UIOW/KUruyDofxhg/UU8gnZiOzafgmZODxLSiisszGK5zNI3KJs5tyF0zmYjA3O1pfOWGF0aoczMwYuBHSuR3ykWnOliKBDYnvD4OetIUbivGebB5NKxafSCY21o3ql8xcgHdA29WPO24qZqym7J8yUPaLDuXNNRg365u8ckLT42Go2+1lV6/sHWITRoOIMY/YCBlyU+MjWcFvv1Nir+nQI0HY6MZvDKI2v1zHp78UHvtqFxZjpq98YzFmRdvVg80MfaGYmnYpsuvsaDE0taTQC6JhCPoe6Zjfv4DouUy/gaiTeX9pWtjNcGfruURjft0Ne6l4EMnv9tKdflwc7Rv11ESHbrWlugwiiE5+ISZZIBy4RaOojq7rJzj5aqLDHfxXgRlZa0IdmWpK16/9HTPJ9tREh/tdGoXSWyX1IEXfZ1IRv3kSHBq8ylFwiKXtGplLVC0EMzR2RujwkYCxk5Ovjl0ioxapG+WITSzfSvNTeVdzwvn2E61OV9U=" \ No newline at end of file diff --git a/docs/api/assets/search.js b/docs/api/assets/search.js index 91adf4b..6b3363e 100644 --- a/docs/api/assets/search.js +++ b/docs/api/assets/search.js @@ -1 +1 @@ -window.searchData = "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"; \ No newline at end of file +window.searchData = "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"; \ No newline at end of file diff --git a/docs/api/classes/core_src.Graph.html b/docs/api/classes/core_src.Graph.html index be5c343..1f11aec 100644 --- a/docs/api/classes/core_src.Graph.html +++ b/docs/api/classes/core_src.Graph.html @@ -18,12 +18,12 @@

Class Graph

-
const graph = new Graph({
nodes: [
{ id: "team", label: "Product Team" },
{ id: "service", label: "Notification Service" }
],
links: [
{
source: "team",
target: "service",
type: "owns"
}
]
});

console.log(graph.getNeighbors("team")); +
const graph = new Graph({
nodes: [
{ id: "team", label: "Product Team" },
{ id: "service", label: "Notification Service" }
],
links: [
{
source: "team",
target: "service",
type: "owns"
}
]
});

console.log(graph.getNeighbors("team"));
+
  • Defined in packages/core/src/Graph.ts:28
  • @@ -67,7 +67,7 @@

    Parameters

    Returns Graph

    +
  • Defined in packages/core/src/Graph.ts:38
  • @@ -94,7 +94,7 @@

    Returns voidThrows

    When the source or target node does not exist.

    +
  • Defined in packages/core/src/Graph.ts:90
    • @@ -112,7 +112,7 @@

      Parameters

    Returns void

    +
  • Defined in packages/core/src/Graph.ts:72
  • +
  • Defined in packages/core/src/Graph.ts:128
  • +
  • Defined in packages/core/src/Graph.ts:142
  • +
  • Defined in packages/core/src/Graph.ts:154
  • +
  • Defined in packages/core/src/Graph.ts:118
    • @@ -195,7 +195,7 @@

      Parameters

    Returns GraphLink[]

    +
  • Defined in packages/core/src/Graph.ts:183
  • +
  • Defined in packages/core/src/Graph.ts:135
    • @@ -224,7 +224,7 @@

      Parameters

    Returns void

    +
  • Defined in packages/core/src/Graph.ts:214
    • @@ -241,7 +241,7 @@

      Parameters

    Returns void

    +
  • Defined in packages/core/src/Graph.ts:196
    • @@ -259,7 +259,7 @@

      Parameters

    Returns void

    +
  • Defined in packages/core/src/Graph.ts:51
  • +
  • Defined in packages/core/src/Graph.ts:231
  • +
  • Defined in packages/three/src/OrbitGraph.ts:55
  • @@ -27,6 +27,11 @@
    + +
    +
    addLink addNode @@ -80,7 +85,20 @@

    Parameters

  • options: OrbitGraphOptions = {}
  • Returns OrbitGraph

    +
  • Defined in packages/three/src/OrbitGraph.ts:93
  • +
    + +
    +
    + +
    +
    + +
    @@ -96,7 +114,7 @@

    Parameters

  • link: GraphLink
  • Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:420
    • @@ -109,7 +127,7 @@

      Parameters

    • node: GraphNode

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:408
  • +
  • Defined in packages/three/src/OrbitGraph.ts:452
    • @@ -131,7 +149,7 @@

      Parameters

    • nodeId: string

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:393
  • +
  • Defined in packages/three/src/OrbitGraph.ts:543
    • @@ -155,7 +173,7 @@

      Parameters

    • options: GraphJSONExportOptions & { fileName?: string } = {}

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:537
    • @@ -170,7 +188,7 @@

      Parameters

    • fileName: string = "orbitgraph.png"

    Returns Promise<void>

    +
  • Defined in packages/three/src/OrbitGraph.ts:527
    • @@ -184,7 +202,7 @@

      Parameters

    • options: GraphExpansionOptions = {}

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:388
    • @@ -199,7 +217,7 @@

      Parameters

    • options: GraphJSONExportOptions = {}

    Returns string

    +
  • Defined in packages/three/src/OrbitGraph.ts:532
  • +
  • Defined in packages/three/src/OrbitGraph.ts:522
  • +
  • Defined in packages/three/src/OrbitGraph.ts:344
    • @@ -232,7 +250,7 @@

      Parameters

    • nodeId: string

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:463
    • @@ -247,7 +265,7 @@

      Parameters

    • options: GraphPathOptions = {}

    Returns boolean

    +
  • Defined in packages/three/src/OrbitGraph.ts:475
  • +
  • Defined in packages/three/src/OrbitGraph.ts:509
  • +
  • Defined in packages/three/src/OrbitGraph.ts:373
    • @@ -278,7 +296,7 @@

      Parameters

    • nodeId: string

    Returns GraphNodeExplorationState

    +
  • Defined in packages/three/src/OrbitGraph.ts:513
  • +
  • Defined in packages/three/src/OrbitGraph.ts:489
  • +
  • Defined in packages/three/src/OrbitGraph.ts:499
    • @@ -309,7 +327,7 @@

      Parameters

    • state: OrbitGraphViewState

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:354
    • @@ -323,7 +341,7 @@

      Parameters

    • options: GraphNeighborhoodLoadOptions = {}

    Returns Promise<GraphNeighborhoodResult | null>

    +
  • Defined in packages/three/src/OrbitGraph.ts:381
    • @@ -336,7 +354,7 @@

      Parameters

    • nodeId: string

    Returns Promise<GraphNode | undefined>

    +
  • Defined in packages/three/src/OrbitGraph.ts:377
    • @@ -349,7 +367,7 @@

      Parameters

    • linkId: string

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:426
    • @@ -362,7 +380,7 @@

      Parameters

    • nodeId: string

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:414
  • +
  • Defined in packages/three/src/OrbitGraph.ts:457
  • +
  • Defined in packages/three/src/OrbitGraph.ts:398
    • @@ -393,7 +411,7 @@

      Parameters

    • query: string

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:432
    • @@ -408,7 +426,7 @@

      Parameters

    • data: GraphData

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:322
    • @@ -421,7 +439,7 @@

      Parameters

    • OptionaldataSource: GraphDataSource

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:369
    • @@ -434,7 +452,7 @@

      Parameters

    • view: GraphInitialView

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:333
    • @@ -448,7 +466,7 @@

      Parameters

    • options: GraphLayoutOptions = {}

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:338
    • @@ -461,7 +479,7 @@

      Parameters

    • weight: number

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:447
    • @@ -474,7 +492,7 @@

      Parameters

    • types: string[]

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:442
  • +
  • Defined in packages/three/src/OrbitGraph.ts:403
    • @@ -496,7 +514,7 @@

      Parameters

    • type: string

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:437
    • @@ -509,7 +527,7 @@

      Parameters

    • nodeId: string

    Returns void

    +
  • Defined in packages/three/src/OrbitGraph.ts:517
  • +
  • Defined in packages/three/src/OrbitGraph.ts:575
  • @@ -129,19 +170,24 @@

    Settings

    On This Page

    -
    getting-started
    performance
    relationship-exploration
    +
    data-sources
    getting-started
    interaction-and-export
    performance
    relationship-exploration
    core/src
    react/src
    three/src
    Graph
    -
    GraphAccessibilityOptions
    GraphData
    GraphDataSource
    GraphDirection
    GraphExpansionOptions
    GraphExplorationHistoryState
    GraphExplorerExpansionState
    GraphExplorerState
    GraphExportScope
    GraphFilterState
    GraphInitialView
    GraphJSONExportOptions
    GraphLayout
    GraphLayoutOptions
    GraphLoadingState
    GraphMobileControlsOptions
    GraphNeighborhoodLoadOptions
    GraphNeighborhoodQuery
    GraphNeighborhoodResult
    GraphNode
    GraphNodeExplorationState
    GraphPathFocusState
    GraphPathOptions
    GraphSelection
    JSONPrimitive
    JSONValue
    LinkClickEvent
    LinkFlowOptions
    LinkHoverEvent
    NodeClickEvent
    NodeHoverEvent
    OrbitGraphCameraOptions
    OrbitGraphOptions
    OrbitGraphViewState
    VisibleGraphData
    +
    BetweennessOptions
    CommunityDetectionOptions
    CommunityDetectionResult
    GraphAccessibilityOptions
    GraphCommunity
    GraphData
    GraphDataSource
    GraphDegreeMetrics
    GraphDiagnostic
    GraphDirection
    GraphExpansionOptions
    GraphExplorationHistoryState
    GraphExplorerExpansionState
    GraphExplorerState
    GraphExportScope
    GraphFilterState
    GraphInitialView
    GraphJSONExportOptions
    GraphLabelMode
    GraphLabelsOptions
    GraphLayout
    GraphLayoutOptions
    GraphLoadError
    GraphLoadingState
    GraphLoadOperation
    GraphMiniMapOptions
    GraphMiniMapPosition
    GraphMobileControlsOptions
    GraphNeighborhoodLoadOptions
    GraphNeighborhoodQuery
    GraphNeighborhoodResult
    GraphNode
    GraphNodeExplorationState
    GraphPathFocusState
    GraphPathOptions
    GraphSelection
    JSONPrimitive
    JSONValue
    LinkClickEvent
    LinkFlowOptions
    LinkHoverEvent
    NodeClickEvent
    NodeHoverEvent
    OrbitGraphCameraOptions
    OrbitGraphOptions
    OrbitGraphPhysicsOptions
    OrbitGraphViewState
    PageRankOptions
    PageRankResult
    VisibleGraphData
    +
    +
    calculateBetweennessCentrality
    calculateDegreeMetrics
    calculatePageRank
    detectCommunities
    detectCommunitiesAsync
    +
    BetweennessOptionsCommunityDetectionOptionsCommunityDetectionResultGraphAccessibilityOptionsGraphCommunityGraphDataGraphDataSourceGraphDegreeMetricsGraphDiagnosticGraphDirectionGraphExpansionOptionsGraphExplorationHistoryStateGraphExplorerExpansionStateGraphExplorerStateGraphExportScopeGraphFilterStateGraphInitialViewGraphJSONExportOptionsGraphLabelModeGraphLabelsOptionsGraphLayoutGraphLayoutOptionsGraphLinkGraphLoadErrorGraphLoadingStateGraphLoadOperationGraphMiniMapOptionsGraphMiniMapPositionGraphMobileControlsOptionsGraphNeighborhoodLoadOptionsGraphNeighborhoodQueryGraphNeighborhoodResultGraphNodeGraphNodeExplorationStateGraphPathFocusStateGraphPathOptionsGraphSelectionJSONPrimitiveJSONValueLinkClickEventLinkFlowOptionsLinkHoverEventNodeClickEventNodeHoverEventOrbitGraphCameraOptionsOrbitGraphOptionsOrbitGraphPhysicsOptionsOrbitGraphViewStatePageRankOptionsPageRankResultVisibleGraphData
    +
    Functions +
    -
    OrbitGraph
    +
    GraphAnalyticsController
    GraphMiniMap
    GraphPresentationController
    GraphQLDataSourceError
    OrbitGraph
    +
    +
    BetweennessAnalyticsOptions
    BetweennessOptions
    CommunityDetectionAnalyticsOptions
    CommunityDetectionOptions
    CommunityDetectionResult
    DegreeMetricsOptions
    GraphAnalyticsScope
    GraphAnalyticsScopeOptions
    GraphDegreeMetrics
    GraphNodePresentationStyle
    GraphNodePresentationStyles
    GraphQLClientOptions
    GraphQLDataSourceOptions
    GraphQLNeighborhoodOperation
    GraphQLNodeOperation
    GraphQLRequest
    GraphQLResponseError
    GraphQLVariables
    PageRankAnalyticsOptions
    PageRankOptions
    PageRankResult
    -
    createOrbitGraph
    +
    createGraphQLClient
    createGraphQLDataSource
    createOrbitGraph
    type GraphAccessibilityOptions = {
        ariaLabel?: string;
        keyboardNavigation?: boolean;
    }
    +
  • Defined in packages/core/src/types.ts:570
  • @@ -42,7 +42,7 @@
    +
  • Defined in packages/core/src/types.ts:581
  • keyboardNavigation?: boolean
    @@ -50,12 +50,12 @@
    +
  • Defined in packages/core/src/types.ts:575
  • type GraphData = {
        links: GraphLink[];
        nodes: GraphNode[];
    }
    +
  • Defined in packages/core/src/types.ts:66
  • @@ -34,12 +34,12 @@
    links: GraphLink[]
    +
  • Defined in packages/core/src/types.ts:68
  • nodes: GraphNode[]
    +
  • Defined in packages/core/src/types.ts:67
  • type GraphDataSource = {
        getNeighborhood: (
            query: GraphNeighborhoodQuery,
        ) => Promise<GraphNeighborhoodResult>;
        getNode?: (nodeId: string) => Promise<GraphNode | undefined>;
    }
    +
  • Defined in packages/core/src/types.ts:529
  • @@ -38,14 +38,14 @@
    +
  • Defined in packages/core/src/types.ts:533
  • getNode?: (nodeId: string) => Promise<GraphNode | undefined>

    Loads one node, commonly used to load the first exploration root.

    +
  • Defined in packages/core/src/types.ts:531
  • +
  • Defined in packages/core/src/types.ts:74
  • type GraphExpansionOptions = {
        depth?: number;
        direction?: GraphDirection;
        limit?: number;
        offset?: number;
        relationshipTypes?: string[];
    }
    +
  • Defined in packages/core/src/types.ts:79
  • @@ -40,12 +40,12 @@
    +
  • Defined in packages/core/src/types.ts:81
  • direction?: GraphDirection
    @@ -58,7 +58,7 @@
    +
  • Defined in packages/core/src/types.ts:84
  • limit?: number
    @@ -66,7 +66,7 @@
    +
  • Defined in packages/core/src/types.ts:94
  • offset?: number
    @@ -74,14 +74,14 @@
    +
  • Defined in packages/core/src/types.ts:101
  • relationshipTypes?: string[]

    Optional relationship types to include while expanding.

    +
  • Defined in packages/core/src/types.ts:87
  • type GraphExplorationHistoryState = {
        canGoBack: boolean;
        canGoForward: boolean;
        index: number;
        length: number;
    }
    +
  • Defined in packages/core/src/types.ts:183
  • @@ -38,28 +38,28 @@
    +
  • Defined in packages/core/src/types.ts:185
  • canGoForward: boolean

    Whether a later exploration state can be restored.

    +
  • Defined in packages/core/src/types.ts:188
  • index: number

    Current zero-based history entry index.

    +
  • Defined in packages/core/src/types.ts:191
  • length: number

    Total number of exploration history entries.

    +
  • Defined in packages/core/src/types.ts:194
  • type GraphExplorerExpansionState = {
        nodeId: string;
        pages: GraphExpansionOptions[];
    }
    +
  • Defined in packages/core/src/types.ts:452
  • @@ -36,14 +36,14 @@
    +
  • Defined in packages/core/src/types.ts:454
  • Loaded neighborhood pages and their options.

    +
  • Defined in packages/core/src/types.ts:456
  • type GraphExplorerState = {
        activeView: GraphInitialView;
        expansions: GraphExplorerExpansionState[];
        initialView: GraphInitialView;
        path: GraphPathFocusState | null;
    }
    +
  • Defined in packages/core/src/types.ts:475
  • @@ -40,28 +40,28 @@
    +
  • Defined in packages/core/src/types.ts:479
  • Current paginated node expansions.

    +
  • Defined in packages/core/src/types.ts:481
  • initialView: GraphInitialView

    Configured entry point used by reset exploration.

    +
  • Defined in packages/core/src/types.ts:477
  • path: GraphPathFocusState | null

    Current focused path, or null when normal exploration is active.

    +
  • Defined in packages/core/src/types.ts:483
  • +
  • Defined in packages/core/src/types.ts:585
  • +
  • Defined in packages/core/src/types.ts:444
  • +
  • Defined in packages/core/src/types.ts:121
  • type GraphJSONExportOptions = {
        pretty?: boolean;
        scope?: GraphExportScope;
    }
    +
  • Defined in packages/core/src/types.ts:588
  • @@ -37,12 +37,12 @@
    +
  • Defined in packages/core/src/types.ts:596
  • @@ -56,7 +56,7 @@
    +
  • Defined in packages/core/src/types.ts:593
  • +
  • Defined in packages/core/src/types.ts:426
  • type GraphLayoutOptions = {
        direction?: GraphDirection;
        rootId?: string;
        spacing?: number;
    }
    +
  • Defined in packages/core/src/types.ts:429
  • @@ -43,14 +43,14 @@
    +
  • Defined in packages/core/src/types.ts:434
  • rootId?: string

    Root node used by the hierarchical layout. Defaults to the first active node.

    +
  • Defined in packages/core/src/types.ts:431
  • spacing?: number
    @@ -58,12 +58,12 @@
    +
  • Defined in packages/core/src/types.ts:437
  • type GraphLink = {
        color?: string;
        data?: Record<string, JSONValue>;
        id?: string;
        source: string;
        target: string;
        type?: string;
        weight?: number;
    }
    +
  • Defined in packages/core/src/types.ts:40
  • @@ -41,49 +41,49 @@
    +
  • Defined in packages/core/src/types.ts:57
  • data?: Record<string, JSONValue>

    Additional JSON-compatible relationship information.

    +
  • Defined in packages/core/src/types.ts:60
  • id?: string

    Unique relationship identifier. Generated when omitted.

    +
  • Defined in packages/core/src/types.ts:42
  • source: string

    Identifier of the node where the relationship starts.

    +
  • Defined in packages/core/src/types.ts:45
  • target: string

    Identifier of the node where the relationship ends.

    +
  • Defined in packages/core/src/types.ts:48
  • type?: string

    Category describing the relationship.

    +
  • Defined in packages/core/src/types.ts:54
  • weight?: number

    Relative relationship importance, usually between 0 and 1.

    +
  • Defined in packages/core/src/types.ts:51
  • +
  • Defined in packages/core/src/types.ts:661
  • type GraphMobileControlsOptions = {
        ariaLabel?: string;
        enabled?: boolean | "auto";
        position?: "bottom-left" | "bottom-right";
        showResetButton?: boolean;
        showZoomButtons?: boolean;
    }
    +
  • Defined in packages/core/src/types.ts:600
  • @@ -39,7 +39,7 @@
    +
  • Defined in packages/core/src/types.ts:617
  • enabled?: boolean | "auto"
    @@ -53,7 +53,7 @@
    +
  • Defined in packages/core/src/types.ts:605
  • position?: "bottom-left" | "bottom-right"
    @@ -66,7 +66,7 @@
    +
  • Defined in packages/core/src/types.ts:608
  • showResetButton?: boolean
    @@ -74,12 +74,12 @@
    +
  • Defined in packages/core/src/types.ts:614
  • showZoomButtons?: boolean
    @@ -87,12 +87,12 @@
    +
  • Defined in packages/core/src/types.ts:611
  • +
  • Defined in packages/core/src/types.ts:539
  • +
  • Defined in packages/core/src/types.ts:504
  • type GraphNeighborhoodResult = {
        hasMore?: boolean;
        links: GraphLink[];
        nextOffset?: number | null;
        nodes: GraphNode[];
        totalNeighbors?: number;
    }
    +
  • Defined in packages/core/src/types.ts:510
  • @@ -39,35 +39,35 @@
    +
  • Defined in packages/core/src/types.ts:518
  • links: GraphLink[]

    Newly available relationships. Existing ids are updated when merged.

    +
  • Defined in packages/core/src/types.ts:514
  • nextOffset?: number | null

    Offset to use for the next page, when available.

    +
  • Defined in packages/core/src/types.ts:520
  • nodes: GraphNode[]

    Newly available nodes. Existing ids are updated when merged.

    +
  • Defined in packages/core/src/types.ts:512
  • totalNeighbors?: number

    Total direct neighbors when the backend can provide it.

    +
  • Defined in packages/core/src/types.ts:516
  • type GraphNode = {
        color?: string;
        data?: Record<string, JSONValue>;
        id: string;
        label?: string;
        size?: number;
        type?: string;
    }
    +
  • Defined in packages/core/src/types.ts:17
  • @@ -40,42 +40,42 @@
    +
  • Defined in packages/core/src/types.ts:31
  • data?: Record<string, JSONValue>

    Additional JSON-compatible information associated with the node.

    +
  • Defined in packages/core/src/types.ts:34
  • id: string

    Unique node identifier.

    +
  • Defined in packages/core/src/types.ts:19
  • label?: string

    Human-readable node name.

    +
  • Defined in packages/core/src/types.ts:22
  • size?: number

    Relative visual size of the node.

    +
  • Defined in packages/core/src/types.ts:28
  • type?: string

    Category used for filtering, styling, and grouping.

    +
  • Defined in packages/core/src/types.ts:25
  • type GraphNodeExplorationState = {
        canExpand: boolean;
        expanded: boolean;
        hiddenNeighbors: number;
        nodeId: string;
        visibleNeighbors: number;
    }
    +
  • Defined in packages/core/src/types.ts:163
  • @@ -39,35 +39,35 @@
    +
  • Defined in packages/core/src/types.ts:177
  • expanded: boolean

    Whether the node currently has one or more manual expansions.

    +
  • Defined in packages/core/src/types.ts:168
  • hiddenNeighbors: number

    Number of direct neighbors still hidden from the explored graph.

    +
  • Defined in packages/core/src/types.ts:174
  • nodeId: string

    Identifier of the node represented by this state.

    +
  • Defined in packages/core/src/types.ts:165
  • visibleNeighbors: number

    Number of direct neighbors currently visible in the explored graph.

    +
  • Defined in packages/core/src/types.ts:171
  • type GraphPathFocusState = {
        linkIds: string[];
        nodeIds: string[];
    }
    +
  • Defined in packages/core/src/types.ts:462
  • @@ -36,14 +36,14 @@
    +
  • Defined in packages/core/src/types.ts:466
  • nodeIds: string[]

    Node identifiers belonging to the visible path.

    +
  • Defined in packages/core/src/types.ts:464
  • type GraphPathOptions = {
        direction?: GraphDirection;
    }
    +
  • Defined in packages/core/src/types.ts:107
  • @@ -41,7 +41,7 @@
    +
  • Defined in packages/core/src/types.ts:112
  • +
  • Defined in packages/core/src/types.ts:390
  • +
  • Defined in packages/core/src/types.ts:4
  • +
  • Defined in packages/core/src/types.ts:9
  • type LinkClickEvent = {
        link: GraphLink;
        nativeEvent: MouseEvent;
    }
    +
  • Defined in packages/core/src/types.ts:382
  • @@ -34,12 +34,12 @@
    link: GraphLink
    +
  • Defined in packages/core/src/types.ts:383
  • nativeEvent: MouseEvent
    +
  • Defined in packages/core/src/types.ts:384
  • type LinkFlowOptions = {
        enabled?: boolean;
        maxParticles?: number;
        particleSize?: number;
        particleSpeed?: number;
    }
    +
  • Defined in packages/core/src/types.ts:200
  • @@ -39,12 +39,12 @@
    +
  • Defined in packages/core/src/types.ts:202
  • maxParticles?: number
    @@ -52,12 +52,12 @@
    +
  • Defined in packages/core/src/types.ts:205
  • particleSize?: number
    @@ -65,12 +65,12 @@
    +
  • Defined in packages/core/src/types.ts:208
  • particleSpeed?: number
    @@ -78,12 +78,12 @@
    +
  • Defined in packages/core/src/types.ts:211
  • type LinkHoverEvent = {
        link: GraphLink | null;
        nativeEvent: PointerEvent;
    }
    +
  • Defined in packages/core/src/types.ts:412
  • @@ -34,12 +34,12 @@
    link: GraphLink | null
    +
  • Defined in packages/core/src/types.ts:413
  • nativeEvent: PointerEvent
    +
  • Defined in packages/core/src/types.ts:414
  • type NodeClickEvent = {
        nativeEvent: MouseEvent;
        node: GraphNode;
    }
    +
  • Defined in packages/core/src/types.ts:374
  • @@ -34,12 +34,12 @@
    nativeEvent: MouseEvent
    +
  • Defined in packages/core/src/types.ts:376
  • node: GraphNode
    +
  • Defined in packages/core/src/types.ts:375
  • type NodeHoverEvent = {
        nativeEvent: PointerEvent;
        node: GraphNode | null;
    }
    +
  • Defined in packages/core/src/types.ts:404
  • @@ -34,12 +34,12 @@
    nativeEvent: PointerEvent
    +
  • Defined in packages/core/src/types.ts:406
  • node: GraphNode | null
    +
  • Defined in packages/core/src/types.ts:405
  • type OrbitGraphCameraOptions = {
        boostMultiplier?: number;
        keyboardNavigation?: boolean;
        maxDistance?: number;
        minDistance?: number;
        movementSpeed?: number;
    }
    +
  • Defined in packages/core/src/types.ts:550
  • @@ -42,12 +42,12 @@
    -
    2.5
    +
    2.5
     
    +
  • Defined in packages/core/src/types.ts:558
  • keyboardNavigation?: boolean
    @@ -55,12 +55,12 @@
    +
  • Defined in packages/core/src/types.ts:552
  • maxDistance?: number
    @@ -68,12 +68,12 @@
    +
  • Defined in packages/core/src/types.ts:564
  • minDistance?: number
    @@ -81,12 +81,12 @@
    +
  • Defined in packages/core/src/types.ts:561
  • movementSpeed?: number
    @@ -94,12 +94,12 @@
    +
  • Defined in packages/core/src/types.ts:555
  • @@ -55,28 +59,28 @@
    +
  • Defined in packages/core/src/types.ts:356
  • +
    + + +

    Configuration for the force simulation runtime.

    +
    type OrbitGraphViewState = {
        exploration: GraphExplorerState;
        filters: GraphFilterState;
        layout: GraphLayout;
        layoutOptions: GraphLayoutOptions;
        version: 1;
    }
    +
  • Defined in packages/core/src/types.ts:486
  • @@ -36,35 +36,35 @@
    +
  • Defined in packages/core/src/types.ts:491
  • Current search, type, and relationship-weight filters.

    +
  • Defined in packages/core/src/types.ts:494
  • layout: GraphLayout

    Visual arrangement of the active graph nodes.

    +
  • Defined in packages/core/src/types.ts:497
  • layoutOptions: GraphLayoutOptions

    Configuration associated with the active layout.

    +
  • Defined in packages/core/src/types.ts:500
  • version: 1

    Schema version used to safely evolve saved view states.

    +
  • Defined in packages/core/src/types.ts:488
  • type VisibleGraphData = {
        links: GraphLink[];
        nodes: GraphNode[];
    }
    +
  • Defined in packages/core/src/types.ts:420
  • @@ -34,12 +34,12 @@
    links: GraphLink[]
    +
  • Defined in packages/core/src/types.ts:422
  • nodes: GraphNode[]
    +
  • Defined in packages/core/src/types.ts:421
  • -
    type OrbitGraphHandle = {
        collapseNode(nodeId: string): void;
        downloadJSON(
            options?: GraphJSONExportOptions & { fileName?: string },
        ): void;
        downloadPNG(fileName?: string): Promise<void>;
        expandNode(nodeId: string, options?: GraphExpansionOptions): void;
        exportJSON(options?: GraphJSONExportOptions): string;
        exportPNG(): Promise<Blob>;
        focusNode(nodeId: string): void;
        getLoadingState(): GraphLoadingState;
        resetCamera(): void;
        resetExploration(): void;
        setInitialView(view: GraphInitialView): void;
        showAll(): void;
    }
    @@ -34,7 +34,11 @@

    Parameters

  • nodeId: string
  • Returns void

    +
  • Defined in packages/react/src/OrbitGraph.tsx:50
    • @@ -72,7 +76,7 @@

      Parameters

    • Optionaloptions: GraphJSONExportOptions & { fileName?: string }

    Returns void

    +
  • Defined in packages/react/src/OrbitGraph.tsx:86
    • @@ -87,7 +91,7 @@

      Parameters

    • OptionalfileName: string

    Returns Promise<void>

    +
  • Defined in packages/react/src/OrbitGraph.tsx:80
    • @@ -103,7 +107,7 @@

      Parameters

    • Optionaloptions: GraphExpansionOptions

    Returns void

    +
  • Defined in packages/react/src/OrbitGraph.tsx:47
    • @@ -118,7 +122,7 @@

      Parameters

    • Optionaloptions: GraphJSONExportOptions

    Returns string

    +
  • Defined in packages/react/src/OrbitGraph.tsx:83
  • +
  • Defined in packages/react/src/OrbitGraph.tsx:77
    • @@ -144,7 +148,18 @@

      Parameters

    • nodeId: string

    Returns void

    +
  • Defined in packages/react/src/OrbitGraph.tsx:44
  • +
    + +
      +
    • + +
      +

      Provides graph metrics for the complete or visible data scope.

      +
      +

      Returns GraphAnalyticsController

    +
  • Defined in packages/react/src/OrbitGraph.tsx:91
  • +
    + +
      +
    • + +
      +

      Provides temporary visual styles without mutating source graph data.

      +
      +

      Returns GraphPresentationController

    +
    + +
      +
    • + +
      +

      Loads and merges one remote relationship neighborhood page.

      +
      +
      +

      Parameters

      +
        +
      • nodeId: string
      • +
      • Optionaloptions: GraphNeighborhoodLoadOptions
      +

      Returns Promise<GraphNeighborhoodResult | null>

    +
    + +
      +
    • + +
      +

      Loads one node through the configured remote data source.

      +
      +
      +

      Parameters

      +
        +
      • nodeId: string
      +

      Returns Promise<GraphNode | undefined>

    +
  • Defined in packages/react/src/OrbitGraph.tsx:41
  • +
  • Defined in packages/react/src/OrbitGraph.tsx:53
    • @@ -192,7 +249,7 @@

      Parameters

    • view: GraphInitialView

    Returns void

    +
  • Defined in packages/react/src/OrbitGraph.tsx:59
  • +
  • Defined in packages/react/src/OrbitGraph.tsx:56
  • -
    OrbitGraphProps: Omit<HTMLAttributes<HTMLDivElement>, "children"> & {
        data: GraphData;
        onKeyboardFocusChange?: (node: GraphNode | null) => void;
        onLinkClick?: OrbitGraphOptions["onLinkClick"];
        onLinkHover?: OrbitGraphOptions["onLinkHover"];
        onLoadingChange?: (state: GraphLoadingState) => void;
        onNodeClick?: OrbitGraphOptions["onNodeClick"];
        onNodeHover?: OrbitGraphOptions["onNodeHover"];
        onSelectionChange?: (selection: GraphSelection) => void;
        onVisibleDataChange?: (data: VisibleGraphData) => void;
        options?: Omit<
            OrbitGraphOptions,
            | "onSelectionChange"
            | "onNodeClick"
            | "onLinkClick"
            | "onNodeHover"
            | "onLinkHover"
            | "onVisibleDataChange"
            | "onLoadingChange"
            | "onKeyboardFocusChange",
        >;
        style?: CSSProperties;
    }
    +
    OrbitGraphProps: Omit<HTMLAttributes<HTMLDivElement>, "children"> & {
        data: GraphData;
        onDiagnostic?: (diagnostic: GraphDiagnostic) => void;
        onKeyboardFocusChange?: (node: GraphNode | null) => void;
        onLinkClick?: OrbitGraphOptions["onLinkClick"];
        onLinkHover?: OrbitGraphOptions["onLinkHover"];
        onLoadingChange?: (state: GraphLoadingState) => void;
        onNodeClick?: OrbitGraphOptions["onNodeClick"];
        onNodeHover?: OrbitGraphOptions["onNodeHover"];
        onSelectionChange?: (selection: GraphSelection) => void;
        onVisibleDataChange?: (data: VisibleGraphData) => void;
        options?: Omit<
            OrbitGraphOptions,
            | "onSelectionChange"
            | "onVisibleDataChange"
            | "onLoadingChange"
            | "onDiagnostic"
            | "onKeyboardFocusChange"
            | "onNodeClick"
            | "onLinkClick"
            | "onNodeHover"
            | "onLinkHover",
        >;
        style?: CSSProperties;
    }

    Type Declaration

      @@ -20,6 +20,8 @@
      data

      Complete source data. Replacing it resets exploration to initialView.

  • +
    OptionalonDiagnostic?: (diagnostic: GraphDiagnostic) => void
  • +
  • OptionalonKeyboardFocusChange?: (node: GraphNode | null) => void
  • OptionalonLinkClick?: OrbitGraphOptions["onLinkClick"]
  • @@ -36,13 +38,13 @@
    OptionalonSelec
  • OptionalonVisibleDataChange?: (data: VisibleGraphData) => void
  • -
    Optionaloptions?: Omit<
        OrbitGraphOptions,
        | "onSelectionChange"
        | "onNodeClick"
        | "onLinkClick"
        | "onNodeHover"
        | "onLinkHover"
        | "onVisibleDataChange"
        | "onLoadingChange"
        | "onKeyboardFocusChange",
    >
    +
    Optionaloptions?: Omit<
        OrbitGraphOptions,
        | "onSelectionChange"
        | "onVisibleDataChange"
        | "onLoadingChange"
        | "onDiagnostic"
        | "onKeyboardFocusChange"
        | "onNodeClick"
        | "onLinkClick"
        | "onNodeHover"
        | "onLinkHover",
    >

    Renderer, camera, exploration, mobile, and link-flow configuration.

  • Optionalstyle?: CSSProperties
  • +
  • Defined in packages/react/src/OrbitGraph.tsx:94
  • +
  • Defined in packages/react/src/OrbitGraph.tsx:133