Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,18 @@ All notable changes to OrbitGraph are documented in this file.

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.3.0] - Unreleased
## [1.4.0]

### Added

- Graph snapshot comparison, weighted shortest paths, and edge-disjoint route alternatives.
- Operation-based editing API, custom streaming adapter contract, and bounded undo/redo history.
- Declarative node style rules based on type, degree, PageRank, and metadata predicates.
- Multi-node selection API and v1.4 core contracts for cluster summary nodes, themes, streams, and plugins.
- Canvas 2D renderer, MapLibre GeoJSON layer, runtime plugin registry, and SVG/PDF export APIs.
- Aggregate cluster-data generator for rendering collapsed communities as summary nodes and consolidated links.

## [1.3.0]

### Added

Expand Down
13 changes: 13 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ Hidden nodes are kept out of WebGL and the active physics simulation until explo
- Bookmarks and serializable annotations for application-managed collaboration.
- CSV, Cytoscape, JSON-LD, and Neo4j import helpers, plus timeline, bipartite, geographic, DAG, and Sankey layouts.
- Application-owned tooltip/detail renderers, semantic node list, adaptive label detail, and optional FPS telemetry.
- Canvas 2D fallback, MapLibre geographic layer, runtime plugin registry, plus SVG and PDF exports.
- Vanilla JavaScript and React support.

## Packages
Expand Down Expand Up @@ -133,6 +134,18 @@ graph.saveBookmark("launch-review", "Launch review");

Use `accessibility: { semanticView: true }` to render a synchronized semantic node list. `performance: { telemetry: true, onPerformanceSample }` reports FPS and visible graph counts; labels automatically reduce to 20 items above 1,000 visible nodes unless `levelOfDetail: false` is set.

## Editing, routes, and graph changes

```ts
graph.applyOperations([{ type: "update-node", nodeId: "api", patch: { data: { status: "production" } } }]);
graph.undo();
graph.redo();

graph.setStyleRules([{ id: "important", when: { minPageRank: 0.1 }, style: { color: "#facc15", scale: 1.5 } }]);
const route = graph.findWeightedPath("team", "api");
const comparison = graph.compare(previousSnapshot);
```

## Remote data

```ts
Expand Down
11 changes: 11 additions & 0 deletions docs/api/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ This reference covers the public APIs provided by the `@orbitgraph/core`, `@orbi
- [Exploration](#exploration)
- [Search and filters](#search-and-filters)
- [Clustering, collaboration, and UI hooks](#clustering-collaboration-and-ui-hooks)
- [Editing, routes, streaming, and comparison](#editing-routes-streaming-and-comparison)
- [Importing data](#importing-data)
- [Remote and GraphQL data](#remote-and-graphql-data)
- [Layouts and physics](#layouts-and-physics)
Expand Down Expand Up @@ -238,6 +239,16 @@ graph.saveBookmark("review", "Review graph");

`@orbitgraph/core` exports `importCSVNodes`, `importCSVLinks`, `importJSON`, `importCytoscape`, `importJSONLD`, and `importNeo4j`. The CSV helpers recognize standard graph fields and place other columns in `data`; the Neo4j helper accepts a plain-object projection of driver records.

## Editing, routes, streaming, and comparison

Use `applyOperations()` with `GraphOperation` records to add, remove, or update nodes and links. `undo()` and `redo()` restore bounded data snapshots. `stream` accepts a host-owned adapter with `connect(onMessage, onError)` and applies incoming operation batches without a full page reload.

`findWeightedPath(sourceId, targetId)` uses link weights as inverse traversal cost; `findKShortestPaths(sourceId, targetId, count)` returns edge-disjoint alternatives. `compare(snapshot)` returns added, removed, and changed nodes and links. `setStyleRules()` applies declarative styles by type, metadata, degree, or PageRank. `selectNodes()` and `getSelectedNodeIds()` provide framework-neutral multi-selection state.

### Renderer extensions and exports

`CanvasGraphRenderer` is a real 2D canvas renderer for low-power embedding; supply a canvas and the active physics nodes/links. `MapLibreGraphLayer` writes nodes with longitude/latitude metadata to a MapLibre GeoJSON source. `GraphPluginRegistry` runs application-installed plugins and makes their data sources and style rules available at runtime. `exportSVG()` / `downloadSVG()` and `exportPDF()` / `downloadPDF()` capture the current rendered view for reports.

## Instance API

### Data
Expand Down
10 changes: 9 additions & 1 deletion examples/benchmark/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ function createGraph(): OrbitGraph {
if (nodeCountElement) nodeCountElement.textContent = String(nodes.length);
if (linkCountElement) linkCountElement.textContent = String(links.length);
},
performance: {
telemetry: true,
onPerformanceSample: ({ fps, visibleNodes, visibleLinks }) => {
if (fpsElement) fpsElement.textContent = String(fps);
if (summaryElement) summaryElement.title = `${fps} FPS · ${visibleNodes} nodes · ${visibleLinks} relationships`;
},
},
});
}

Expand Down Expand Up @@ -90,6 +97,7 @@ function loadBenchmark(regenerate = true): void {
if (regenerate) currentData = createData(currentSize);

graph.setData(currentData);
graph.setStyleRules([{ id: "hubs", when: { minDegree: 5 }, style: { glow: 0.7, scale: 1.25 } }]);
graph.resetCamera();
updateSizeButtons();

Expand Down Expand Up @@ -142,4 +150,4 @@ layoutInput?.addEventListener("change", () => {

graph = createGraph();
loadBenchmark(true);
requestAnimationFrame(measureFps);
requestAnimationFrame(measureFps);
Loading
Loading