vortx-gl 1.0.4 → 1.0.27
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/dist/components/DatasetSelector.d.ts +19 -0
- package/dist/components/FPSMonitor.d.ts +2 -0
- package/dist/components/GraphCanvas.d.ts +109 -0
- package/dist/components/LayoutControls.d.ts +18 -0
- package/dist/components/LucideIcon.d.ts +10 -0
- package/dist/components/PropertyPanel.d.ts +28 -0
- package/dist/components/RadialMenu.d.ts +33 -0
- package/dist/components/SearchBar.d.ts +12 -0
- package/dist/components/ViewControls.d.ts +18 -0
- package/dist/engine/Minimap.d.ts +25 -0
- package/dist/engine/api/adapter.d.ts +35 -0
- package/dist/engine/api/index.d.ts +2 -0
- package/dist/engine/api/types.d.ts +86 -0
- package/dist/engine/config.d.ts +117 -0
- package/dist/engine/core/Camera.d.ts +34 -0
- package/dist/engine/core/ComboStore.d.ts +23 -0
- package/dist/engine/core/EdgeStore.d.ts +37 -0
- package/dist/engine/core/NodeStore.d.ts +34 -0
- package/dist/engine/core/context.d.ts +20 -0
- package/dist/engine/events.d.ts +0 -13
- package/dist/engine/gpu/GpuBufferManager.d.ts +39 -0
- package/dist/engine/interaction/GroupInteraction.d.ts +40 -0
- package/dist/engine/interaction.d.ts +7 -2
- package/dist/engine/overlay/ComboRenderer.d.ts +25 -0
- package/dist/engine/overlay/EdgeRenderer.d.ts +32 -0
- package/dist/engine/overlay/NodeRenderer.d.ts +52 -0
- package/dist/engine/overlay/OverlayManager.d.ts +38 -0
- package/dist/engine/overlay/SharedOverlayState.d.ts +47 -0
- package/dist/engine/overlay/effects.d.ts +15 -0
- package/dist/engine/overlay/index.d.ts +2 -0
- package/dist/engine/overlay/shapes.d.ts +7 -0
- package/dist/engine/overlay/text.d.ts +15 -0
- package/dist/engine/picking.d.ts +14 -3
- package/dist/engine/renderConstants.d.ts +13 -0
- package/dist/engine/renderer.d.ts +185 -432
- package/dist/engine/shaders/edge.glsl.d.ts +2 -0
- package/dist/engine/shaders/node.glsl.d.ts +2 -0
- package/dist/engine/shaders.d.ts +2 -4
- package/dist/engine/spatialIndex.d.ts +32 -0
- package/dist/engine/types.d.ts +472 -9
- package/dist/engine/utils/pointSize.d.ts +23 -0
- package/dist/engine/utils/styleResolver.d.ts +163 -0
- package/dist/index.d.ts +11 -5
- package/dist/vortx-gl.css +1206 -1
- package/dist/vortx-gl.es.js +3718 -1
- package/dist/vortx-gl.umd.js +3706 -1
- package/package.json +27 -19
- package/dist/assets/layout.worker-CBxeMMC3.js +0 -1
- package/dist/engine/overlay.d.ts +0 -80
- package/dist/favicon.ico +0 -0
- package/dist/logo.png +0 -0
- package/dist/vite.svg +0 -1
- package/examples/vue-example.vue +0 -80
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface Dataset {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
count: string;
|
|
5
|
+
size: string;
|
|
6
|
+
file: string;
|
|
7
|
+
}
|
|
8
|
+
type __VLS_Props = {
|
|
9
|
+
modelValue: string;
|
|
10
|
+
datasets: Dataset[];
|
|
11
|
+
};
|
|
12
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
13
|
+
change: (value: string) => any;
|
|
14
|
+
"update:modelValue": (value: string) => any;
|
|
15
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
16
|
+
onChange?: ((value: string) => any) | undefined;
|
|
17
|
+
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
18
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
19
|
+
export default _default;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, HTMLDivElement>;
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { GraphEngine } from '../engine/renderer';
|
|
2
|
+
import { NodeInput, EdgeInput, Stylesheet, RadialMenuItem } from '../engine/types';
|
|
3
|
+
interface GraphData {
|
|
4
|
+
nodes: Array<{
|
|
5
|
+
data: NodeInput;
|
|
6
|
+
position?: {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
};
|
|
10
|
+
}>;
|
|
11
|
+
edges: Array<{
|
|
12
|
+
data: EdgeInput;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
type __VLS_Props = {
|
|
16
|
+
data?: GraphData;
|
|
17
|
+
theme?: "dark" | "light";
|
|
18
|
+
showUI?: boolean;
|
|
19
|
+
autoFit?: boolean;
|
|
20
|
+
};
|
|
21
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {
|
|
22
|
+
engine: import('vue').ShallowRef<GraphEngine | null, GraphEngine | null>;
|
|
23
|
+
runLayout: (id: string) => void;
|
|
24
|
+
runStressTest: (count: number) => void;
|
|
25
|
+
toggleFlow: () => void;
|
|
26
|
+
toggleTheme: () => void;
|
|
27
|
+
fitToView: () => void | undefined;
|
|
28
|
+
zoomIn: () => void | undefined;
|
|
29
|
+
zoomOut: () => void | undefined;
|
|
30
|
+
loadDataset: (id: string) => Promise<void>;
|
|
31
|
+
addNode: (input: NodeInput) => string | number | undefined;
|
|
32
|
+
removeNode: (id: string | number) => void;
|
|
33
|
+
updateNode: (input: NodeInput) => void;
|
|
34
|
+
addEdge: (input: EdgeInput) => string | undefined;
|
|
35
|
+
removeEdge: (id: string) => void;
|
|
36
|
+
updateEdge: (input: EdgeInput) => void;
|
|
37
|
+
showAllHidden: () => void | undefined;
|
|
38
|
+
setStylesheet: (sheet: Stylesheet) => void | undefined;
|
|
39
|
+
setRadialMenu: (type: "node" | "edge" | "combo", items: RadialMenuItem[]) => void | undefined;
|
|
40
|
+
selectNode: (id: number) => void;
|
|
41
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
42
|
+
"nodes-selected": (ids: number[]) => any;
|
|
43
|
+
"edge-selected": (id: string | null) => any;
|
|
44
|
+
"node-selected": (id: number | null) => any;
|
|
45
|
+
"combo-selected": (id: string | null) => any;
|
|
46
|
+
"node-moved": (detail: {
|
|
47
|
+
id: number;
|
|
48
|
+
x: number;
|
|
49
|
+
y: number;
|
|
50
|
+
}) => any;
|
|
51
|
+
"canvas-click": () => any;
|
|
52
|
+
"layout-started": (layoutId: string) => any;
|
|
53
|
+
"theme-changed": (theme: "dark" | "light") => any;
|
|
54
|
+
"dataset-loaded": (datasetId: string) => any;
|
|
55
|
+
"node-added": (node: NodeInput) => any;
|
|
56
|
+
"node-removed": (id: string | number) => any;
|
|
57
|
+
"edge-added": (edge: EdgeInput) => any;
|
|
58
|
+
"edge-removed": (id: string) => any;
|
|
59
|
+
"node-updated": (node: NodeInput) => any;
|
|
60
|
+
"edge-updated": (edge: EdgeInput) => any;
|
|
61
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
62
|
+
"onNodes-selected"?: ((ids: number[]) => any) | undefined;
|
|
63
|
+
"onEdge-selected"?: ((id: string | null) => any) | undefined;
|
|
64
|
+
"onNode-selected"?: ((id: number | null) => any) | undefined;
|
|
65
|
+
"onCombo-selected"?: ((id: string | null) => any) | undefined;
|
|
66
|
+
"onNode-moved"?: ((detail: {
|
|
67
|
+
id: number;
|
|
68
|
+
x: number;
|
|
69
|
+
y: number;
|
|
70
|
+
}) => any) | undefined;
|
|
71
|
+
"onCanvas-click"?: (() => any) | undefined;
|
|
72
|
+
"onLayout-started"?: ((layoutId: string) => any) | undefined;
|
|
73
|
+
"onTheme-changed"?: ((theme: "dark" | "light") => any) | undefined;
|
|
74
|
+
"onDataset-loaded"?: ((datasetId: string) => any) | undefined;
|
|
75
|
+
"onNode-added"?: ((node: NodeInput) => any) | undefined;
|
|
76
|
+
"onNode-removed"?: ((id: string | number) => any) | undefined;
|
|
77
|
+
"onEdge-added"?: ((edge: EdgeInput) => any) | undefined;
|
|
78
|
+
"onEdge-removed"?: ((id: string) => any) | undefined;
|
|
79
|
+
"onNode-updated"?: ((node: NodeInput) => any) | undefined;
|
|
80
|
+
"onEdge-updated"?: ((edge: EdgeInput) => any) | undefined;
|
|
81
|
+
}>, {
|
|
82
|
+
theme: "dark" | "light";
|
|
83
|
+
showUI: boolean;
|
|
84
|
+
autoFit: boolean;
|
|
85
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
86
|
+
canvasRef: HTMLCanvasElement;
|
|
87
|
+
overlayCanvasRef: HTMLCanvasElement;
|
|
88
|
+
searchBarRef: import('vue').CreateComponentPublicInstanceWithMixins<Readonly<{
|
|
89
|
+
nodes: import('..').NodeData[];
|
|
90
|
+
}> & Readonly<{
|
|
91
|
+
onSelect?: ((id: number) => any) | undefined;
|
|
92
|
+
}>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
93
|
+
select: (id: number) => any;
|
|
94
|
+
}, import('vue').PublicProps, {}, false, {}, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, {
|
|
95
|
+
inputRef: HTMLInputElement;
|
|
96
|
+
}, HTMLDivElement, import('vue').ComponentProvideOptions, {
|
|
97
|
+
P: {};
|
|
98
|
+
B: {};
|
|
99
|
+
D: {};
|
|
100
|
+
C: {};
|
|
101
|
+
M: {};
|
|
102
|
+
Defaults: {};
|
|
103
|
+
}, Readonly<{
|
|
104
|
+
nodes: import('..').NodeData[];
|
|
105
|
+
}> & Readonly<{
|
|
106
|
+
onSelect?: ((id: number) => any) | undefined;
|
|
107
|
+
}>, {}, {}, {}, {}, {}> | null;
|
|
108
|
+
}, HTMLDivElement>;
|
|
109
|
+
export default _default;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface LayoutOption {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
icon: string;
|
|
5
|
+
}
|
|
6
|
+
type __VLS_Props = {
|
|
7
|
+
layouts: LayoutOption[];
|
|
8
|
+
currentLayout: string;
|
|
9
|
+
flowEnabled: boolean;
|
|
10
|
+
};
|
|
11
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
12
|
+
toggleFlow: () => any;
|
|
13
|
+
runLayout: (id: string) => any;
|
|
14
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
15
|
+
onToggleFlow?: (() => any) | undefined;
|
|
16
|
+
onRunLayout?: ((id: string) => any) | undefined;
|
|
17
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
name: string;
|
|
3
|
+
size?: number | string;
|
|
4
|
+
strokeWidth?: number | string;
|
|
5
|
+
};
|
|
6
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
7
|
+
size: number | string;
|
|
8
|
+
strokeWidth: number | string;
|
|
9
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, SVGSVGElement>;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { NodeMetadata, EdgeMetadata, Combo } from '../engine/types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
nodeId: number | null;
|
|
4
|
+
nodeMetadata: NodeMetadata | null;
|
|
5
|
+
nodeX: number;
|
|
6
|
+
nodeY: number;
|
|
7
|
+
edgeId: string | null;
|
|
8
|
+
edgeMetadata: EdgeMetadata | null;
|
|
9
|
+
combo: Combo | null;
|
|
10
|
+
};
|
|
11
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
12
|
+
"update:nodeX": (val: number) => any;
|
|
13
|
+
"update:nodeY": (val: number) => any;
|
|
14
|
+
"update:nodeId": (val: number | null) => any;
|
|
15
|
+
"update:edgeId": (val: string | null) => any;
|
|
16
|
+
"update:combo": (val: Combo | null) => any;
|
|
17
|
+
"update:comboLabel": (val: string) => any;
|
|
18
|
+
removeFromCombo: (nodeId: number) => any;
|
|
19
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
20
|
+
"onUpdate:nodeX"?: ((val: number) => any) | undefined;
|
|
21
|
+
"onUpdate:nodeY"?: ((val: number) => any) | undefined;
|
|
22
|
+
"onUpdate:nodeId"?: ((val: number | null) => any) | undefined;
|
|
23
|
+
"onUpdate:edgeId"?: ((val: string | null) => any) | undefined;
|
|
24
|
+
"onUpdate:combo"?: ((val: Combo | null) => any) | undefined;
|
|
25
|
+
"onUpdate:comboLabel"?: ((val: string) => any) | undefined;
|
|
26
|
+
onRemoveFromCombo?: ((nodeId: number) => any) | undefined;
|
|
27
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
28
|
+
export default _default;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface MenuItem {
|
|
2
|
+
label: string;
|
|
3
|
+
icon: string;
|
|
4
|
+
action: string;
|
|
5
|
+
}
|
|
6
|
+
type __VLS_Props = {
|
|
7
|
+
show: boolean;
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
type: string;
|
|
11
|
+
items: MenuItem[];
|
|
12
|
+
};
|
|
13
|
+
declare function __VLS_template(): {
|
|
14
|
+
attrs: Partial<{}>;
|
|
15
|
+
slots: {
|
|
16
|
+
center?(_: {}): any;
|
|
17
|
+
};
|
|
18
|
+
refs: {};
|
|
19
|
+
rootEl: any;
|
|
20
|
+
};
|
|
21
|
+
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
|
|
22
|
+
declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
23
|
+
action: (action: string) => any;
|
|
24
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
25
|
+
onAction?: ((action: string) => any) | undefined;
|
|
26
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
27
|
+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
28
|
+
export default _default;
|
|
29
|
+
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
30
|
+
new (): {
|
|
31
|
+
$slots: S;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NodeData } from '../engine/types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
nodes: NodeData[];
|
|
4
|
+
};
|
|
5
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
6
|
+
select: (id: number) => any;
|
|
7
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
8
|
+
onSelect?: ((id: number) => any) | undefined;
|
|
9
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
10
|
+
inputRef: HTMLInputElement;
|
|
11
|
+
}, HTMLDivElement>;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
theme: "dark" | "light";
|
|
3
|
+
flowEnabled: boolean;
|
|
4
|
+
};
|
|
5
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
6
|
+
toggleTheme: () => any;
|
|
7
|
+
fit: () => any;
|
|
8
|
+
zoomIn: () => any;
|
|
9
|
+
zoomOut: () => any;
|
|
10
|
+
toggleFlow: () => any;
|
|
11
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
|
+
onToggleTheme?: (() => any) | undefined;
|
|
13
|
+
onFit?: (() => any) | undefined;
|
|
14
|
+
onZoomIn?: (() => any) | undefined;
|
|
15
|
+
onZoomOut?: (() => any) | undefined;
|
|
16
|
+
onToggleFlow?: (() => any) | undefined;
|
|
17
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { GraphEngine } from './renderer';
|
|
2
|
+
/**
|
|
3
|
+
* Renders an aerial-view minimap of the graph into its own canvas.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* const minimap = new Minimap(engine, canvas);
|
|
7
|
+
* minimap.start();
|
|
8
|
+
* // …
|
|
9
|
+
* minimap.destroy();
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare class Minimap {
|
|
13
|
+
private engine;
|
|
14
|
+
private canvas;
|
|
15
|
+
private ctx;
|
|
16
|
+
private intervalId;
|
|
17
|
+
private intervalMs;
|
|
18
|
+
constructor(engine: GraphEngine, canvas: HTMLCanvasElement, intervalMs?: number);
|
|
19
|
+
/** Begin periodic redraw. Returns a cleanup function for symmetry with addEventListener. */
|
|
20
|
+
start(): () => void;
|
|
21
|
+
/** Stop redraws and release the interval handle. Safe to call multiple times. */
|
|
22
|
+
destroy(): void;
|
|
23
|
+
/** Force an immediate redraw. Useful after a fitView or dataset swap. */
|
|
24
|
+
draw(): void;
|
|
25
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { NodeInput, EdgeInput } from '../types';
|
|
2
|
+
import { BackendGraphData, BackendNodeElement, BackendEdgeElement } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Map a backend node to the renderer's NodeInput.
|
|
5
|
+
*
|
|
6
|
+
* Fields with first-class renderer support — `colorOnSelect`, `groupCount` —
|
|
7
|
+
* are lifted to top-level inputs. Fields the renderer doesn't know about
|
|
8
|
+
* (iri, codeValue, parentConcept, …) ride along on `data` so consumers can
|
|
9
|
+
* still read them back via `getAllNodes()`.
|
|
10
|
+
*
|
|
11
|
+
* `backgroundImage` is a server-resolved URL (or `data:` base64) and is passed
|
|
12
|
+
* straight through as the renderer's `image`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const adaptNode: (element: BackendNodeElement) => NodeInput;
|
|
15
|
+
/**
|
|
16
|
+
* Map a backend edge to the renderer's EdgeInput.
|
|
17
|
+
*
|
|
18
|
+
* Backend `classes` is a bare string ("edges") — we normalize to an array so
|
|
19
|
+
* downstream code can treat node and edge classes uniformly. Selection-time
|
|
20
|
+
* styling (`colorOnSelect`, `widthOnSelect`) is lifted to first-class inputs.
|
|
21
|
+
*/
|
|
22
|
+
export declare const adaptEdge: (element: BackendEdgeElement) => EdgeInput;
|
|
23
|
+
/**
|
|
24
|
+
* Adapt a full backend payload into the renderer's input shape.
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* const { nodes, edges } = adaptGraphData(apiResponse);
|
|
28
|
+
* nodes.forEach((n) => engine.addNode(n));
|
|
29
|
+
* edges.forEach((e) => engine.addEdge(e));
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare const adaptGraphData: (data: BackendGraphData) => {
|
|
33
|
+
nodes: NodeInput[];
|
|
34
|
+
edges: EdgeInput[];
|
|
35
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/** Discriminator on `NodeElement.classes` — drives the rendering style. */
|
|
2
|
+
export type NodeClass = "nodes" | "nodeGroup";
|
|
3
|
+
/** Discriminator on `EdgeElement.classes` — backend currently emits a bare string here, not an array. */
|
|
4
|
+
export type EdgeClass = "edges";
|
|
5
|
+
/** Stable category tag carried on every node — useful for filtering/grouping. */
|
|
6
|
+
export type CodeValue = "SID-ACC" | "SN-PST" | "SN-CMNT" | "TAG" | "WWW" | (string & {});
|
|
7
|
+
/**
|
|
8
|
+
* Backend node payload.
|
|
9
|
+
*
|
|
10
|
+
* `hidden` is typed as boolean here to match the consumer's existing `IGraph.ts`.
|
|
11
|
+
* The original spec described it as the string `'true'|'false'`; if the API
|
|
12
|
+
* actually emits strings, normalize at the network boundary (not here).
|
|
13
|
+
*/
|
|
14
|
+
export interface BackendNodeData {
|
|
15
|
+
/** Numeric node id used as the join key for edges. */
|
|
16
|
+
id: number;
|
|
17
|
+
iri: string;
|
|
18
|
+
label: string;
|
|
19
|
+
shownValue: string;
|
|
20
|
+
displayName: string;
|
|
21
|
+
/** Current fill — may have been overridden from `defaultColor` (e.g. highlight assignment). */
|
|
22
|
+
color: string;
|
|
23
|
+
/** Base fill when not highlighted. */
|
|
24
|
+
defaultColor: string;
|
|
25
|
+
/** Fill swap applied on select — NOT the selection ring color. */
|
|
26
|
+
colorOnSelect: string;
|
|
27
|
+
hidden: boolean;
|
|
28
|
+
deletable: boolean;
|
|
29
|
+
parentConcept: string;
|
|
30
|
+
/**
|
|
31
|
+
* Server-resolved icon URL. Can be a CDN path, a proxy endpoint, or an inline
|
|
32
|
+
* `data:` base64 payload — the renderer treats it as an opaque image source.
|
|
33
|
+
*/
|
|
34
|
+
backgroundImage: string;
|
|
35
|
+
/** Diameter in CSS pixels (consistently 50 in observed data). */
|
|
36
|
+
width: number;
|
|
37
|
+
height: number;
|
|
38
|
+
codeValue: CodeValue;
|
|
39
|
+
geolocations: unknown[];
|
|
40
|
+
/** Group UUID — present when this node represents a collapsed cluster (`classes: ['nodeGroup']`). */
|
|
41
|
+
group?: string;
|
|
42
|
+
/** Number of nodes collapsed into this group. */
|
|
43
|
+
groupCount?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface BackendNodeElement {
|
|
46
|
+
data: BackendNodeData;
|
|
47
|
+
position: {
|
|
48
|
+
x: number;
|
|
49
|
+
y: number;
|
|
50
|
+
};
|
|
51
|
+
/** Style discriminator — array form (single class today: `['nodes']` or `['nodeGroup']`). */
|
|
52
|
+
classes: NodeClass[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Backend edge payload.
|
|
56
|
+
*
|
|
57
|
+
* `width` encodes group size visually: 1 = single, 5-7/12/15 = bundled. The real
|
|
58
|
+
* count is `ids.length`. `label` already contains the human-readable count when
|
|
59
|
+
* bundled (e.g. `"Follows (24)"`) — render as-is, don't reparse.
|
|
60
|
+
*/
|
|
61
|
+
export interface BackendEdgeData {
|
|
62
|
+
id: string;
|
|
63
|
+
iri: string;
|
|
64
|
+
label: string;
|
|
65
|
+
source: number;
|
|
66
|
+
target: number;
|
|
67
|
+
color: string;
|
|
68
|
+
defaultColor: string;
|
|
69
|
+
colorOnSelect: string;
|
|
70
|
+
hidden: boolean;
|
|
71
|
+
/** Edge line style. Backend defaults to "solid"; resolver supports "dashed"/"dotted" too. */
|
|
72
|
+
style?: "solid" | "dashed" | "dotted";
|
|
73
|
+
width: number;
|
|
74
|
+
widthOnSelect: number;
|
|
75
|
+
/** Real edge ids bundled into this visual edge. `ids.length === 1` for un-grouped. */
|
|
76
|
+
ids: string[];
|
|
77
|
+
}
|
|
78
|
+
export interface BackendEdgeElement {
|
|
79
|
+
data: BackendEdgeData;
|
|
80
|
+
/** Style discriminator — backend emits a bare string, not an array (contrast with nodes). */
|
|
81
|
+
classes: EdgeClass;
|
|
82
|
+
}
|
|
83
|
+
export interface BackendGraphData {
|
|
84
|
+
nodes: BackendNodeElement[];
|
|
85
|
+
edges: BackendEdgeElement[];
|
|
86
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
export declare const GraphConfig: {
|
|
2
|
+
readonly zoom: {
|
|
3
|
+
/** Edge labels need a readable run of pixels between endpoints, and the
|
|
4
|
+
* label text is a fixed ~18 px CSS — only show once nodes are large
|
|
5
|
+
* enough that labels don't dwarf them. zoom 0.5 → pointSize ≈ 25 px. */
|
|
6
|
+
readonly hideEdgeLabelsBelow: 0.5;
|
|
7
|
+
/** Same logic for node labels. Fixed-size labels look oversized when the
|
|
8
|
+
* node beside them is smaller than the label glyph height. */
|
|
9
|
+
readonly hideNodeLabelsBelow: 0.5;
|
|
10
|
+
/** Arrow heads are small triangles — illegible below ~11 px nodes. */
|
|
11
|
+
readonly hideArrowsBelow: 0.15;
|
|
12
|
+
/** Count badge + expand button anchor on the node; need ~21 px node. */
|
|
13
|
+
readonly hideBadgesBelow: 0.4;
|
|
14
|
+
/** Below this, GPU edge pass may fall back to gl.LINES on big graphs. */
|
|
15
|
+
readonly simplifyEdgesBelow: 0.15;
|
|
16
|
+
/** Below this the per-edge/per-node text+arrow block is skipped entirely. */
|
|
17
|
+
readonly fullStyleBelow: 0.05;
|
|
18
|
+
readonly sensitivity: 1.2;
|
|
19
|
+
readonly fitOnLoad: true;
|
|
20
|
+
};
|
|
21
|
+
readonly performance: {
|
|
22
|
+
readonly lodNodeThreshold: 2000;
|
|
23
|
+
readonly edgeCullThreshold: 5000;
|
|
24
|
+
readonly instanceBatchSize: 512;
|
|
25
|
+
readonly viewportCullMargin: 100;
|
|
26
|
+
readonly targetFPS: 60;
|
|
27
|
+
readonly fullStyleRange: 1500;
|
|
28
|
+
readonly smallGraphThreshold: 3000;
|
|
29
|
+
readonly maxLabelsPerFrame: 800;
|
|
30
|
+
};
|
|
31
|
+
readonly interaction: {
|
|
32
|
+
readonly panInertia: true;
|
|
33
|
+
readonly panDecay: 0.88;
|
|
34
|
+
readonly dragMode: "single";
|
|
35
|
+
readonly selectionMode: "additive";
|
|
36
|
+
readonly contextMenu: true;
|
|
37
|
+
readonly hoverThrottleMs: 32;
|
|
38
|
+
readonly zoomSettleMs: 120;
|
|
39
|
+
readonly longPressMs: 500;
|
|
40
|
+
readonly tapTimeMs: 250;
|
|
41
|
+
readonly tapDistancePx: 10;
|
|
42
|
+
};
|
|
43
|
+
readonly style: {
|
|
44
|
+
readonly selectionRingColor: "#4A9EFF";
|
|
45
|
+
readonly selectionRingWidthPx: 3;
|
|
46
|
+
readonly selectionRingRadiusFactor: 1.1;
|
|
47
|
+
readonly nodeGroupBadgeRadiusPx: 10;
|
|
48
|
+
readonly nodeGroupBadgeFill: "#76ABE7";
|
|
49
|
+
readonly nodeGroupBadgeText: "#ffffff";
|
|
50
|
+
readonly nodeGroupBadgeTextPx: 10;
|
|
51
|
+
readonly nodeGroupStackShadowOffsets: readonly number[];
|
|
52
|
+
readonly nodeGroupStackShadowOpacity: 0.2;
|
|
53
|
+
readonly nodeExpandButtonRadiusPx: 10;
|
|
54
|
+
readonly nodeExpandButtonFill: "#1a1a1a";
|
|
55
|
+
readonly nodeExpandButtonIcon: "#ffffff";
|
|
56
|
+
readonly nodeExpandButtonIconPx: 12;
|
|
57
|
+
readonly nodeShape: "circle";
|
|
58
|
+
readonly edgeStyle: "bezier";
|
|
59
|
+
readonly labelFontSize: 11;
|
|
60
|
+
readonly iconMode: "canvas";
|
|
61
|
+
/** CSS pixels of inset between the icon and the node's outer border. */
|
|
62
|
+
readonly nodeIconPaddingPx: 4;
|
|
63
|
+
readonly minimap: true;
|
|
64
|
+
readonly background: "#f5f5f5";
|
|
65
|
+
readonly minimapIntervalMs: 500;
|
|
66
|
+
/**
|
|
67
|
+
* When a selected node is outside the viewport, draw a small dot + arrow
|
|
68
|
+
* stub at the canvas edge pointing toward it. Useful on small graphs;
|
|
69
|
+
* noisy on large multi-selections (one indicator per off-screen
|
|
70
|
+
* selected node). Set false to suppress.
|
|
71
|
+
*/
|
|
72
|
+
readonly showOffscreenSelectionIndicator: true;
|
|
73
|
+
};
|
|
74
|
+
readonly graphOptions: {
|
|
75
|
+
/** Cytoscape: text-opacity 1 vs 0 on `.nodes`. */
|
|
76
|
+
readonly showEntityLabel: true;
|
|
77
|
+
/** Cytoscape: text-opacity 1 vs 0 on `edges`. */
|
|
78
|
+
readonly showEdgeLabel: true;
|
|
79
|
+
/** Cytoscape: background-image set vs 'none' on `.nodes`. */
|
|
80
|
+
readonly showEntityIcon: true;
|
|
81
|
+
/** Cytoscape: bypasses the icon atlas — solid fill only. */
|
|
82
|
+
readonly showEntityPlainColor: false;
|
|
83
|
+
/** Cytoscape: data(<field>) inside the label mapper — pick the field. */
|
|
84
|
+
readonly entityLabel: "shownValue";
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
export type GraphConfigType = typeof GraphConfig;
|
|
88
|
+
/** Recursively make every field of an object optional. */
|
|
89
|
+
export type DeepPartial<T> = {
|
|
90
|
+
[K in keyof T]?: T[K] extends ReadonlyArray<infer _U> ? T[K] : T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
91
|
+
};
|
|
92
|
+
export type PartialGraphConfig = DeepPartial<GraphConfigType>;
|
|
93
|
+
export type ResolvedGraphConfig = {
|
|
94
|
+
zoom: {
|
|
95
|
+
[K in keyof GraphConfigType["zoom"]]: GraphConfigType["zoom"][K];
|
|
96
|
+
};
|
|
97
|
+
performance: {
|
|
98
|
+
[K in keyof GraphConfigType["performance"]]: GraphConfigType["performance"][K];
|
|
99
|
+
};
|
|
100
|
+
interaction: {
|
|
101
|
+
[K in keyof GraphConfigType["interaction"]]: GraphConfigType["interaction"][K];
|
|
102
|
+
};
|
|
103
|
+
style: {
|
|
104
|
+
[K in keyof GraphConfigType["style"]]: GraphConfigType["style"][K];
|
|
105
|
+
};
|
|
106
|
+
graphOptions: {
|
|
107
|
+
[K in keyof GraphConfigType["graphOptions"]]: GraphConfigType["graphOptions"][K];
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Public shape of the graphOptions section — exported so consumers can build
|
|
112
|
+
* a typed override before passing to createGraphRenderer or recomputeStyles.
|
|
113
|
+
*
|
|
114
|
+
* // STYLE: matches the Cytoscape `defaultOptions` bag 1:1.
|
|
115
|
+
*/
|
|
116
|
+
export type GraphOptions = ResolvedGraphConfig["graphOptions"];
|
|
117
|
+
export declare function resolveConfig(overrides?: PartialGraphConfig): ResolvedGraphConfig;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { mat3, vec2 } from 'gl-matrix';
|
|
2
|
+
import { EngineContext } from './context';
|
|
3
|
+
export declare class Camera {
|
|
4
|
+
viewMatrix: mat3;
|
|
5
|
+
private static readonly MAX_ZOOM;
|
|
6
|
+
private static readonly MIN_ZOOM;
|
|
7
|
+
private _invMatrix;
|
|
8
|
+
private _posScratch;
|
|
9
|
+
private ctx;
|
|
10
|
+
constructor(ctx: EngineContext);
|
|
11
|
+
get zoom(): number;
|
|
12
|
+
get offset(): vec2;
|
|
13
|
+
updateMatrix(): void;
|
|
14
|
+
unproject(screenX: number, screenY: number): vec2;
|
|
15
|
+
fitToView(): void;
|
|
16
|
+
fitGroupToView(groupId: string): void;
|
|
17
|
+
calculateFit(minX: number, minY: number, maxX: number, maxY: number): {
|
|
18
|
+
zoom: number;
|
|
19
|
+
offset: vec2;
|
|
20
|
+
};
|
|
21
|
+
private _performFit;
|
|
22
|
+
zoomIn(): void;
|
|
23
|
+
zoomOut(): void;
|
|
24
|
+
setCenter(x: number, y: number): void;
|
|
25
|
+
setZoom(zoom: number): void;
|
|
26
|
+
zoomAt(mouseX: number, mouseY: number, delta: number): void;
|
|
27
|
+
pan(dx: number, dy: number): void;
|
|
28
|
+
getViewportWorldBounds(): {
|
|
29
|
+
minX: number;
|
|
30
|
+
maxX: number;
|
|
31
|
+
minY: number;
|
|
32
|
+
maxY: number;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { EngineContext } from './context';
|
|
2
|
+
import { Combo } from '../types';
|
|
3
|
+
export declare class ComboStore {
|
|
4
|
+
combos: Map<string, Combo>;
|
|
5
|
+
private representativeToCombo;
|
|
6
|
+
private nodeToCombo;
|
|
7
|
+
private ctx;
|
|
8
|
+
constructor(ctx: EngineContext);
|
|
9
|
+
createGroup(id: string, label: string, nodeIds: (string | number)[]): void;
|
|
10
|
+
removeGroup(id: string): void;
|
|
11
|
+
addToGroup(groupId: string, nodeId: string | number): void;
|
|
12
|
+
removeFromGroup(groupId: string, nodeId: string | number): void;
|
|
13
|
+
getComboByRepresentative(id: number): string | null;
|
|
14
|
+
toggleComboCollapse(groupId: string): void;
|
|
15
|
+
moveGroup(groupId: string, dx: number, dy: number, skipSync?: boolean): void;
|
|
16
|
+
calculateBounds(groupId: string): void;
|
|
17
|
+
findNodeGroup(nodeId: string | number): string | null;
|
|
18
|
+
getAllGroups(): {
|
|
19
|
+
id: string;
|
|
20
|
+
label: string;
|
|
21
|
+
nodeIds: (string | number)[];
|
|
22
|
+
}[];
|
|
23
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { EngineContext } from './context';
|
|
2
|
+
import { EdgeMetadata, EdgeInput, EdgeData } from '../types';
|
|
3
|
+
export declare class EdgeStore {
|
|
4
|
+
list: Array<{
|
|
5
|
+
id: string;
|
|
6
|
+
u: number;
|
|
7
|
+
v: number;
|
|
8
|
+
metadata: EdgeMetadata;
|
|
9
|
+
}>;
|
|
10
|
+
idMap: Map<string, number>;
|
|
11
|
+
indexToUserIdMap: Map<string, string>;
|
|
12
|
+
indexToId: string[];
|
|
13
|
+
metadata: Map<string, EdgeMetadata>;
|
|
14
|
+
hiddenEdges: Set<string>;
|
|
15
|
+
indices: Uint32Array | null;
|
|
16
|
+
count: number;
|
|
17
|
+
hasCustomEdges: boolean;
|
|
18
|
+
hasEdgeLabels: boolean;
|
|
19
|
+
private _customEdgeCount;
|
|
20
|
+
private _labeledEdgeCount;
|
|
21
|
+
_bulkMode: boolean;
|
|
22
|
+
private autoEdgeId;
|
|
23
|
+
private ctx;
|
|
24
|
+
constructor(ctx: EngineContext);
|
|
25
|
+
addEdge(input: EdgeInput): string;
|
|
26
|
+
bulkAddEdges(inputs: ReadonlyArray<EdgeInput>): void;
|
|
27
|
+
updateEdge(input: EdgeInput): void;
|
|
28
|
+
removeEdge(edgeId: string): void;
|
|
29
|
+
removeAllConnected(nodeIndex: number): void;
|
|
30
|
+
remapNodeIndex(oldIndex: number, newIndex: number): void;
|
|
31
|
+
resetFlags(): void;
|
|
32
|
+
rebuildEdgeBuffer(): void;
|
|
33
|
+
private calculateCurvatures;
|
|
34
|
+
rebuildIndexToUserIdMap(): void;
|
|
35
|
+
private _removeEdgeInternal;
|
|
36
|
+
getAllEdges(): EdgeData[];
|
|
37
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { EngineContext } from './context';
|
|
2
|
+
import { NodeMetadata, NodeInput, NodeData, Stylesheet, GraphStyle } from '../types';
|
|
3
|
+
export declare class NodeStore {
|
|
4
|
+
count: number;
|
|
5
|
+
capacity: number;
|
|
6
|
+
positions: Float32Array | null;
|
|
7
|
+
colorData: Float32Array;
|
|
8
|
+
idData: Float32Array;
|
|
9
|
+
shapeData: Float32Array;
|
|
10
|
+
sizeData: Float32Array;
|
|
11
|
+
nodeIdMap: Map<string | number, number>;
|
|
12
|
+
reverseIdMap: Map<number, string | number>;
|
|
13
|
+
metadata: Map<number, NodeMetadata>;
|
|
14
|
+
lockedNodes: Set<number>;
|
|
15
|
+
hiddenNodes: Set<number>;
|
|
16
|
+
hasGroupNodes: boolean;
|
|
17
|
+
_bulkMode: boolean;
|
|
18
|
+
private autoNodeId;
|
|
19
|
+
private stylesheet;
|
|
20
|
+
private ctx;
|
|
21
|
+
constructor(ctx: EngineContext);
|
|
22
|
+
setStylesheet(sheet: Stylesheet): void;
|
|
23
|
+
resolveStyle(classes?: string[]): GraphStyle;
|
|
24
|
+
resolveNodeIndex(nodeId: string | number): number | null;
|
|
25
|
+
ensureCapacity(minCount: number): void;
|
|
26
|
+
addNode(input: NodeInput): string | number;
|
|
27
|
+
bulkAddNodes(inputs: ReadonlyArray<NodeInput>): void;
|
|
28
|
+
updateNode(input: NodeInput): void;
|
|
29
|
+
removeNode(nodeId: string | number): void;
|
|
30
|
+
getAllNodes(): NodeData[];
|
|
31
|
+
parseColor(color?: string | [number, number, number, number?]): [number, number, number, number];
|
|
32
|
+
private loadNodeImage;
|
|
33
|
+
private mapShapeToId;
|
|
34
|
+
}
|