@petrarca/sonnet-graph 0.3.0 → 0.4.1
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 +144 -0
- package/dist/index.d.ts +31 -7
- package/dist/index.js +610 -247
- package/dist/index.js.map +1 -1
- package/package.json +34 -5
package/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# @petrarca/sonnet-graph
|
|
2
|
+
|
|
3
|
+
Renderer-agnostic property graph visualization, exploration, and enrichment
|
|
4
|
+
for the Petrarca Sonnet component library.
|
|
5
|
+
|
|
6
|
+
## What's included
|
|
7
|
+
|
|
8
|
+
**GraphVisualizer** — Main visualization component. Renders a property graph
|
|
9
|
+
using the active renderer (Cytoscape or Reagraph). Supports node/edge
|
|
10
|
+
selection, focus mode, hide/show, and graph expansion.
|
|
11
|
+
|
|
12
|
+
**ActionPanel** — Side panel showing selected node/edge details and graph
|
|
13
|
+
exploration actions.
|
|
14
|
+
|
|
15
|
+
**GraphA11yList** — Accessible DOM mirror of the graph's selectable elements.
|
|
16
|
+
Cytoscape (canvas) and Reagraph (WebGL) draw nodes/edges outside the DOM, so they
|
|
17
|
+
are invisible to screen readers, keyboard users, and DOM automation; this renders
|
|
18
|
+
a virtualized list of node/edge `<button>`s that drive the same selection store
|
|
19
|
+
the canvas reads. `sr-only` by default (real apps); pass `visible` for an on-screen
|
|
20
|
+
outline panel.
|
|
21
|
+
|
|
22
|
+
**GraphRendererProvider** — Context provider that selects the active renderer
|
|
23
|
+
(`"cytoscape"` or `"reagraph"`).
|
|
24
|
+
|
|
25
|
+
**Store factories** — Create the Zustand stores the graph components need:
|
|
26
|
+
`createGraphDataStore`, `createGraphFilterStore`, `createGraphExplorationStore`,
|
|
27
|
+
`createSelectionStore`, `createGraphFocusStore`.
|
|
28
|
+
|
|
29
|
+
**Graph utilities** — `enrichNodes`, `enrichEdges`, `buildColorPalette` for
|
|
30
|
+
preparing raw graph data before passing it to stores.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pnpm add @petrarca/sonnet-graph
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Required peer dependencies
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pnpm add react@">=19" react-dom@">=19"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Renderer peer dependencies
|
|
47
|
+
|
|
48
|
+
Install only the renderers you use:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pnpm add cytoscape # Cytoscape.js renderer
|
|
52
|
+
pnpm add reagraph # Reagraph (3D/WebGL) renderer
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If you use `@petrarca/sonnet-playground` (which includes the graph demo page),
|
|
56
|
+
both `cytoscape` and `reagraph` are required even if your app only uses one renderer.
|
|
57
|
+
|
|
58
|
+
### Cytoscape layout plugins (optional)
|
|
59
|
+
|
|
60
|
+
Install the layout algorithms you need. All are optional — the graph works
|
|
61
|
+
without them but with fewer layout options:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pnpm add cytoscape-fcose # Force-directed, compound graph
|
|
65
|
+
pnpm add cytoscape-cola # Constraint-based
|
|
66
|
+
pnpm add cytoscape-dagre # DAG / hierarchical
|
|
67
|
+
pnpm add cytoscape-elk # Eclipse Layout Kernel
|
|
68
|
+
pnpm add cytoscape-cise # Circular layout
|
|
69
|
+
pnpm add cytoscape-klay # KLay hierarchical
|
|
70
|
+
pnpm add cytoscape-cxtmenu # Context menu extension
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Local development with SONNET_UI_LOCAL=1
|
|
74
|
+
|
|
75
|
+
When resolving `@petrarca/sonnet-graph` from the local dist (via Vite aliases),
|
|
76
|
+
the Cytoscape plugins must also be aliased to the consumer's `node_modules` —
|
|
77
|
+
Vite cannot find them relative to the dist file. Add to your `sonnet-aliases.ts`:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
const nm = path.resolve(baseDir, "node_modules");
|
|
81
|
+
// ...
|
|
82
|
+
"cytoscape-fcose": path.resolve(nm, "cytoscape-fcose"),
|
|
83
|
+
"cytoscape-cola": path.resolve(nm, "cytoscape-cola"),
|
|
84
|
+
"cytoscape-dagre": path.resolve(nm, "cytoscape-dagre"),
|
|
85
|
+
"cytoscape-elk": path.resolve(nm, "cytoscape-elk"),
|
|
86
|
+
"cytoscape-cise": path.resolve(nm, "cytoscape-cise"),
|
|
87
|
+
"cytoscape-klay": path.resolve(nm, "cytoscape-klay"),
|
|
88
|
+
"cytoscape-cxtmenu": path.resolve(nm, "cytoscape-cxtmenu"),
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
See `sonnet-ui-starter/sonnet-aliases.ts` for a complete reference implementation.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Basic usage
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import {
|
|
99
|
+
GraphVisualizer,
|
|
100
|
+
ActionPanel,
|
|
101
|
+
GraphRendererProvider,
|
|
102
|
+
GraphStoresContext,
|
|
103
|
+
createGraphDataStore,
|
|
104
|
+
createGraphFilterStore,
|
|
105
|
+
createGraphExplorationStore,
|
|
106
|
+
createSelectionStore,
|
|
107
|
+
createGraphFocusStore,
|
|
108
|
+
enrichNodes,
|
|
109
|
+
enrichEdges,
|
|
110
|
+
buildColorPalette,
|
|
111
|
+
type RawGraphNode,
|
|
112
|
+
type RawGraphEdge,
|
|
113
|
+
type WorkspaceStores,
|
|
114
|
+
} from "@petrarca/sonnet-graph";
|
|
115
|
+
|
|
116
|
+
// Create stores once (e.g. in a context provider)
|
|
117
|
+
const stores: WorkspaceStores = {
|
|
118
|
+
graphData: createGraphDataStore(),
|
|
119
|
+
graphFilter: createGraphFilterStore(),
|
|
120
|
+
graphExploration: createGraphExplorationStore(),
|
|
121
|
+
selection: createSelectionStore(),
|
|
122
|
+
graphFocus: createGraphFocusStore(),
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Render
|
|
126
|
+
function MyGraph() {
|
|
127
|
+
return (
|
|
128
|
+
<GraphStoresContext.Provider value={stores}>
|
|
129
|
+
<GraphRendererProvider defaultRenderer="cytoscape">
|
|
130
|
+
<div style={{ display: "flex", height: 600 }}>
|
|
131
|
+
<GraphVisualizer />
|
|
132
|
+
<ActionPanel />
|
|
133
|
+
</div>
|
|
134
|
+
</GraphRendererProvider>
|
|
135
|
+
</GraphStoresContext.Provider>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
See [LICENSE.md](../../LICENSE.md).
|
package/dist/index.d.ts
CHANGED
|
@@ -494,6 +494,18 @@ declare const useGraphFocus: zustand.UseBoundStore<zustand.StoreApi<GraphFocusSt
|
|
|
494
494
|
* - GraphFilter (label filters)
|
|
495
495
|
*/
|
|
496
496
|
|
|
497
|
+
/** Options for bounded node expansion. */
|
|
498
|
+
interface ExpandOptions {
|
|
499
|
+
direction?: "both" | "out" | "in";
|
|
500
|
+
relTypes?: string[];
|
|
501
|
+
limit?: number;
|
|
502
|
+
}
|
|
503
|
+
/** Result shape returned by the expand backend call. */
|
|
504
|
+
interface ExpandResult {
|
|
505
|
+
nodes: RawGraphNode[];
|
|
506
|
+
edges: RawGraphEdge[];
|
|
507
|
+
has_more: boolean;
|
|
508
|
+
}
|
|
497
509
|
/**
|
|
498
510
|
* Store dependencies for GraphExploration.
|
|
499
511
|
* Allows workspace-specific or global store injection.
|
|
@@ -503,10 +515,8 @@ interface GraphExplorationDeps {
|
|
|
503
515
|
selection: UseBoundStore<StoreApi<SelectionStore>>;
|
|
504
516
|
graphFocus: UseBoundStore<StoreApi<GraphFocusStore>>;
|
|
505
517
|
graphFilter: UseBoundStore<StoreApi<GraphFilterStore>>;
|
|
506
|
-
expandNode: (id: number) => Promise<
|
|
507
|
-
|
|
508
|
-
edges: RawGraphEdge[];
|
|
509
|
-
}>;
|
|
518
|
+
expandNode: (id: number, options?: ExpandOptions) => Promise<ExpandResult>;
|
|
519
|
+
getNodeEdgeTypes?: (id: number) => Promise<string[]>;
|
|
510
520
|
getNodes: (ids: number[]) => Promise<RawGraphNode[]>;
|
|
511
521
|
getLabelDisplayMap?: () => LabelDisplayMap;
|
|
512
522
|
}
|
|
@@ -614,9 +624,10 @@ interface GraphExplorationStore {
|
|
|
614
624
|
* Expand a node by fetching connected nodes/edges from backend
|
|
615
625
|
* and merging them into the graph data.
|
|
616
626
|
* @param nodeId - ID of the node to expand
|
|
627
|
+
* @param options - Optional expand parameters (direction, relTypes, limit)
|
|
617
628
|
* @returns Promise that resolves when expansion is complete
|
|
618
629
|
*/
|
|
619
|
-
expandNode: (nodeId: string) => Promise<void>;
|
|
630
|
+
expandNode: (nodeId: string, options?: ExpandOptions) => Promise<void>;
|
|
620
631
|
/**
|
|
621
632
|
* Add a node to the graph by ID.
|
|
622
633
|
* If the node already exists in the graph, just focuses it (if autoFocus=true).
|
|
@@ -834,8 +845,10 @@ interface GraphVisualizerProps {
|
|
|
834
845
|
onCopyNode?: (node: VisualGraphNode) => void;
|
|
835
846
|
/** Extra toolbar content (e.g. clipboard UI) injected into the renderer toolbar. */
|
|
836
847
|
extraToolbarContent?: ReactNode;
|
|
848
|
+
/** Fetch distinct edge types for a node (for expand options panel). */
|
|
849
|
+
getNodeEdgeTypes?: (id: number) => Promise<string[]>;
|
|
837
850
|
}
|
|
838
|
-
declare function GraphVisualizer({ onCopyNode, extraToolbarContent, }: GraphVisualizerProps): react_jsx_runtime.JSX.Element;
|
|
851
|
+
declare function GraphVisualizer({ onCopyNode, extraToolbarContent, getNodeEdgeTypes, }: GraphVisualizerProps): react_jsx_runtime.JSX.Element;
|
|
839
852
|
|
|
840
853
|
interface ActionPanelProps {
|
|
841
854
|
/** Optional actions rendered at the top of the panel (e.g. CRUD buttons) */
|
|
@@ -855,4 +868,15 @@ declare function EdgeInfoCard({ edge }: Props): react_jsx_runtime.JSX.Element;
|
|
|
855
868
|
|
|
856
869
|
declare function Overview(): react_jsx_runtime.JSX.Element | null;
|
|
857
870
|
|
|
858
|
-
|
|
871
|
+
interface GraphA11yListProps {
|
|
872
|
+
/** Render on-screen instead of visually-hidden (still a11y-present). */
|
|
873
|
+
visible?: boolean;
|
|
874
|
+
/** Estimated row height in px (virtualization). Default 28. */
|
|
875
|
+
rowHeight?: number;
|
|
876
|
+
/** Max viewport height in px when visible. Default 320. */
|
|
877
|
+
maxHeight?: number;
|
|
878
|
+
className?: string;
|
|
879
|
+
}
|
|
880
|
+
declare function GraphA11yList({ visible, rowHeight, maxHeight, className, }: GraphA11yListProps): react_jsx_runtime.JSX.Element;
|
|
881
|
+
|
|
882
|
+
export { ActionPanel, type ActionPanelState, type ActionPanelStore, type ColorPalette, EMPTY_NORMALIZED, EdgeInfoCard, type EdgeVisual, type ExpandOptions, type ExpandResult, GraphA11yList, type GraphA11yListProps, type GraphDataHook, type GraphDataStore, type GraphDisplayConfig, type GraphExplorationDeps, type GraphExplorationStore, type GraphFilterStore, type GraphFocusAction, type GraphFocusStore, type GraphProperties, type GraphProperty, type GraphRenderer, GraphRendererProvider, type GraphStatistics, type WorkspaceStores as GraphStoreBundle, GraphStoresContext, GraphVisualizer, type GraphVisualizerProps, type LabelDisplayMap, type LiveGraphDataResult, NodeInfoCard, type NodeVisual, type NormalizedGraph, Overview, type RawGraphEdge, type RawGraphNode, type SelectionStore, type StoreFactory, type VisualGraphEdge, type VisualGraphNode, type VisualGraphNormalized, type WorkspaceStores, buildColorPalette, buildColorPaletteFromNodes, createActionPanelStore, createGraphDataStore, createGraphExplorationStore, createGraphFilterStore, createGraphFocusStore, createSelectionStore, enrichEdge, enrichEdges, enrichNode, enrichNodes, extractDisplayLabel, isRawGraphNode, isVisualEdge, isVisualNode, normalizeGraph, toCytoscapeEdge, toCytoscapeNode, toReagraphEdge, toReagraphNode, useActionPanelStore, useCytoscapeData, useGraphFocus, useGraphRenderer, useLiveGraphData, useReagraphData, useWorkspaceGraphData, useWorkspaceGraphExploration, useWorkspaceGraphFilter, useWorkspaceSelection };
|