@sandeepsj0000/react-graph-visualizer 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,646 @@
1
+ # react-graph-visualizer
2
+
3
+ Interactive React component **and** headless engine for graph visualization, node selection, path finding, and data export. Supports directed and undirected graphs.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [Install](#install)
10
+ - [Quick Start — Visual Mode](#quick-start--visual-mode)
11
+ - [Quick Start — Headless Mode](#quick-start--headless-mode)
12
+ - [Data Format](#data-format)
13
+ - [Visual Component API](#visual-component-api)
14
+ - [Props](#props)
15
+ - [Interaction Guide](#interaction-guide)
16
+ - [Selection Modes](#selection-modes)
17
+ - [Headless APIs](#headless-apis)
18
+ - [GraphEngine (class)](#graphengine-class)
19
+ - [useGraphEngine (React hook)](#usegraphengine-react-hook)
20
+ - [Export & Serialization](#export--serialization)
21
+ - [Type Reference](#type-reference)
22
+ - [Examples](#examples)
23
+ - [Running the Demo](#running-the-demo)
24
+
25
+ ---
26
+
27
+ ## Install
28
+
29
+ ```bash
30
+ npm install react-graph-visualizer
31
+ ```
32
+
33
+ Peer dependencies: `react >= 17`, `react-dom >= 17`.
34
+
35
+ ---
36
+
37
+ ## Quick Start — Visual Mode
38
+
39
+ Render an interactive force-directed graph with built-in selection UI, sidebar, and export buttons.
40
+
41
+ ```tsx
42
+ import { GraphVisualizer } from "react-graph-visualizer";
43
+
44
+ const data = {
45
+ directed: false,
46
+ nodes: [
47
+ { id: "a", label: "Alice" },
48
+ { id: "b", label: "Bob" },
49
+ { id: "c", label: "Charlie" },
50
+ { id: "d", label: "Diana" },
51
+ ],
52
+ edges: [
53
+ { source: "a", target: "b" },
54
+ { source: "b", target: "c" },
55
+ { source: "c", target: "d" },
56
+ { source: "a", target: "d" },
57
+ ],
58
+ };
59
+
60
+ function App() {
61
+ return (
62
+ <GraphVisualizer
63
+ data={data}
64
+ width={900}
65
+ height={600}
66
+ onSelectionChange={(selected, connected) => {
67
+ console.log("Selected:", selected, "Connected:", connected);
68
+ }}
69
+ />
70
+ );
71
+ }
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Quick Start — Headless Mode
77
+
78
+ Use `GraphEngine` directly when you don't need any UI — works in Node.js, tests, scripts, or server-side code.
79
+
80
+ ```ts
81
+ import { GraphEngine } from "react-graph-visualizer";
82
+
83
+ const engine = new GraphEngine({
84
+ directed: true,
85
+ nodes: [
86
+ { id: "api", label: "API Gateway" },
87
+ { id: "auth", label: "Auth Service" },
88
+ { id: "db", label: "Database" },
89
+ { id: "cache", label: "Cache" },
90
+ ],
91
+ edges: [
92
+ { source: "api", target: "auth" },
93
+ { source: "auth", target: "db" },
94
+ { source: "auth", target: "cache" },
95
+ { source: "api", target: "db" },
96
+ ],
97
+ });
98
+
99
+ // Connected nodes
100
+ engine.getConnectedNodes("auth");
101
+ // => ["db", "cache", "api"]
102
+
103
+ // Inverted selection — everything NOT connected to "auth"
104
+ engine.getInvertedSelection("auth");
105
+ // => [] (all nodes happen to be connected in this small graph)
106
+
107
+ // All paths from api to db
108
+ engine.findAllPaths("api", "db");
109
+ // => [
110
+ // { path: ["api", "auth", "db"], labels: ["API Gateway", "Auth Service", "Database"] },
111
+ // { path: ["api", "db"], labels: ["API Gateway", "Database"] }
112
+ // ]
113
+
114
+ // Shortest path
115
+ engine.findShortestPath("api", "db");
116
+ // => { path: ["api", "db"], labels: ["API Gateway", "Database"] }
117
+
118
+ // Graph stats
119
+ engine.getStats();
120
+ // => { nodeCount: 4, edgeCount: 4, directed: true, density: 0.3333, ... }
121
+
122
+ // Serialize results to CSV string (no DOM needed)
123
+ const csv = GraphEngine.toCSV(engine.getConnectedNodesWithLabels("auth"));
124
+ ```
125
+
126
+ Or use the **React hook** `useGraphEngine` for headless usage inside React apps (manages selection state for you):
127
+
128
+ ```tsx
129
+ import { useGraphEngine } from "react-graph-visualizer";
130
+
131
+ function MyCustomUI({ data }) {
132
+ const graph = useGraphEngine(data);
133
+
134
+ // Select a node programmatically
135
+ graph.selectNode("auth");
136
+
137
+ // Reactive results
138
+ console.log(graph.connectedNodes); // [{ id: "db", label: "Database" }, ...]
139
+ console.log(graph.invertedNodes); // nodes NOT connected
140
+ console.log(graph.paths); // auto-computed when 2+ selected
141
+
142
+ // Serialize current results
143
+ const csv = graph.toCSV();
144
+ const json = graph.pathsToJSON();
145
+
146
+ return <div>{/* build your own UI */}</div>;
147
+ }
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Data Format
153
+
154
+ ### `GraphData`
155
+
156
+ ```ts
157
+ interface GraphData {
158
+ nodes: GraphNode[];
159
+ edges: GraphEdge[];
160
+ directed?: boolean; // default: false
161
+ }
162
+ ```
163
+
164
+ ### `GraphNode`
165
+
166
+ ```ts
167
+ interface GraphNode {
168
+ id: string; // unique identifier
169
+ label?: string; // display name (defaults to id)
170
+ color?: string; // per-node color override
171
+ size?: number; // per-node radius override
172
+ metadata?: Record<string, unknown>; // arbitrary data attached to node
173
+ }
174
+ ```
175
+
176
+ ### `GraphEdge`
177
+
178
+ ```ts
179
+ interface GraphEdge {
180
+ source: string; // source node id
181
+ target: string; // target node id
182
+ label?: string; // edge label
183
+ weight?: number; // edge weight
184
+ metadata?: Record<string, unknown>; // arbitrary data attached to edge
185
+ }
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Visual Component API
191
+
192
+ ### Props
193
+
194
+ | Prop | Type | Default | Description |
195
+ |------|------|---------|-------------|
196
+ | `data` | `GraphData` | **required** | Graph nodes and edges |
197
+ | `width` | `number` | `900` | SVG canvas width in pixels |
198
+ | `height` | `number` | `600` | SVG canvas height in pixels |
199
+ | `onSelectionChange` | `(selectedIds: string[], connectedIds: string[]) => void` | — | Fires when selection changes |
200
+ | `nodeColor` | `string` | `#4f46e5` | Default node fill color |
201
+ | `highlightColor` | `string` | `#f59e0b` | Color for selected / connected nodes |
202
+ | `dimColor` | `string` | `#d1d5db` | Color for non-relevant nodes |
203
+ | `invertColor` | `string` | `#ef4444` | Color for inverted selection nodes |
204
+ | `nodeRadius` | `number` | `20` | Default circle radius |
205
+ | `showEdgeLabels` | `boolean` | `false` | Render edge labels on the graph |
206
+ | `showArrows` | `boolean` | `true` | Show arrowheads on directed edges |
207
+ | `className` | `string` | — | CSS class applied to the outer container |
208
+
209
+ ### Interaction Guide
210
+
211
+ | Action | Effect |
212
+ |--------|--------|
213
+ | **Click** a node | Select it (replaces any previous selection) |
214
+ | **Ctrl/Cmd + Click** a node | Toggle it into/out of a multi-selection |
215
+ | **Click** the background | Clear all selections |
216
+ | **Drag** a node | Reposition it in the force layout |
217
+ | **Scroll wheel** | Zoom in/out |
218
+ | **Click + drag** background | Pan the viewport |
219
+
220
+ ### Selection Modes
221
+
222
+ The sidebar provides three toggle modes:
223
+
224
+ | Mode | Behavior |
225
+ |------|----------|
226
+ | **Connected** | Highlights direct neighbors of the selected node. Lists them in the sidebar. |
227
+ | **Inverted** | Highlights every node that is NOT a direct neighbor (selection inverter). |
228
+ | **Paths** | When 2+ nodes are selected, finds and lists all paths connecting them. Highlights path edges. |
229
+
230
+ The sidebar includes **Export** buttons to download results as CSV/JSON and the graph image as SVG/PNG.
231
+
232
+ ---
233
+
234
+ ## Headless APIs
235
+
236
+ ### `GraphEngine` (class)
237
+
238
+ Import: `import { GraphEngine } from "react-graph-visualizer"`
239
+
240
+ No React or DOM dependency. Works in Node.js, tests, server-side, scripts — anywhere.
241
+
242
+ #### Constructor
243
+
244
+ ```ts
245
+ const engine = new GraphEngine(data: GraphData);
246
+ ```
247
+
248
+ #### Node Accessors
249
+
250
+ | Method | Returns | Description |
251
+ |--------|---------|-------------|
252
+ | `getNode(id)` | `GraphNode \| undefined` | Get full node object |
253
+ | `getLabel(id)` | `string` | Display label |
254
+ | `getNodeIds()` | `string[]` | All node ids |
255
+ | `getNodes()` | `GraphNode[]` | All node objects |
256
+ | `getEdges()` | `GraphEdge[]` | All edge objects |
257
+ | `hasNode(id)` | `boolean` | Check existence |
258
+ | `hasEdge(source, target)` | `boolean` | Check if edge exists |
259
+ | `getNodeInfo(id)` | `NodeInfo \| null` | Rich info: label, degrees, all neighbors |
260
+
261
+ #### Neighbor Queries
262
+
263
+ | Method | Returns | Description |
264
+ |--------|---------|-------------|
265
+ | `getConnectedNodes(id)` | `string[]` | All direct neighbors (in + out) |
266
+ | `getConnectedNodesWithLabels(id)` | `{id, label}[]` | Same, with labels |
267
+ | `getOutgoingNeighbors(id)` | `string[]` | Only outgoing (directed) |
268
+ | `getIncomingNeighbors(id)` | `string[]` | Only incoming (directed) |
269
+
270
+ #### Degree
271
+
272
+ | Method | Returns | Description |
273
+ |--------|---------|-------------|
274
+ | `getDegree(id)` | `number` | Total unique neighbors |
275
+ | `getOutDegree(id)` | `number` | Outgoing edge count |
276
+ | `getInDegree(id)` | `number` | Incoming edge count |
277
+
278
+ #### Selection Inverter
279
+
280
+ | Method | Returns | Description |
281
+ |--------|---------|-------------|
282
+ | `getInvertedSelection(id)` | `string[]` | Nodes NOT connected to `id` |
283
+ | `getInvertedSelectionWithLabels(id)` | `{id, label}[]` | Same, with labels |
284
+
285
+ #### Path Finding
286
+
287
+ | Method | Returns | Description |
288
+ |--------|---------|-------------|
289
+ | `findAllPaths(from, to, maxDepth?)` | `PathResult[]` | All paths via DFS (default depth limit: 10) |
290
+ | `findShortestPath(from, to)` | `PathResult \| null` | Shortest path via BFS |
291
+ | `findAllPathsBetweenMultiple(ids)` | `PathResult[]` | All pairwise paths between multiple nodes |
292
+ | `areConnected(from, to)` | `boolean` | Reachability check |
293
+
294
+ #### Edge Queries
295
+
296
+ | Method | Returns | Description |
297
+ |--------|---------|-------------|
298
+ | `getEdgesOfNode(id)` | `GraphEdge[]` | All edges touching a node |
299
+ | `getEdgesForNodes(idSet)` | `GraphEdge[]` | Edges where both endpoints are in the set |
300
+ | `getEdgesOnPaths(paths)` | `Set<string>` | Edge keys (`"a->b"`) on given paths |
301
+
302
+ #### Subgraph Extraction
303
+
304
+ | Method | Returns | Description |
305
+ |--------|---------|-------------|
306
+ | `getSubgraph(ids)` | `SubgraphResult` | Subgraph of specified nodes + their internal edges |
307
+ | `getNeighborhoodSubgraph(id)` | `SubgraphResult` | Node + all neighbors + connecting edges |
308
+
309
+ #### Graph Analytics
310
+
311
+ | Method | Returns | Description |
312
+ |--------|---------|-------------|
313
+ | `getStats()` | `GraphStats` | Node/edge count, density, avg/max/min degree, components, isolated nodes |
314
+ | `getNodesByDegree()` | `{id, label, degree}[]` | All nodes sorted by degree (descending) |
315
+
316
+ #### Serialization (string output, no DOM)
317
+
318
+ | Method | Returns | Description |
319
+ |--------|---------|-------------|
320
+ | `GraphEngine.toCSV(nodes)` | `string` | CSV of `{id, label}[]` |
321
+ | `GraphEngine.toJSON(nodes)` | `string` | JSON of `{id, label}[]` |
322
+ | `GraphEngine.pathsToCSV(paths)` | `string` | CSV of `PathResult[]` |
323
+ | `GraphEngine.pathsToJSON(paths)` | `string` | JSON of `PathResult[]` |
324
+ | `engine.toGraphJSON()` | `string` | Full graph data as JSON |
325
+
326
+ #### Meta
327
+
328
+ | Method | Returns | Description |
329
+ |--------|---------|-------------|
330
+ | `isDirected()` | `boolean` | Whether graph is directed |
331
+ | `nodeCount()` | `number` | Number of nodes |
332
+ | `edgeCount()` | `number` | Number of edges |
333
+
334
+ ---
335
+
336
+ ### `useGraphEngine` (React hook)
337
+
338
+ Import: `import { useGraphEngine } from "react-graph-visualizer"`
339
+
340
+ A React hook that wraps `GraphEngine` with reactive selection state. Use it to build your own custom UI or to drive headless logic inside a React app.
341
+
342
+ ```ts
343
+ const graph = useGraphEngine(data: GraphData): UseGraphEngineReturn;
344
+ ```
345
+
346
+ #### Selection State
347
+
348
+ | Property / Method | Type | Description |
349
+ |-------------------|------|-------------|
350
+ | `selectedNodes` | `string[]` | Currently selected node ids |
351
+ | `selectNode(id)` | `void` | Select a single node (clears previous) |
352
+ | `toggleNode(id)` | `void` | Add/remove node from multi-selection |
353
+ | `selectNodes(ids)` | `void` | Select multiple nodes at once |
354
+ | `clearSelection()` | `void` | Deselect everything |
355
+
356
+ #### Reactive Results (auto-update when selection changes)
357
+
358
+ | Property | Type | Description |
359
+ |----------|------|-------------|
360
+ | `connectedNodes` | `{id, label}[]` | Neighbors of all selected nodes |
361
+ | `invertedNodes` | `{id, label}[]` | Non-neighbors (when 1 node selected) |
362
+ | `paths` | `PathResult[]` | All paths between selected nodes (when 2+ selected) |
363
+
364
+ #### Direct Query Methods
365
+
366
+ Same as `GraphEngine` methods — `getNodeInfo`, `findAllPaths`, `findShortestPath`, `findAllPathsBetweenMultiple`, `areConnected`, `getInvertedSelection`, `getConnectedNodes`, `getSubgraph`, `getNeighborhoodSubgraph`, `getNodesByDegree`, `getStats`.
367
+
368
+ #### Serialization
369
+
370
+ | Method | Description |
371
+ |--------|-------------|
372
+ | `toCSV(nodes?)` | CSV string of provided nodes or current `connectedNodes` |
373
+ | `toJSON(nodes?)` | JSON string of provided nodes or current `connectedNodes` |
374
+ | `pathsToCSV(paths?)` | CSV string of provided paths or current `paths` |
375
+ | `pathsToJSON(paths?)` | JSON string of provided paths or current `paths` |
376
+ | `toGraphJSON()` | Full graph data as JSON string |
377
+
378
+ ---
379
+
380
+ ## Export & Serialization
381
+
382
+ ### Headless (string output — no DOM required)
383
+
384
+ Use `GraphEngine` static methods to get raw strings you can write to a file, send over an API, or process further:
385
+
386
+ ```ts
387
+ import { GraphEngine } from "react-graph-visualizer";
388
+
389
+ const engine = new GraphEngine(data);
390
+
391
+ // Get CSV string of connected nodes
392
+ const csv = GraphEngine.toCSV(engine.getConnectedNodesWithLabels("a"));
393
+ // => "ID,Label\n\"a\",\"Alice\"\n..."
394
+
395
+ // Get JSON string of all paths
396
+ const json = GraphEngine.pathsToJSON(engine.findAllPaths("a", "d"));
397
+
398
+ // Full graph as JSON
399
+ const graphJson = engine.toGraphJSON();
400
+ ```
401
+
402
+ ### Browser (triggers file download — requires DOM)
403
+
404
+ ```ts
405
+ import {
406
+ exportNodeListAsCSV,
407
+ exportNodeListAsJSON,
408
+ exportPathsAsCSV,
409
+ exportPathsAsJSON,
410
+ exportSVG,
411
+ exportPNG,
412
+ } from "react-graph-visualizer";
413
+
414
+ // Download a node list
415
+ exportNodeListAsCSV([{ id: "a", label: "Alice" }], "my-nodes.csv");
416
+
417
+ // Download paths
418
+ exportPathsAsJSON(paths, "routes.json");
419
+
420
+ // Download graph image (pass the SVG DOM element)
421
+ exportSVG(svgElement, "graph.svg");
422
+ exportPNG(svgElement, "graph.png", 2); // 2x scale
423
+ ```
424
+
425
+ ---
426
+
427
+ ## Type Reference
428
+
429
+ ### `PathResult`
430
+
431
+ ```ts
432
+ interface PathResult {
433
+ path: string[]; // ordered node ids
434
+ labels: string[]; // ordered node labels
435
+ }
436
+ ```
437
+
438
+ ### `NodeInfo`
439
+
440
+ ```ts
441
+ interface NodeInfo {
442
+ id: string;
443
+ label: string;
444
+ metadata?: Record<string, unknown>;
445
+ outDegree: number;
446
+ inDegree: number;
447
+ degree: number;
448
+ outgoingNeighbors: { id: string; label: string }[];
449
+ incomingNeighbors: { id: string; label: string }[];
450
+ allNeighbors: { id: string; label: string }[];
451
+ }
452
+ ```
453
+
454
+ ### `GraphStats`
455
+
456
+ ```ts
457
+ interface GraphStats {
458
+ nodeCount: number;
459
+ edgeCount: number;
460
+ directed: boolean;
461
+ density: number; // 0-1
462
+ avgDegree: number;
463
+ maxDegree: number;
464
+ minDegree: number;
465
+ connectedComponents: number; // weakly connected components
466
+ isolatedNodes: string[]; // nodes with 0 connections
467
+ }
468
+ ```
469
+
470
+ ### `SubgraphResult`
471
+
472
+ ```ts
473
+ interface SubgraphResult {
474
+ nodes: GraphNode[];
475
+ edges: GraphEdge[];
476
+ directed: boolean;
477
+ }
478
+ ```
479
+
480
+ ---
481
+
482
+ ## Examples
483
+
484
+ ### Headless: Find all paths and export to CSV (Node.js / script)
485
+
486
+ ```ts
487
+ import { GraphEngine } from "react-graph-visualizer";
488
+ import { writeFileSync } from "fs";
489
+
490
+ const engine = new GraphEngine({
491
+ directed: false,
492
+ nodes: [
493
+ { id: "1", label: "Start" },
494
+ { id: "2", label: "Mid A" },
495
+ { id: "3", label: "Mid B" },
496
+ { id: "4", label: "End" },
497
+ ],
498
+ edges: [
499
+ { source: "1", target: "2" },
500
+ { source: "1", target: "3" },
501
+ { source: "2", target: "4" },
502
+ { source: "3", target: "4" },
503
+ { source: "2", target: "3" },
504
+ ],
505
+ });
506
+
507
+ const paths = engine.findAllPaths("1", "4");
508
+ console.log(`Found ${paths.length} paths`);
509
+
510
+ // Write to file
511
+ writeFileSync("paths.csv", GraphEngine.pathsToCSV(paths));
512
+ writeFileSync("paths.json", GraphEngine.pathsToJSON(paths));
513
+ ```
514
+
515
+ ### Headless: Graph analytics
516
+
517
+ ```ts
518
+ const engine = new GraphEngine(data);
519
+
520
+ // Who are the most connected nodes?
521
+ const ranked = engine.getNodesByDegree();
522
+ console.log("Top nodes:", ranked.slice(0, 5));
523
+
524
+ // Overall graph health
525
+ const stats = engine.getStats();
526
+ console.log(`Density: ${stats.density}, Components: ${stats.connectedComponents}`);
527
+ console.log(`Isolated nodes: ${stats.isolatedNodes.join(", ") || "none"}`);
528
+
529
+ // Can user A reach user D?
530
+ console.log(engine.areConnected("a", "d")); // true/false
531
+
532
+ // What's the shortest route?
533
+ const shortest = engine.findShortestPath("a", "d");
534
+ console.log(shortest?.labels.join(" → "));
535
+ ```
536
+
537
+ ### Headless: Selection inverter
538
+
539
+ ```ts
540
+ const engine = new GraphEngine(data);
541
+
542
+ // "Show me everything NOT connected to node X"
543
+ const isolated = engine.getInvertedSelectionWithLabels("api");
544
+ console.log("Disconnected from API:", isolated);
545
+ const csv = GraphEngine.toCSV(isolated);
546
+ ```
547
+
548
+ ### React hook: Custom UI with headless engine
549
+
550
+ ```tsx
551
+ import { useGraphEngine } from "react-graph-visualizer";
552
+
553
+ function DependencyExplorer({ data }) {
554
+ const graph = useGraphEngine(data);
555
+
556
+ return (
557
+ <div>
558
+ <h3>Services</h3>
559
+ <ul>
560
+ {graph.engine.getNodes().map((node) => (
561
+ <li
562
+ key={node.id}
563
+ onClick={() => graph.selectNode(node.id)}
564
+ style={{
565
+ fontWeight: graph.selectedNodes.includes(node.id)
566
+ ? "bold"
567
+ : "normal",
568
+ }}
569
+ >
570
+ {node.label ?? node.id} (degree: {graph.engine.getDegree(node.id)})
571
+ </li>
572
+ ))}
573
+ </ul>
574
+
575
+ {graph.connectedNodes.length > 0 && (
576
+ <div>
577
+ <h4>Connected to selection:</h4>
578
+ <ul>
579
+ {graph.connectedNodes.map((n) => (
580
+ <li key={n.id}>{n.label}</li>
581
+ ))}
582
+ </ul>
583
+ <button onClick={() => console.log(graph.toCSV())}>
584
+ Copy as CSV
585
+ </button>
586
+ </div>
587
+ )}
588
+
589
+ {graph.paths.length > 0 && (
590
+ <div>
591
+ <h4>Paths ({graph.paths.length}):</h4>
592
+ {graph.paths.map((p, i) => (
593
+ <div key={i}>{p.labels.join(" → ")}</div>
594
+ ))}
595
+ <button onClick={() => console.log(graph.pathsToCSV())}>
596
+ Copy paths as CSV
597
+ </button>
598
+ </div>
599
+ )}
600
+ </div>
601
+ );
602
+ }
603
+ ```
604
+
605
+ ### Visual + headless combined
606
+
607
+ ```tsx
608
+ import { GraphVisualizer, useGraphEngine } from "react-graph-visualizer";
609
+
610
+ function App() {
611
+ const graph = useGraphEngine(data);
612
+
613
+ return (
614
+ <div>
615
+ {/* Visual graph */}
616
+ <GraphVisualizer
617
+ data={data}
618
+ onSelectionChange={(sel) => graph.selectNodes(sel)}
619
+ />
620
+
621
+ {/* Programmatic access alongside the visual */}
622
+ <pre>{graph.toGraphJSON()}</pre>
623
+ <pre>Stats: {JSON.stringify(graph.getStats(), null, 2)}</pre>
624
+ </div>
625
+ );
626
+ }
627
+ ```
628
+
629
+ ---
630
+
631
+ ## Running the Demo
632
+
633
+ ```bash
634
+ git clone <repo>
635
+ cd visualize-graph
636
+ npm install
637
+ npm run demo
638
+ ```
639
+
640
+ Opens at `http://localhost:5173` with two sample graphs (social network + microservices).
641
+
642
+ ---
643
+
644
+ ## License
645
+
646
+ MIT
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import { GraphVisualizerProps } from "./types";
3
+ export declare const GraphVisualizer: React.FC<GraphVisualizerProps>;
@@ -0,0 +1,14 @@
1
+ import { PathResult } from "./types";
2
+ export declare function downloadFile(content: string, filename: string, mime: string): void;
3
+ export declare function exportNodeListAsCSV(nodes: {
4
+ id: string;
5
+ label: string;
6
+ }[], filename?: string): void;
7
+ export declare function exportNodeListAsJSON(nodes: {
8
+ id: string;
9
+ label: string;
10
+ }[], filename?: string): void;
11
+ export declare function exportPathsAsCSV(paths: PathResult[], filename?: string): void;
12
+ export declare function exportPathsAsJSON(paths: PathResult[], filename?: string): void;
13
+ export declare function exportSVG(svgElement: SVGSVGElement, filename?: string): void;
14
+ export declare function exportPNG(svgElement: SVGSVGElement, filename?: string, scale?: number): void;