@neo4j-nvl/base 1.0.0 → 1.1.0-01fc2de1

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/base.mjs +1 -1
  3. package/dist/types/index.d.ts +44 -11
  4. package/dist/types/layouts/circularLayout/CircularLayout.d.ts +18 -0
  5. package/dist/types/layouts/d3forcelayout/d3ForceLayout.d.ts +20 -20
  6. package/dist/types/layouts/d3forcelayout/types.d.ts +5 -6
  7. package/dist/types/layouts/forcedirectedlayout/ForceCytoLayout.d.ts +1 -1
  8. package/dist/types/layouts/forcedirectedlayout/physlayout/PhysLayout.d.ts +8 -4
  9. package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-fragment.d.ts +1 -1
  10. package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-repulsive-fragment.d.ts +1 -1
  11. package/dist/types/layouts/forcedirectedlayout/physlayout/solarmerger/SolarMerger.d.ts +17 -39
  12. package/dist/types/layouts/forcedirectedlayout/physlayout/solarmerger/types.d.ts +49 -0
  13. package/dist/types/layouts/gridLayout/GridLayout.d.ts +25 -9
  14. package/dist/types/modules/NvlController.d.ts +20 -4
  15. package/dist/types/modules/state/types.d.ts +32 -15
  16. package/dist/types/modules/state/utils.d.ts +2 -2
  17. package/dist/types/renderers/domrenderer/BaseRenderer.d.ts +75 -0
  18. package/dist/types/renderers/{canvasrenderer → domrenderer/canvasrenderer}/CanvasRenderer.d.ts +33 -40
  19. package/dist/types/renderers/domrenderer/canvasrenderer/arrowDrawing.d.ts +168 -0
  20. package/dist/types/renderers/domrenderer/canvasrenderer/nodeDrawing.d.ts +109 -0
  21. package/dist/types/renderers/domrenderer/shared/ImageCache.d.ts +16 -0
  22. package/dist/types/renderers/{canvasrenderer → domrenderer/shared}/arrows/ArrowBundle.d.ts +20 -4
  23. package/dist/types/renderers/{canvasrenderer → domrenderer/shared}/arrows/ArrowBundler.d.ts +11 -1
  24. package/dist/types/renderers/domrenderer/shared/arrows/ArrowBundler.test.d.ts +1 -0
  25. package/dist/types/renderers/domrenderer/shared/arrows/arrows.d.ts +175 -0
  26. package/dist/types/renderers/domrenderer/shared/arrows/arrows.test.d.ts +1 -0
  27. package/dist/types/renderers/domrenderer/shared/nodes/nodes.d.ts +103 -0
  28. package/dist/types/renderers/domrenderer/shared/nodes/nodes.test.d.ts +1 -0
  29. package/dist/types/renderers/{canvasrenderer → domrenderer/shared}/types.d.ts +2 -2
  30. package/dist/types/renderers/domrenderer/shared/util.d.ts +16 -0
  31. package/dist/types/renderers/domrenderer/shared/util.test.d.ts +1 -0
  32. package/dist/types/renderers/{canvasrenderer → domrenderer/shared}/vectorUtils.d.ts +1 -1
  33. package/dist/types/renderers/{canvasrenderer → domrenderer/shared}/wordwrap.d.ts +10 -0
  34. package/dist/types/renderers/domrenderer/shared/wordwrap.test.d.ts +1 -0
  35. package/dist/types/renderers/domrenderer/svgrenderer/SvgRenderer.d.ts +20 -0
  36. package/dist/types/renderers/domrenderer/svgrenderer/SvgRenderer.test.d.ts +1 -0
  37. package/dist/types/renderers/domrenderer/svgrenderer/arrowDrawing.d.ts +59 -0
  38. package/dist/types/renderers/domrenderer/svgrenderer/arrowDrawing.test.d.ts +1 -0
  39. package/dist/types/renderers/domrenderer/svgrenderer/nodeDrawing.d.ts +16 -0
  40. package/dist/types/renderers/domrenderer/svgrenderer/nodeDrawing.test.d.ts +1 -0
  41. package/dist/types/renderers/domrenderer/svgrenderer/svgUtils.d.ts +78 -0
  42. package/dist/types/renderers/domrenderer/svgrenderer/svgUtils.test.d.ts +1 -0
  43. package/dist/types/renderers/webglrenderer/Renderer.d.ts +5 -1
  44. package/dist/types/renderers/webglrenderer/Renderer.test.d.ts +1 -0
  45. package/dist/types/types/graph-element.d.ts +1 -1
  46. package/dist/types/utils/canvasManagement.d.ts +16 -1
  47. package/dist/types/utils/circularUtils.d.ts +3 -0
  48. package/dist/types/utils/circularUtils.test.d.ts +1 -0
  49. package/dist/types/utils/constants.d.ts +7 -3
  50. package/dist/types/utils/geometry.d.ts +2 -1
  51. package/dist/types/utils/graphObjectUtils.d.ts +2 -2
  52. package/dist/types/utils/jsDriverResultTransformer.d.ts +1 -1
  53. package/dist/types/utils/segmentAnalytics.d.ts +2 -2
  54. package/package.json +25 -24
  55. package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-fragment-verlet.d.ts +0 -2
  56. package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-repulsive-fragment-verlet.d.ts +0 -2
  57. package/dist/types/modules/performance.d.ts +0 -93
  58. package/dist/types/renderers/canvasrenderer/ImageCache.d.ts +0 -11
  59. package/dist/types/renderers/canvasrenderer/arrows/arrows.d.ts +0 -55
  60. package/dist/types/renderers/canvasrenderer/nodes/nodes.d.ts +0 -59
  61. package/dist/types/renderers/canvasrenderer/util.d.ts +0 -68
  62. /package/dist/types/{renderers/canvasrenderer/Animation.test.d.ts → layouts/d3forcelayout/circularLayout.test.d.ts} +0 -0
  63. /package/dist/types/{renderers/canvasrenderer/CanvasRenderer.test.d.ts → layouts/d3forcelayout/d3ForceLayout.test.d.ts} +0 -0
  64. /package/dist/types/renderers/{canvasrenderer/ImageCache.test.d.ts → domrenderer/BaseRenderer.test.d.ts} +0 -0
  65. /package/dist/types/renderers/{canvasrenderer → domrenderer/canvasrenderer}/Animation.d.ts +0 -0
  66. /package/dist/types/renderers/{canvasrenderer/arrows/ArrowBundle.test.d.ts → domrenderer/canvasrenderer/Animation.test.d.ts} +0 -0
  67. /package/dist/types/renderers/{canvasrenderer → domrenderer/canvasrenderer}/AnimationHandler.d.ts +0 -0
  68. /package/dist/types/renderers/{canvasrenderer/arrows/ArrowBundler.test.d.ts → domrenderer/canvasrenderer/CanvasRenderer.test.d.ts} +0 -0
  69. /package/dist/types/renderers/{canvasrenderer/arrows/arrows.test.d.ts → domrenderer/canvasrenderer/arrowDrawing.test.d.ts} +0 -0
  70. /package/dist/types/renderers/{canvasrenderer/nodes/nodes.test.d.ts → domrenderer/canvasrenderer/nodeDrawing.test.d.ts} +0 -0
  71. /package/dist/types/renderers/{canvasrenderer/util.test.d.ts → domrenderer/shared/ImageCache.test.d.ts} +0 -0
  72. /package/dist/types/renderers/{canvasrenderer/wordwrap.test.d.ts → domrenderer/shared/arrows/ArrowBundle.test.d.ts} +0 -0
  73. /package/dist/types/renderers/{canvasrenderer → domrenderer/shared}/arrows/constants.d.ts +0 -0
@@ -1,8 +1,8 @@
1
1
  import type { ExternalCallbacks } from './modules/ExternalCallbackHandler';
2
- import type { ForceDirectedOptions, HierarchicalOptions, Layout, LayoutOptions, NvlOptions, NvlState, Renderer, ZoomOptions } from './modules/state/types';
3
- import { CanvasRendererType, ForceDirectedLayoutType, FreeLayoutType, GridLayoutType, HierarchicalLayoutType, WebGLRendererType, d3ForceLayoutType } from './modules/state/types';
4
- import type { StyledCaption } from './renderers/canvasrenderer/types';
5
- import { drawCircleBand } from './renderers/canvasrenderer/util';
2
+ import type { CircularOptions, ForceDirectedOptions, HierarchicalOptions, Renderer as InternalRenderer, Layout, LayoutOptions, NvlOptions, NvlState, ZoomOptions } from './modules/state/types';
3
+ import { CanvasRendererType, CircularLayoutType, ForceDirectedLayoutType, FreeLayoutType, GridLayoutType, HierarchicalLayoutType, SvgRendererType, WebGLRendererType, d3ForceLayoutType } from './modules/state/types';
4
+ import { drawCircleBand } from './renderers/domrenderer/canvasrenderer/nodeDrawing';
5
+ import type { StyledCaption } from './renderers/domrenderer/shared/types';
6
6
  import type { Node, PartialNode, PartialRelationship, Relationship } from './types/graph-element';
7
7
  import { CompatibilityError } from './utils/errors';
8
8
  import type { Point } from './utils/geometry';
@@ -38,11 +38,6 @@ interface NvlMouseEvent extends MouseEvent {
38
38
  */
39
39
  declare class NVL {
40
40
  #private;
41
- /**
42
- * @internal
43
- * @hidden
44
- */
45
- readonly performance: any;
46
41
  /**
47
42
  * Creates a new NVL instance.
48
43
  * @param frame - The DOM element to display the graph in.
@@ -274,6 +269,17 @@ declare class NVL {
274
269
  filename?: string;
275
270
  backgroundColor?: string;
276
271
  }): void;
272
+ /**
273
+ * Saves the entire graph visualization as an SVG file to the client.
274
+ * @param options - Options for the SVG export
275
+ * @param options.filename - The filename of the SVG file.
276
+ * @param options.backgroundColor - The background color of the SVG file.
277
+ * @experimental
278
+ */
279
+ saveToSvg(options?: {
280
+ filename?: string;
281
+ backgroundColor?: string;
282
+ }): void;
277
283
  /**
278
284
  * Returns the current view of the graph visualization canvas as a data URL.
279
285
  * @param options - The options for the image.
@@ -283,6 +289,25 @@ declare class NVL {
283
289
  getImageDataUrl(options?: {
284
290
  backgroundColor?: string;
285
291
  }): string;
292
+ /**
293
+ * Returns the entire graph visualization as an SVG data URL.
294
+ * @param options - Options for the SVG export
295
+ * @param options.backgroundColor - The background color of the SVG (defaults to transparent).
296
+ * @returns A Promise resolving to a data URL string representing the graph as SVG (data:image/svg+xml;...)
297
+ * @experimental
298
+ *
299
+ * @example
300
+ * ```typescript
301
+ * const svgDataUrl = await nvl.getSvgDataUrl({ backgroundColor: '#ffffff' })
302
+ * const img = document.createElement('img')
303
+ * img.src = svgDataUrl
304
+ * img.alt = 'Graph Visualization'
305
+ * document.body.appendChild(img)
306
+ * ```
307
+ */
308
+ getSvgDataUrl(options?: {
309
+ backgroundColor?: string;
310
+ }): Promise<string>;
286
311
  /**
287
312
  * Saves the entire graph visualization canvas as a png to the client.
288
313
  * @param {{ filename: string, backgroundColor: string }} options The filename and background color of the png.
@@ -295,6 +320,10 @@ declare class NVL {
295
320
  filename?: string;
296
321
  backgroundColor?: string;
297
322
  }): void;
323
+ getZoomLimits(): {
324
+ minZoom: number;
325
+ maxZoom: number;
326
+ };
298
327
  /**
299
328
  * Sets the zoom of the viewport to a specific value.
300
329
  * @param zoomValue - The desired zoom level.
@@ -381,6 +410,10 @@ declare class NVL {
381
410
  declare const colorMapperFunctions: {
382
411
  textColorForBackground: (color: string) => string;
383
412
  };
413
+ /**
414
+ * The different types of renderers available
415
+ */
416
+ type Renderer = Exclude<InternalRenderer, typeof SvgRendererType>;
384
417
  export default NVL;
385
- export type { NvlOptions, Renderer, Node, Relationship, PartialNode, PartialRelationship, Layout, LayoutOptions, ForceDirectedOptions, HierarchicalOptions, ExternalCallbacks, HitTargets, HitTargetNode, HitTargetRelationship, Point, NvlMouseEvent, ZoomOptions, StyledCaption, WebGLRendererType, CanvasRendererType };
386
- export { NVL, colorMapperFunctions, CompatibilityError, ForceDirectedLayoutType, HierarchicalLayoutType, GridLayoutType, FreeLayoutType, d3ForceLayoutType, drawCircleBand, nvlResultTransformer, getZoomTargetForNodePositions };
418
+ export type { NvlOptions, Renderer, Node, Relationship, PartialNode, PartialRelationship, Layout, LayoutOptions, ForceDirectedOptions, HierarchicalOptions, CircularOptions, ExternalCallbacks, HitTargets, HitTargetNode, HitTargetRelationship, Point, NvlMouseEvent, ZoomOptions, StyledCaption, WebGLRendererType, CanvasRendererType };
419
+ export { NVL, colorMapperFunctions, CompatibilityError, ForceDirectedLayoutType, HierarchicalLayoutType, GridLayoutType, FreeLayoutType, d3ForceLayoutType, CircularLayoutType, drawCircleBand, nvlResultTransformer, getZoomTargetForNodePositions };
@@ -0,0 +1,18 @@
1
+ import type { CircularOptions, LayoutOptions, NvlState } from '../../modules/state/types';
2
+ import AnimatedLayout from '../animatedlayout/AnimatedLayout';
3
+ type CircularLayoutConfig = {
4
+ state: NvlState;
5
+ } & CircularOptions;
6
+ export declare class CircularLayout extends AnimatedLayout {
7
+ private stateDisposers;
8
+ private sortFunction;
9
+ constructor(config: CircularLayoutConfig);
10
+ setOptions(options?: LayoutOptions): void;
11
+ update(refreshPositions?: boolean): void;
12
+ getShouldUpdate(): boolean;
13
+ getComputing(): boolean;
14
+ private layout;
15
+ terminateUpdate(): void;
16
+ destroy(): void;
17
+ }
18
+ export {};
@@ -1,33 +1,33 @@
1
- export class d3ForceLayout {
2
- constructor(config: any);
3
- state: any;
4
- d3Nodes: {};
5
- d3RelList: {};
1
+ import type { Simulation, SimulationLinkDatum, SimulationNodeDatum } from 'd3-force';
2
+ import type { NvlState } from '../../modules/state/types';
3
+ import type { Node, Relationship } from '../../types/graph-element';
4
+ import type { Point } from '../../utils/geometry';
5
+ import type { D3Node } from './types';
6
+ export declare class D3ForceLayout {
7
+ state: NvlState;
8
+ d3Nodes: Record<string, D3Node>;
9
+ d3RelList: SimulationLinkDatum<D3Node>[];
6
10
  computing: boolean;
7
- center: {
8
- x: number;
9
- y: number;
10
- };
11
- nodeRelCount: any[];
12
- simulation: import("d3-force").Simulation<import("d3-force").SimulationNodeDatum, undefined>;
11
+ center: Point;
12
+ nodeRelCount: number[];
13
+ simulation: Simulation<SimulationNodeDatum, undefined>;
13
14
  simulationStopped: boolean;
14
15
  shouldUpdate: boolean;
15
16
  shouldReheatNodes: boolean;
16
17
  shouldCountNodeRels: boolean;
17
- stateDisposers: any[];
18
+ stateDisposers: (() => void)[];
19
+ constructor(config: {
20
+ state: NvlState;
21
+ });
18
22
  setOptions(options: any): void;
19
- updateNodes(positionList: any): void;
23
+ updateNodes(positionList: D3Node[]): void;
20
24
  update(refreshPositions?: boolean): void;
21
- layout(_nodes: any, _rels: any, firstTimeAddingNodes: any): void;
22
- getNodePositions(nodeList: any): {
23
- id: any;
24
- x: any;
25
- y: any;
26
- }[];
25
+ layout(_nodes: Node[], _rels: Relationship[], firstTimeAddingNodes: boolean): void;
26
+ getNodePositions(nodeList: D3Node[]): any[];
27
27
  getShouldUpdate(): boolean;
28
28
  getComputing(): boolean;
29
29
  terminateUpdate(): void;
30
30
  destroy(): void;
31
- setAlpha(alpha: any): void;
31
+ setAlpha(alpha: number): void;
32
32
  countNodeRels(): any[];
33
33
  }
@@ -1,9 +1,8 @@
1
- export type D3Node = {
2
- x: number | undefined;
3
- y: number | undefined;
1
+ import type { Node } from '../../types/graph-element';
2
+ export type D3Node = Node & {
4
3
  vx?: number;
5
4
  vy?: number;
6
- fx?: number | null;
7
- fy?: number | null;
8
- size?: number;
5
+ fx?: number;
6
+ fy?: number;
7
+ index?: number;
9
8
  };
@@ -16,7 +16,7 @@ export declare class ForceCytoLayout {
16
16
  getShouldUpdate(): boolean;
17
17
  getComputing(): boolean;
18
18
  updateNodes(positionList: any): void;
19
- getNodePositions(data: any): import("../../types/graph-element").Node[];
19
+ getNodePositions(data: any): import("../..").Node[];
20
20
  terminateUpdate(): void;
21
21
  destroy(): void;
22
22
  }
@@ -52,9 +52,13 @@ export declare class PhysLayout {
52
52
  private pinTexture;
53
53
  private addedNodes;
54
54
  private updateTexture;
55
- enableVerlet: boolean;
55
+ private vaoExt;
56
+ private physVao;
57
+ private physSmallVao;
58
+ private updateVao;
59
+ private workaroundVao;
56
60
  constructor(config: ForceDirectedOptions & {
57
- webGLContext: WebGL2RenderingContext;
61
+ webGLContext: WebGLRenderingContext;
58
62
  state: NvlState;
59
63
  });
60
64
  /**
@@ -71,7 +75,7 @@ export declare class PhysLayout {
71
75
  setData(data: {
72
76
  nodes: Node[];
73
77
  rels: Relationship[];
74
- }): any;
78
+ }): import("./solarmerger/types").CoarsenedGraph;
75
79
  /**
76
80
  * Updates the node's positions for the next step in the physics layout iterations if the layout needs to update
77
81
  * @param refreshPositions whether the entire layout should be reheated
@@ -130,7 +134,7 @@ export declare class PhysLayout {
130
134
  }, relationshipChanges: {
131
135
  adds: Record<string, Relationship>;
132
136
  removes: Record<string, Relationship>;
133
- }): any;
137
+ }): import("./solarmerger/types").CoarsenedGraph;
134
138
  /**
135
139
  * Destroys the class and all buffers and textures.
136
140
  */
@@ -1,2 +1,2 @@
1
- declare const _default: "precision mediump float;\n\nuniform sampler2D u_physData;\nuniform sampler2D u_connections;\nuniform sampler2D u_connectionOffsets;\nuniform sampler2D u_pinnedNodes;\nuniform sampler2D u_sizeTexture;\nuniform float u_baseLength;\nuniform float u_curIteration;\nuniform float u_iterationMultiplier;\nuniform vec2 u_gravityCenter;\nuniform float u_numNodes;\nuniform float u_gravity;\n\nuniform sampler2D u_clusterData;\nuniform sampler2D u_prevForce;\nuniform float u_collisionMultiplier;\n\nfloat TIMESTEP = 1.0 / 30.0;\nfloat VELOCITYDECAY = 0.6;\nfloat accLimitLow = 500000.0;\nfloat accLimitHigh = 750000.0;\nfloat accLimitPosHigh = 10000000.0;\n\nconst float denseNodeThreshold = 1000.0;\nconst float MIN_DISTANCE = 0.00000001;\nconst float MAX_DISTANCE = 1000000000.0;\nconst float MAX_ACCELERATION = 500000.0;\n\nvec4 getTextureData(sampler2D texture, float index, float base) {\n float x = mod(index, base);\n float y = (index - x) / base;\n return texture2D(texture, vec2(x + 0.5, y + 0.5) / base);\n}\n\nbool isNan(float val) {\n return (val < 0.0 || 0.0 < val || val == 0.0) ? false : true;\n}\n\nconst float BIG_NUMBER = 999999999999999999.0;\nbool isInf(float val) {\n return val > BIG_NUMBER || val < -BIG_NUMBER;\n}\n\nvec2 getDelta(vec2 v1, vec2 v2) {\n vec2 delta = v1 - v2;\n float dist = length(delta);\n if (dist < MIN_DISTANCE || isNan(dist)) {\n return vec2(MIN_DISTANCE, MIN_DISTANCE);\n }\n if (dist > MAX_DISTANCE) {\n vec2 normDelta = delta / dist;\n return normDelta * MAX_DISTANCE;\n }\n return delta;\n}\n\nvec4 getOtherNodePosition(float i) {\n return getTextureData(u_physData, i, 256.0);\n}\n\nfloat getCombinedNodeSize(float i, float nodeSize) {\n float otherNodeSize = getTextureData(u_sizeTexture, i, 256.0).a;\n return nodeSize + otherNodeSize;\n}\n\nvec2 getSpringForce(float curConnection, float numConnections, float springFScale, vec4 myPosition, float i) {\n float curSpring = getTextureData(u_connections, curConnection + i, 4096.0).a;\n\n vec4 otherPosition = getTextureData(u_physData, curSpring, 256.0);\n float otherDataPosition = getTextureData(u_connectionOffsets, curSpring, 256.0).a;\n float avgDegree;\n#if INTEL_WORKAROUND\n avgDegree = max(numConnections, 4.0);\n#else\n float otherNumConnections = getTextureData(u_connections, otherDataPosition, 4096.0).a;\n avgDegree = max((otherNumConnections + numConnections * 3.0) / 4.0, 4.0);\n#endif\n\n vec2 delta = getDelta(myPosition.xy, otherPosition.xy);\n float dist = length(delta);\n\n float F = (dist * dist * springFScale) / (u_baseLength * avgDegree);\n if (u_collisionMultiplier > 0.0) {\n F *= u_collisionMultiplier;\n }\n return (-delta / dist) * F;\n}\n\nvec2 getCollisionForce(float combinedNodeSize, float dist, float fScale, vec2 delta) {\n float collisionForce = ((combinedNodeSize - dist) / dist);\n if (u_collisionMultiplier > 0.0) {\n collisionForce *= u_collisionMultiplier;\n }\n return (delta * collisionForce * fScale * combinedNodeSize) / (combinedNodeSize + 1.0);\n}\n\nvec2 getRepulsionForce(float dist, float fScale, vec2 delta) {\n float F = (u_baseLength * u_baseLength * (fScale / 1.5)) / dist;\n return (delta / dist) * F * 0.05;\n}\n\nvoid main(void) {\n float textureSide = 256.0; //#TEXTURE_SIDE#;\n float index = (gl_FragCoord.x - 0.5) + (gl_FragCoord.y - 0.5) * textureSide;\n\n if (index >= u_numNodes) {\n discard;\n }\n\n vec4 clusterData = getTextureData(u_clusterData, index, 256.0);\n\n float clusterIndex = clusterData.x;\n float clusterStartIndex = clusterData.y;\n float clusterSize = clusterData.z;\n float clusterWeight = clusterData.w;\n\n vec4 myPosition = getTextureData(u_physData, index, 256.0);\n vec4 previousForce = getTextureData(u_prevForce, clusterIndex, 256.0);\n\n vec2 acceleration = previousForce.xy;\n\n float isPinned = getTextureData(u_pinnedNodes, index, 256.0).a;\n float nodeSize = getTextureData(u_sizeTexture, index, 256.0).a;\n\n if (isPinned > 0.5) {\n gl_FragColor = vec4(myPosition.xy, 0.0, 0.0);\n return;\n }\n\n float curConnection = getTextureData(u_connectionOffsets, index, 256.0).a;\n float numConnections = getTextureData(u_connections, curConnection, 4096.0).a;\n\n float fScale = 1.0 + sqrt(u_iterationMultiplier);\n float springFScale = fScale;\n\n if (numConnections > denseNodeThreshold) {\n springFScale = sqrt(fScale);\n }\n\n float numOfRels = 0.0;\n\n // Springs\n for (float i = 1.0; i <= 256.0 * 256.0; i++) {\n if (numOfRels >= numConnections) {\n break;\n }\n acceleration += getSpringForce(curConnection, numConnections, springFScale, myPosition, i);\n numOfRels += 1.0;\n }\n\n // Repulsion && collision detection\n if (u_collisionMultiplier > 0.0) {\n float number_of_collisions = 0.0;\n for (float i = 0.0; i < 256.0 * 256.0; i++) {\n if (i >= u_numNodes) {\n break;\n }\n\n if (i == index) {\n continue;\n }\n\n vec4 otherPosition = getOtherNodePosition(i);\n vec2 delta = getDelta(myPosition.xy, otherPosition.xy);\n float dist = length(delta);\n float combinedNodeSize = getCombinedNodeSize(i, nodeSize) * 2.0;\n\n if (dist < combinedNodeSize && number_of_collisions < 40.0) {\n number_of_collisions++;\n acceleration += getCollisionForce(combinedNodeSize, dist, fScale, delta);\n }\n\n if (i >= clusterStartIndex && i < clusterStartIndex + clusterSize) {\n acceleration += getRepulsionForce(dist, fScale, delta);\n }\n }\n } else {\n for (float i = 0.0; i < 256.0 * 256.0; i++) {\n if (i >= clusterStartIndex + clusterSize || i >= u_numNodes) {\n break;\n }\n\n if (i < clusterStartIndex || i == index) {\n continue;\n }\n\n vec4 otherPosition = getOtherNodePosition(i);\n vec2 delta = getDelta(myPosition.xy, otherPosition.xy);\n float dist = length(delta);\n float combinedNodeSize = getCombinedNodeSize(i, nodeSize);\n\n if (dist < combinedNodeSize) {\n acceleration += getCollisionForce(combinedNodeSize, dist, fScale, delta);\n }\n\n acceleration += getRepulsionForce(dist, fScale, delta);\n }\n }\n\n // Gravity\n vec2 delta = getDelta(u_gravityCenter, myPosition.xy);\n float dist = length(delta);\n\n vec2 grav = (delta / dist) * u_gravity * fScale;\n acceleration += grav * smoothstep(0.0, 500.0, dist);\n\n float accMagnitude = length(acceleration);\n acceleration *= min(MAX_ACCELERATION, accMagnitude) / accMagnitude;\n\n float iterationFrictionThreshold = 1000.0;\n\n if (u_curIteration > iterationFrictionThreshold) {\n float friction = 1.0 + pow((u_curIteration - iterationFrictionThreshold), 2.0) / 100.0;\n acceleration *= 1.0 / friction;\n }\n\n if (u_curIteration == 0.0) {\n gl_FragColor = vec4(myPosition.xy, acceleration * TIMESTEP * 0.5);\n } else {\n myPosition.zw = myPosition.zw * VELOCITYDECAY;\n gl_FragColor = vec4(myPosition.xy + myPosition.zw * TIMESTEP, myPosition.zw + acceleration * TIMESTEP);\n }\n}";
1
+ declare const _default: "precision mediump float;\n\nuniform sampler2D u_physData;\nuniform sampler2D u_connections;\nuniform sampler2D u_connectionOffsets;\nuniform sampler2D u_pinnedNodes;\nuniform sampler2D u_sizeTexture;\nuniform float u_baseLength;\nuniform float u_curIteration;\nuniform float u_iterationMultiplier;\nuniform vec2 u_gravityCenter;\nuniform float u_numNodes;\nuniform float u_gravity;\n\nuniform sampler2D u_clusterData;\nuniform sampler2D u_prevForce;\nuniform float u_collisionMultiplier;\n\n\nfloat DAMP = 0.6;\nfloat COOL = 0.99998;\nfloat TEMP = max(0.02, pow(COOL, u_curIteration));\nfloat TIMESTEP = 1.0 / 30.0;\nfloat VELOCITYDECAY = 0.6;\nfloat accLimitLow = 500000.0;\nfloat accLimitHigh = 750000.0;\nfloat accLimitPosHigh = 10000000.0;\n\nconst float denseNodeThreshold = 1000.0;\nconst float MIN_DISTANCE = 0.00000001;\nconst float MAX_DISTANCE = 1000000000.0;\nconst float MAX_ACCELERATION = 50000.0;\n\nvec4 getTextureData(sampler2D texture, float index, float base) {\n float x = mod(index, base);\n float y = (index - x) / base;\n return texture2D(texture, vec2(x + 0.5, y + 0.5) / base);\n}\n\nbool isNan(float val) {\n return (val < 0.0 || 0.0 < val || val == 0.0) ? false : true;\n}\n\nconst float BIG_NUMBER = 999999999999999999.0;\nbool isInf(float val) {\n return val > BIG_NUMBER || val < -BIG_NUMBER;\n}\n\nvec2 getDelta(vec2 v1, vec2 v2) {\n vec2 delta = v1 - v2;\n float dist = length(delta);\n if (dist < MIN_DISTANCE || isNan(dist)) {\n return vec2(MIN_DISTANCE, MIN_DISTANCE);\n }\n if (dist > MAX_DISTANCE) {\n vec2 normDelta = delta / dist;\n return normDelta * MAX_DISTANCE;\n }\n return delta;\n}\n\nvec4 getOtherNodePosition(float i) {\n return getTextureData(u_physData, i, 256.0);\n}\n\nfloat getCombinedNodeSize(float i, float nodeSize) {\n float otherNodeSize = getTextureData(u_sizeTexture, i, 256.0).a;\n return nodeSize + otherNodeSize;\n}\n\nvec2 getSpringForce(float curConnection, float numConnections, float springFScale, vec4 myPosition, float i) {\n float curSpring = getTextureData(u_connections, curConnection + i, 4096.0).a;\n\n vec4 otherPosition = getTextureData(u_physData, curSpring, 256.0);\n float otherDataPosition = getTextureData(u_connectionOffsets, curSpring, 256.0).a;\n float avgDegree;\n#if INTEL_WORKAROUND\n avgDegree = max(numConnections, 4.0);\n#else\n float otherNumConnections = getTextureData(u_connections, otherDataPosition, 4096.0).a;\n avgDegree = max((otherNumConnections + numConnections * 3.0) / 4.0, 4.0);\n#endif\n\n vec2 delta = getDelta(myPosition.xy, otherPosition.xy);\n float dist = length(delta);\n\n float F = (dist * dist * springFScale) / (u_baseLength * avgDegree);\n if (u_collisionMultiplier > 0.0) {\n F *= u_collisionMultiplier;\n }\n return (-delta / dist) * F;\n}\n\nvec2 getCollisionForce(float combinedNodeSize, float dist, float fScale, vec2 delta) {\n float collisionForce = (combinedNodeSize - dist) / (dist);\n if (u_collisionMultiplier > 0.0) {\n collisionForce *= u_collisionMultiplier;\n }\n return (delta * collisionForce * fScale * combinedNodeSize) / (combinedNodeSize + 1.0);\n}\n\nvec2 getRepulsionForce(float dist, float fScale, vec2 delta) {\n float F = (u_baseLength * u_baseLength * fScale) / (dist);\n return (delta / dist) * F * 0.05;\n}\n\nvoid main(void) {\n float textureSide = 256.0; //#TEXTURE_SIDE#;\n float index = (gl_FragCoord.x - 0.5) + (gl_FragCoord.y - 0.5) * textureSide;\n\n if (index >= u_numNodes) {\n discard;\n }\n\n vec4 clusterData = getTextureData(u_clusterData, index, 256.0);\n\n float clusterIndex = clusterData.x;\n float clusterStartIndex = clusterData.y;\n float clusterSize = clusterData.z;\n float clusterWeight = clusterData.w;\n\n vec4 myPosition = getTextureData(u_physData, index, 256.0);\n vec4 previousForce = getTextureData(u_prevForce, clusterIndex, 256.0);\n\n vec2 acceleration = previousForce.xy;\n\n float isPinned = getTextureData(u_pinnedNodes, index, 256.0).a;\n float nodeSize = getTextureData(u_sizeTexture, index, 256.0).a;\n\n if (isPinned > 0.5) {\n gl_FragColor = vec4(myPosition.xy, 0.0, 0.0);\n return;\n }\n\n float curConnection = getTextureData(u_connectionOffsets, index, 256.0).a;\n float numConnections = getTextureData(u_connections, curConnection, 4096.0).a;\n\n float fScale = 1.0 + sqrt(u_iterationMultiplier);\n float springFScale = fScale;\n\n if (numConnections > denseNodeThreshold) {\n springFScale = sqrt(fScale);\n }\n\n float numOfRels = 0.0;\n\n // Springs\n for (float i = 1.0; i <= 256.0 * 256.0; i++) {\n if (numOfRels >= numConnections) {\n break;\n }\n acceleration += getSpringForce(curConnection, numConnections, springFScale, myPosition, i);\n numOfRels += 1.0;\n }\n\n // Repulsion && collision detection\n if (u_collisionMultiplier > 0.0) {\n float number_of_collisions = 0.0;\n for (float i = 0.0; i < 256.0 * 256.0; i++) {\n if (i >= u_numNodes) {\n break;\n }\n\n if (i == index) {\n continue;\n }\n\n vec4 otherPosition = getOtherNodePosition(i);\n vec2 delta = getDelta(myPosition.xy, otherPosition.xy);\n float dist = length(delta);\n float combinedNodeSize = getCombinedNodeSize(i, nodeSize) * 2.0;\n\n if (dist < combinedNodeSize && number_of_collisions < 40.0) {\n number_of_collisions++;\n acceleration += getCollisionForce(combinedNodeSize, dist, fScale, delta);\n }\n\n if (i >= clusterStartIndex && i < clusterStartIndex + clusterSize) {\n acceleration += getRepulsionForce(dist, fScale, delta);\n }\n }\n } else {\n for (float i = 0.0; i < 256.0 * 256.0; i++) {\n if (i >= clusterStartIndex + clusterSize || i >= u_numNodes) {\n break;\n }\n\n if (i < clusterStartIndex || i == index) {\n continue;\n }\n\n vec4 otherPosition = getOtherNodePosition(i);\n vec2 delta = getDelta(myPosition.xy, otherPosition.xy);\n float dist = length(delta);\n float combinedNodeSize = getCombinedNodeSize(i, nodeSize);\n\n if (dist < combinedNodeSize) {\n acceleration += getCollisionForce(combinedNodeSize, dist, fScale, delta);\n }\n\n acceleration += getRepulsionForce(dist, fScale, delta);\n }\n }\n\n // Gravity\n vec2 delta = getDelta(u_gravityCenter, myPosition.xy);\n float dist = length(delta);\n\n vec2 grav = (delta / dist) * u_gravity * fScale * (dist / 1000.0);\n acceleration += grav;\n\n float accMagnitude = length(acceleration);\n acceleration *= min(MAX_ACCELERATION, accMagnitude) / accMagnitude;\n\n float iterationFrictionThreshold = 1000.0;\n\n if (u_curIteration > iterationFrictionThreshold) {\n float friction = 1.0 + pow((u_curIteration - iterationFrictionThreshold), 2.0) / 100.0;\n acceleration *= 1.0 / friction;\n }\n\n if (u_curIteration == 0.0) {\n gl_FragColor = vec4(myPosition.xy, myPosition.zw);\n } else {\n vec2 prevVelocity = myPosition.zw;\n vec2 currentPos = myPosition.xy;\n vec2 prevPos = currentPos - prevVelocity;\n\n vec2 newPos = currentPos + TEMP * ( DAMP * (prevVelocity) + acceleration * TIMESTEP * TIMESTEP);\n vec2 newVelocity = newPos - currentPos;\n gl_FragColor = vec4(newPos, newVelocity);\n }\n}";
2
2
  export default _default;
@@ -1,2 +1,2 @@
1
- declare const _default: "precision mediump float;\nuniform sampler2D u_physData;\nuniform sampler2D u_clusterData;\nuniform sampler2D u_finestIndexes;\nuniform sampler2D u_prevForce;\n\nuniform float u_baseLength;\nuniform float u_numNodes;\nuniform float u_iterationMultiplier;\nuniform float u_isTopLevel;\n\nfloat TIMESTEP = 1.0 / 30.0;\nfloat VELOCITYDECAY = 0.6;\n\nvec4 getTextureData(sampler2D texture, float index, float base) {\n float x = mod(index, base);\n float y = (index - x) / base;\n return texture2D(texture, vec2(x + 0.5, y + 0.5) / base);\n}\n\nfloat getLogClusterWeight(float value) {\n return value / max(log(value), 1.0);\n}\n\nvoid main(void) {\n float index = (gl_FragCoord.x - 0.5) + (gl_FragCoord.y - 0.5) * 256.0;\n\n if (index >= u_numNodes) {\n discard;\n }\n\n vec4 clusterData = getTextureData(u_clusterData, index, 256.0);\n\n float clusterIndex = clusterData.x;\n float clusterStartIndex = clusterData.y;\n float clusterSize = clusterData.z;\n\n float finestIndex = getTextureData(u_finestIndexes, index, 256.0).a;\n vec4 myPosition = getTextureData(u_physData, finestIndex, 256.0);\n vec4 previousForce = getTextureData(u_prevForce, clusterIndex, 256.0);\n float fScale = 1.0 + sqrt(u_iterationMultiplier);\n\n vec2 acceleration = previousForce.xy;\n\n // Repulsion & Collision Detection\n for (float i = 0.0; i < 256.0 * 256.0; i++) {\n if (i >= clusterStartIndex + clusterSize || i >= u_numNodes) {\n break;\n }\n if (i < clusterStartIndex || i == index) {\n continue;\n }\n\n vec4 otherClusterData = getTextureData(u_clusterData, i, 256.0);\n float otherClusterWeight = getLogClusterWeight(otherClusterData.w);\n\n float otherFinestIndex = getTextureData(u_finestIndexes, i, 256.0).a;\n vec4 otherPosition = getTextureData(u_physData, otherFinestIndex, 256.0);\n\n vec2 delta = myPosition.xy - otherPosition.xy;\n float dist = max(length(delta), 0.0000001);\n float maxDist = 25.0;\n float repulsionForceScale = 0.1;\n\n float F = ((u_baseLength * u_baseLength) * (fScale / 1.5)) / dist;\n\n if (u_isTopLevel == 1.0) {\n repulsionForceScale = 0.3;\n }\n\n acceleration += ((delta / dist) * F) * repulsionForceScale * otherClusterWeight;\n\n if (dist < maxDist) {\n float collide = (maxDist - dist) / dist;\n acceleration += delta * collide * fScale * maxDist / (maxDist + 1.0);\n }\n }\n\n gl_FragColor = vec4(acceleration, vec2(finestIndex, 0));\n}";
1
+ declare const _default: "precision mediump float;\nuniform sampler2D u_physData;\nuniform sampler2D u_clusterData;\nuniform sampler2D u_finestIndexes;\nuniform sampler2D u_prevForce;\n\nuniform float u_baseLength;\nuniform float u_numNodes;\nuniform float u_iterationMultiplier;\nuniform float u_isTopLevel;\n\nfloat PI = 3.1415926535897932384626433832795;\nfloat TIMESTEP = 1.0 / 30.0;\nfloat VELOCITYDECAY = 1.0;\n\nvec4 getTextureData(sampler2D texture, float index, float base) {\n float x = mod(index, base);\n float y = (index - x) / base;\n return texture2D(texture, vec2(x + 0.5, y + 0.5) / base);\n}\n\nfloat getSquaredLogClusterWeight(float value) {\n return pow(log(value), 2.0);\n}\n\nvoid main(void) {\n float index = (gl_FragCoord.x - 0.5) + (gl_FragCoord.y - 0.5) * 256.0;\n\n if (index >= u_numNodes) {\n discard;\n }\n\n vec4 clusterData = getTextureData(u_clusterData, index, 256.0);\n\n float clusterIndex = clusterData.x;\n float clusterStartIndex = clusterData.y;\n float clusterSize = clusterData.z;\n float clusterArea = pow(clusterSize + u_baseLength * 2.0, 2.0);\n\n float finestIndex = getTextureData(u_finestIndexes, index, 256.0).a;\n vec4 myPosition = getTextureData(u_physData, finestIndex, 256.0);\n vec4 previousForce = getTextureData(u_prevForce, clusterIndex, 256.0);\n float fScale = 1.0 + sqrt(u_iterationMultiplier);\n\n vec2 acceleration = previousForce.xy;\n\n // Repulsion & Collision Detection\n for (float i = 0.0; i < 256.0 * 256.0; i++) {\n if (i >= clusterStartIndex + clusterSize || i >= u_numNodes) {\n break;\n }\n if (i < clusterStartIndex || i == index) {\n continue;\n }\n\n vec4 otherClusterData = getTextureData(u_clusterData, i, 256.0);\n float otherClusterWeight = getSquaredLogClusterWeight(otherClusterData.w);\n\n float otherFinestIndex = getTextureData(u_finestIndexes, i, 256.0).a;\n vec4 otherPosition = getTextureData(u_physData, otherFinestIndex, 256.0);\n\n vec2 delta = myPosition.xy - otherPosition.xy;\n float dist = max(length(delta), 0.0000001);\n float maxDist = 25.0;\n float repulsionForceScale = 0.1;\n\n float F = (clusterArea * fScale) / (dist * dist);\n\n if (u_isTopLevel == 1.0) {\n repulsionForceScale = 0.2;\n }\n\n acceleration += ((delta / sqrt(dist)) * F) * repulsionForceScale * otherClusterWeight;\n\n if (dist < maxDist) {\n float collide = (maxDist - dist) / (dist * dist);\n acceleration += delta * collide * fScale * maxDist / (maxDist + 1.0);\n }\n }\n\n gl_FragColor = vec4(acceleration, vec2(finestIndex, 0));\n}";
2
2
  export default _default;
@@ -1,43 +1,21 @@
1
+ import type { Node, Relationship } from '../../../../types/graph-element';
2
+ import type { CoarsenedGraph, SolarRelationship } from './types';
1
3
  export default class SolarMerger {
2
- constructor(graph: any, nodeIdToIndex: any);
3
4
  graph: {
4
- nodes: any[];
5
- relationships: any[];
6
- idToRel: {};
7
- };
8
- subGraphs: any[];
9
- sunMap: {};
10
- constructGraphObjects(graph: any, nodeIdToIndex: any): {
11
- nodes: any[];
12
- relationships: any[];
13
- idToRel: {};
14
- };
15
- relIdMap: any[];
16
- coarsenTo(targetSize: any): {
17
- nodes: any[];
18
- relationships: any[];
19
- idToRel: {};
20
- };
21
- nodeSortMap: {};
22
- coarsenBy(levelToCoarsenBy: any): {
23
- nodes: any[];
24
- relationships: any[];
25
- idToRel: {};
26
- };
27
- coarsen({ nodes, relationships }: {
28
- nodes: any;
29
- relationships: any;
30
- }, firstIteration: any): {
31
- output: {
32
- nodes: {
33
- id: any;
34
- }[];
35
- relationships: any[];
36
- };
37
- sortedInput: {
38
- nodes: any[];
39
- relationships: any[];
40
- };
41
- nodeSortMap: {};
5
+ nodes: Node[];
6
+ relationships: number[][];
7
+ idToRel: Record<string, SolarRelationship>;
42
8
  };
9
+ subGraphs: CoarsenedGraph[];
10
+ sunMap: Record<string, string>;
11
+ relIdMap: string[][];
12
+ nodeSortMap?: Record<number, number>;
13
+ constructor(inputGraph: {
14
+ nodes: Node[];
15
+ rels: Relationship[];
16
+ }, nodeIdToIndex: Record<string, number>);
17
+ private constructGraphObjects;
18
+ coarsenTo(targetSize: number): CoarsenedGraph;
19
+ coarsenBy(levelToCoarsenBy: number): CoarsenedGraph;
20
+ private coarsen;
43
21
  }
@@ -0,0 +1,49 @@
1
+ import type { Node } from '../../../../types/graph-element';
2
+ export interface SolarNode extends Omit<Node, 'id' | 'size'> {
3
+ id: number;
4
+ weight?: number;
5
+ finestIndex?: number;
6
+ originalId: string;
7
+ position?: {
8
+ x: number;
9
+ y: number;
10
+ };
11
+ placement?: {
12
+ x: number;
13
+ y: number;
14
+ };
15
+ size?: number | (() => number);
16
+ }
17
+ export interface SolarRelationship {
18
+ id: string;
19
+ from: string;
20
+ to: string;
21
+ }
22
+ export interface CoarsenedGraph {
23
+ nodes: SolarNode[];
24
+ relationships: number[][];
25
+ idToRel: Record<string, SolarRelationship>;
26
+ }
27
+ export interface Sun extends SolarNode {
28
+ planets: Planet[];
29
+ size: () => number;
30
+ children: () => Planet[];
31
+ previousIndex: number;
32
+ }
33
+ export interface Planet extends SolarNode {
34
+ parent: Sun;
35
+ sunId: number;
36
+ moons: Moon[];
37
+ size: () => number;
38
+ children: () => Moon[];
39
+ }
40
+ export interface Moon extends SolarNode {
41
+ parent: Planet;
42
+ sunId: number;
43
+ size: () => number;
44
+ }
45
+ export type Celestial = Sun | Planet | Moon;
46
+ export declare const isSolarNode: (node: SolarNode | Node) => node is SolarNode;
47
+ export declare const isSun: (node: SolarNode | Celestial) => node is Sun;
48
+ export declare const isPlanet: (node: SolarNode | Celestial) => node is Planet;
49
+ export declare const isMoon: (node: SolarNode | Celestial) => node is Moon;
@@ -1,14 +1,30 @@
1
- export class GridLayout {
2
- constructor(config: any);
3
- state: any;
4
- positions: {};
5
- stateDisposers: any[];
1
+ import type { NvlState } from '../../modules/state/types';
2
+ import type { Node } from '../../types/graph-element';
3
+ import type { Point } from '../../utils/geometry';
4
+ export declare class GridLayout {
5
+ state: NvlState;
6
+ positions: Record<string, Node & Point>;
7
+ stateDisposers: (() => void)[];
6
8
  shouldUpdate: boolean;
7
- setOptions(options: any): void;
8
- updateNodes(positionList: any): void;
9
+ constructor(config: {
10
+ state: NvlState;
11
+ });
12
+ setOptions(): void;
13
+ updateNodes(positionList: {
14
+ id: string;
15
+ x: number;
16
+ y: number;
17
+ }[]): void;
9
18
  update(refreshPositions?: boolean): void;
10
- layout(mobxNodes: any, nodeIds: any, idToPosition: any, rels: any): void;
11
- getNodePositions(nodeList: any): any[];
19
+ layout(mobxNodes: any): void;
20
+ setNodePositions(idToPosition: Record<string, Node & Point>): void;
21
+ getNodePositions(nodeList: {
22
+ id: string;
23
+ }[]): {
24
+ id: string;
25
+ x: number;
26
+ y: number;
27
+ }[];
12
28
  getShouldUpdate(): boolean;
13
29
  getComputing(): boolean;
14
30
  terminateUpdate(): void;
@@ -1,4 +1,4 @@
1
- import type { Node, Relationship } from '../types/graph-element';
1
+ import { type Node, type PartialNode, type PartialRelationship, type Relationship } from '../types/graph-element';
2
2
  import '../types/nvl-window-functions';
3
3
  import type { Point } from '../utils/geometry';
4
4
  import type { ExternalCallbacks } from './ExternalCallbackHandler';
@@ -27,14 +27,17 @@ export default class NvlController {
27
27
  private readonly gridLayout;
28
28
  private readonly freeLayout;
29
29
  private readonly d3ForceLayout;
30
+ private readonly circularLayout;
30
31
  private readonly forceLayout;
31
32
  private readonly canvasRenderer;
33
+ private readonly svgRenderer;
32
34
  private readonly glCanvas;
33
35
  private canvasRect;
34
36
  private readonly glMinimapCanvas;
35
37
  private readonly c2dCanvas;
38
+ private readonly svg;
36
39
  private isInRenderSwitchAnimation;
37
- private justSwitchedRenderer;
40
+ private previousRenderer;
38
41
  private justSwitchedLayout;
39
42
  private layoutUpdating;
40
43
  private layoutComputing;
@@ -104,8 +107,8 @@ export default class NvlController {
104
107
  isDestroyed(): boolean;
105
108
  destroy(): void;
106
109
  callIfRegistered(...args: any[]): void;
107
- getCanvasRelsAt(point: Point): import("../utils/hittest").HitTargetRelationship[];
108
- getCanvasNodesAt(point: Point, hitNodeMarginWidth?: number): import("../utils/hittest").HitTargetNode[];
110
+ getCanvasRelsAt(point: Point): import("..").HitTargetRelationship[];
111
+ getCanvasNodesAt(point: Point, hitNodeMarginWidth?: number): import("..").HitTargetNode[];
109
112
  private getLayout;
110
113
  setLayout(layoutType: Layout): void;
111
114
  setLayoutOptions(options: LayoutOptions): void;
@@ -113,9 +116,22 @@ export default class NvlController {
113
116
  private initiateFileDownload;
114
117
  private updateLayoutAndPositions;
115
118
  saveToFile(options: SaveToFileOptions): void;
119
+ private createSvgString;
120
+ saveToSvg(options?: SaveToFileOptions): Promise<void>;
116
121
  getImageDataURL(options: SaveToFileOptions): string;
122
+ getSvgDataUrl(options?: SaveToFileOptions): Promise<string>;
117
123
  private prepareLargeFileForDownload;
118
124
  private createCanvasAndRenderImage;
119
125
  saveFullGraphToLargeFile(options: SaveToFileOptions): Promise<void>;
126
+ addAndUpdateElementsInGraph(nodes?: Node[] | PartialNode[], relationships?: Relationship[] | PartialRelationship[]): void;
127
+ updateElementsInGraph(nodes: Node[] | PartialNode[], relationships: Relationship[] | PartialRelationship[]): void;
128
+ /**
129
+ * Adds nodes and relationships in the current scene.
130
+ * @param {Node[]} nodes The nodes to be added.
131
+ * @param {Relationship[]} relationships The relationships to be added.
132
+ */
133
+ addElementsToGraph(nodes: Node[], relationships: Relationship[]): void;
134
+ private validateNodes;
135
+ private validateRelationships;
120
136
  }
121
137
  export {};
@@ -1,5 +1,6 @@
1
1
  import type { LogLevelDesc } from 'loglevel';
2
- import type { WaypointPath } from '../../renderers/canvasrenderer/types';
2
+ import type { WaypointPath } from '../../renderers/domrenderer/shared/types';
3
+ import type { Node } from '../../types/graph-element';
3
4
  import type { ExternalCallbacks } from '../ExternalCallbackHandler';
4
5
  import type { NodeDataSet, RelationshipDataSet } from '../dataset';
5
6
  type RingStyle = {
@@ -45,17 +46,13 @@ export interface ForceDirectedOptions {
45
46
  */
46
47
  intelWorkaround?: boolean;
47
48
  /**
49
+ * @deprecated This option will be removed in a future release. For small datasets, use the d3Force layout instead.
48
50
  * Whether to enable automatic switching to CoseBilkent layout for small graphs.
49
51
  * When enabled, small graphs will automatically use the CoseBilkent layout algorithm
50
52
  * which can provide better initial positioning for smaller datasets.
51
- */
52
- enableCytoscape?: boolean;
53
- /**
54
- * Wether to use the new physics engine instead of the legacy one.
55
53
  * @defaultValue true
56
- * @internal
57
54
  */
58
- enableVerlet?: boolean;
55
+ enableCytoscape?: boolean;
59
56
  }
60
57
  /**
61
58
  * The options for the hierarchical layout
@@ -67,6 +64,15 @@ export interface HierarchicalOptions {
67
64
  packing?: 'bin' | 'stack';
68
65
  }
69
66
  export declare const isHierarchicalLayoutOptions: (options: LayoutOptions) => options is HierarchicalOptions;
67
+ /**
68
+ * The options for the circular layout.
69
+ */
70
+ export interface CircularOptions {
71
+ /**
72
+ * Function which should return the sorted nodes.
73
+ */
74
+ sortFunction?: (nodes: Node[]) => Node[];
75
+ }
70
76
  /**
71
77
  * NVL's main force directed layout.
72
78
  */
@@ -87,6 +93,11 @@ export declare const FreeLayoutType = "free";
87
93
  * The commonly used d3-force layout.
88
94
  */
89
95
  export declare const d3ForceLayoutType = "d3Force";
96
+ /**
97
+ * A basic circular layout.
98
+ * @experimental
99
+ */
100
+ export declare const CircularLayoutType = "circular";
90
101
  /**
91
102
  * A WebGL renderer that uses the GPU for rendering.
92
103
  *
@@ -103,18 +114,26 @@ export declare const WebGLRendererType = "webgl";
103
114
  * but supports captions and arrowheads.
104
115
  */
105
116
  export declare const CanvasRendererType = "canvas";
117
+ /**
118
+ * A renderer using SVG.
119
+ *
120
+ * @experimental
121
+ * @remarks
122
+ * This renderer is experimental.
123
+ */
124
+ export declare const SvgRendererType = "svg";
106
125
  /**
107
126
  * The different types of layouts available
108
127
  */
109
- export type Layout = typeof ForceDirectedLayoutType | typeof HierarchicalLayoutType | typeof GridLayoutType | typeof FreeLayoutType | typeof d3ForceLayoutType;
128
+ export type Layout = typeof ForceDirectedLayoutType | typeof HierarchicalLayoutType | typeof GridLayoutType | typeof FreeLayoutType | typeof d3ForceLayoutType | typeof CircularLayoutType;
110
129
  /**
111
130
  * The options for the layout.
112
131
  */
113
- export type LayoutOptions = ForceDirectedOptions | HierarchicalOptions;
132
+ export type LayoutOptions = ForceDirectedOptions | HierarchicalOptions | CircularOptions;
114
133
  /**
115
134
  * The different types of renderers available
116
135
  */
117
- export type Renderer = typeof WebGLRendererType | typeof CanvasRendererType;
136
+ export type Renderer = typeof WebGLRendererType | typeof CanvasRendererType | typeof SvgRendererType;
118
137
  /** Configurations for a NVL instance */
119
138
  export interface NvlOptions {
120
139
  /**
@@ -149,7 +168,7 @@ export interface NvlOptions {
149
168
  * @remarks When using a React ref, make sure the attached element is rendered before the NVL instance is created.
150
169
  * Otherwise, the minimap will not be displayed.
151
170
  */
152
- minimapContainer?: HTMLElement;
171
+ minimapContainer?: HTMLElement | null;
153
172
  /** Configuration for the current layout */
154
173
  layoutOptions?: LayoutOptions;
155
174
  /** X-coordinate for panning of the current viewport */
@@ -160,10 +179,9 @@ export interface NvlOptions {
160
179
  initialZoom?: number;
161
180
  /**
162
181
  * What renderer to use
163
- * Possible values are 'webgl' or 'canvas'
164
- * @defaultValue 'webgl'
182
+ * @defaultValue 'canvas'
165
183
  * WebGL renderer uses GPU and has better performance.
166
- * Captions and arrowheads are only displayed when using the canvas renderer.
184
+ * Captions and arrowheads are only displayed when using the canvas or svg renderer.
167
185
  */
168
186
  renderer?: Renderer;
169
187
  /**
@@ -258,7 +276,6 @@ export interface NvlState {
258
276
  fitNodeIds: string[];
259
277
  resetZoom: boolean;
260
278
  forceWebGL: boolean;
261
- webGLVisible: boolean;
262
279
  renderer: Renderer;
263
280
  disableWebGL: boolean;
264
281
  disableWebWorkers: boolean;
@@ -1,4 +1,4 @@
1
- import type { StyledCaption } from '../../renderers/canvasrenderer/types';
1
+ import type { StyledCaption } from '../../renderers/domrenderer/shared/types';
2
2
  import type { Node, Relationship } from '../../types/graph-element';
3
3
  import type { NvlOptions } from './types';
4
4
  /**
@@ -6,7 +6,7 @@ import type { NvlOptions } from './types';
6
6
  * If both caption and captions are provided, captions takes precedence.
7
7
  */
8
8
  export declare const processCaptions: (item: Partial<Node | Relationship>) => StyledCaption[];
9
- export declare const processColorStyles: (styling: NvlOptions['styling']) => {
9
+ export declare const processColorStyles: (styling: NvlOptions["styling"]) => {
10
10
  nodeBorderStyles: {
11
11
  default: {
12
12
  rings?: {