@neo4j-nvl/base 1.2.2 → 2.0.0-2b04269b

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 (81) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/README.md +8 -0
  3. package/dist/base.mjs +39758 -2
  4. package/dist/types/index.d.ts +21 -20
  5. package/dist/types/layouts/animatedlayout/AnimatedLayout.d.ts +2 -2
  6. package/dist/types/layouts/d3forcelayout/constants.d.ts +0 -1
  7. package/dist/types/layouts/d3forcelayout/d3ForceLayout.d.ts +3 -3
  8. package/dist/types/layouts/forcedirectedlayout/PhysLayout.d.ts +275 -0
  9. package/dist/types/layouts/forcedirectedlayout/clustering/ClusterByMerger.d.ts +62 -0
  10. package/dist/types/layouts/forcedirectedlayout/clustering/SolarMerger.d.ts +56 -0
  11. package/dist/types/layouts/forcedirectedlayout/clustering/clustering-utils.d.ts +143 -0
  12. package/dist/types/layouts/forcedirectedlayout/{physlayout/solarmerger → clustering}/types.d.ts +11 -1
  13. package/dist/types/layouts/forcedirectedlayout/shaders/multilevel-fragment.d.ts +2 -0
  14. package/dist/types/layouts/forcedirectedlayout/shaders/multilevel-repulsive-fragment.d.ts +2 -0
  15. package/dist/types/layouts/forcedirectedlayout/shaders/multilevel-update-fragment.d.ts +2 -0
  16. package/dist/types/layouts/forcedirectedlayout/shaders/sim-vertex.d.ts +2 -0
  17. package/dist/types/layouts/freeLayout/FreeLayout.d.ts +2 -4
  18. package/dist/types/layouts/gridLayout/GridLayout.d.ts +2 -6
  19. package/dist/types/layouts/hierarchicallayout/HierarchicalLayout.d.ts +5 -0
  20. package/dist/types/modules/ExternalCallbackHandler.d.ts +4 -10
  21. package/dist/types/modules/NvlController.d.ts +87 -7
  22. package/dist/types/modules/Shader.d.ts +1 -1
  23. package/dist/types/modules/dataset.d.ts +4 -2
  24. package/dist/types/modules/state/types.d.ts +114 -23
  25. package/dist/types/renderers/ClusterOverlay.d.ts +73 -0
  26. package/dist/types/renderers/ClusterOverlay.test.d.ts +1 -0
  27. package/dist/types/renderers/domrenderer/canvasrenderer/CanvasRenderer.d.ts +1 -1
  28. package/dist/types/renderers/domrenderer/shared/ImageCache.d.ts +1 -0
  29. package/dist/types/renderers/domrenderer/shared/types.d.ts +1 -2
  30. package/dist/types/renderers/webglrenderer/Controller.d.ts +27 -6
  31. package/dist/types/renderers/webglrenderer/IconLayerRegistry.d.ts +14 -0
  32. package/dist/types/renderers/webglrenderer/IconLayerRegistry.test.d.ts +1 -0
  33. package/dist/types/renderers/webglrenderer/Renderer.d.ts +43 -3
  34. package/dist/types/renderers/webglrenderer/node-animation-fragment.d.ts +1 -1
  35. package/dist/types/renderers/webglrenderer/node-animation-vertex.d.ts +1 -1
  36. package/dist/types/renderers/webglrenderer/node-fragment-point.d.ts +1 -1
  37. package/dist/types/renderers/webglrenderer/node-vertex-point.d.ts +1 -1
  38. package/dist/types/renderers/webglrenderer/rel-fragment-line.d.ts +1 -1
  39. package/dist/types/renderers/webglrenderer/rel-glsl-utils.d.ts +1 -0
  40. package/dist/types/renderers/webglrenderer/rel-vertex-arrow.d.ts +2 -0
  41. package/dist/types/renderers/webglrenderer/rel-vertex-line.d.ts +1 -1
  42. package/dist/types/renderers/webglrenderer/viewport-box-fragment.d.ts +1 -1
  43. package/dist/types/renderers/webglrenderer/viewport-box-vertex.d.ts +1 -1
  44. package/dist/types/types/graph-element.d.ts +9 -1
  45. package/dist/types/types/nvl-window-functions.d.ts +2 -2
  46. package/dist/types/utils/canvasManagement.d.ts +7 -1
  47. package/dist/types/utils/clusterGeometry.d.ts +14 -0
  48. package/dist/types/utils/clusterGeometry.test.d.ts +1 -0
  49. package/dist/types/utils/clusterHitRegions.d.ts +42 -0
  50. package/dist/types/utils/clusterHitRegions.test.d.ts +1 -0
  51. package/dist/types/utils/constants.d.ts +6 -0
  52. package/dist/types/utils/geometry.d.ts +44 -1
  53. package/dist/types/utils/{hittest.d.ts → hitTest.d.ts} +30 -4
  54. package/dist/types/utils/hitTest.test.d.ts +1 -0
  55. package/dist/types/utils/jsDriverResultTransformer.d.ts +11 -9
  56. package/dist/types/utils/layoutSeeding.d.ts +7 -0
  57. package/dist/types/utils/layoutSeeding.test.d.ts +1 -0
  58. package/dist/types/utils/webWorkerUtils.d.ts +1 -1
  59. package/dist/types/utils/zoomFunctions.d.ts +9 -2
  60. package/package.json +13 -15
  61. package/skills/neo4j-nvl-skill/README.md +39 -0
  62. package/skills/neo4j-nvl-skill/SKILL.md +456 -0
  63. package/skills/neo4j-nvl-skill/references/api-surface.md +596 -0
  64. package/skills/neo4j-nvl-skill/references/troubleshooting.md +317 -0
  65. package/dist/base.mjs.LICENSE.txt +0 -21
  66. package/dist/types/layouts/forcedirectedlayout/ForceCytoLayout.d.ts +0 -22
  67. package/dist/types/layouts/forcedirectedlayout/cosebilkentlayout/CoseBilkentLayout.d.ts +0 -33
  68. package/dist/types/layouts/forcedirectedlayout/physlayout/PhysLayout.d.ts +0 -174
  69. package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-fragment.d.ts +0 -2
  70. package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-repulsive-fragment.d.ts +0 -2
  71. package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-update-fragment.d.ts +0 -2
  72. package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/sim-vertex.d.ts +0 -2
  73. package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/workaround-fragment.d.ts +0 -2
  74. package/dist/types/layouts/forcedirectedlayout/physlayout/solarmerger/SolarMerger.d.ts +0 -21
  75. package/dist/types/layouts/forcedirectedlayout/physlayout/solarmerger/solar-placer.d.ts +0 -2
  76. /package/dist/types/layouts/forcedirectedlayout/{physlayout/PhysLayout.test.d.ts → PhysLayout.test.d.ts} +0 -0
  77. /package/dist/types/layouts/forcedirectedlayout/{physlayout/solarmerger/SolarMerger.bench.d.ts → clustering/ClusterByMerger.test.d.ts} +0 -0
  78. /package/dist/types/layouts/forcedirectedlayout/{physlayout/solarmerger/SolarMerger.test.d.ts → clustering/SolarMerger.bench.d.ts} +0 -0
  79. /package/dist/types/layouts/forcedirectedlayout/{physlayout/solarmerger/solar-placer.test.d.ts → clustering/SolarMerger.test.d.ts} +0 -0
  80. /package/dist/types/{utils/hittest.test.d.ts → layouts/forcedirectedlayout/clustering/clustering-utils.test.d.ts} +0 -0
  81. /package/dist/types/layouts/forcedirectedlayout/{physlayout/glwrapper.d.ts → glwrapper.d.ts} +0 -0
@@ -0,0 +1,42 @@
1
+ import { type CoarsenedGraph, type Sun } from '../layouts/forcedirectedlayout/clustering/types';
2
+ import type { Cluster, ClusterId } from '../modules/state/types';
3
+ import type { Node } from '../types/graph-element';
4
+ import { type ClusterMemberDisk } from './clusterGeometry';
5
+ import { type Point } from './geometry';
6
+ /**
7
+ * A fitted cluster hull region used for decoration and hit-testing.
8
+ */
9
+ export type ClusterHitRegion = Cluster & {
10
+ /** Convex hull used for picking / decoration. */
11
+ hull: Point[];
12
+ /** Layout sun original id (e.g. `synth-sun:${id}`). */
13
+ sunOriginalId: string;
14
+ };
15
+ export type MultiMemberCluster = {
16
+ sun: Sun;
17
+ nodeIds: string[];
18
+ };
19
+ /**
20
+ * Returns each multi-member first-level sun system in a coarsening hierarchy.
21
+ * @param firstSubGraphLevel - `subGraphs[1]` from the current layout coarsening hierarchy.
22
+ * @returns Suns paired with their original member node ids.
23
+ */
24
+ export declare const getMultiMemberClusters: (firstSubGraphLevel: CoarsenedGraph) => MultiMemberCluster[];
25
+ /**
26
+ * Collects member disks with usable positions for hull fitting.
27
+ * @param nodeIds - Member node ids.
28
+ * @param idToPosition - Node id to position map.
29
+ * @param idToItem - Node id to graph node map.
30
+ * @returns Member disks for {@link fitClusterHull}.
31
+ */
32
+ export declare const collectMemberDisks: (nodeIds: string[], idToPosition: Readonly<Record<string, Point>>, idToItem: Record<string, Node>) => ClusterMemberDisk[];
33
+ /**
34
+ * Builds hit regions for {@link ClusteringOptions.clusterBy} multi-member clusters.
35
+ * Structural {@link SolarMerger} suns are skipped, as they have no entry in `clusterIdsBySun`.
36
+ * @param subGraphs - Layout coarsening hierarchy.
37
+ * @param idToPosition - Node id to position map.
38
+ * @param idToItem - Node id to graph node map.
39
+ * @param clusterIdsBySun - Cluster id per synthetic cluster sun, keyed by sun `originalId`.
40
+ * @returns Fitted cluster hit regions.
41
+ */
42
+ export declare const buildClusterByHitRegions: (subGraphs: CoarsenedGraph[], idToPosition: Readonly<Record<string, Point>>, idToItem: Record<string, Node>, clusterIdsBySun: ReadonlyMap<string, ClusterId>) => ClusterHitRegion[];
@@ -0,0 +1 @@
1
+ export {};
@@ -5,6 +5,12 @@ export declare const MinRelLength = 100;
5
5
  export declare const Gravity = 25;
6
6
  export declare const SimulationStopVelocity = 0.25;
7
7
  export declare const MappingEnd = 999999;
8
+ export declare const LayoutStepIntervalMs = 13;
9
+ export declare const MaxLayoutStepsPerFrame = 20;
10
+ export declare const DefaultMaxFps = 30;
11
+ export declare const DefaultMinFps = 3;
12
+ export declare const MinAllowedFps = 1;
13
+ export declare const MaxAllowedFps = 120;
8
14
  export declare const ActiveAnimDuration = 1000;
9
15
  export declare const DefaultNodeSize = 25;
10
16
  export declare const DefaultNodeColor = "#FFDF81";
@@ -8,11 +8,11 @@ export interface Point {
8
8
  /** The y coordinate of the point. */
9
9
  y: number;
10
10
  }
11
- export declare const isPointDefined: (point: Point | Node) => boolean;
12
11
  /**
13
12
  * Returns true when value is a finite number (not NaN or Infinity).
14
13
  */
15
14
  export declare const isValidFiniteNumber: (value: unknown) => value is number;
15
+ export declare const isPointDefined: (point: Point | Node | null | undefined) => point is Point;
16
16
  /**
17
17
  * This function checks if the coordinates are defined.
18
18
  * @param from - The {@link Node} the edge starts from.
@@ -126,3 +126,46 @@ export declare const getIntersection: (p0: Point, p1: Point, p2: Point, p3: Poin
126
126
  * @returns The distance between the point and the curve.
127
127
  */
128
128
  export declare const getDistanceToQuadratic: (fromCoordinates: Point, toCoordinates: Point, control: Point, point: Point) => number;
129
+ /**
130
+ * Converts a polar coordinate (radius + angle around a centre) to a cartesian point.
131
+ * @param centre - The centre of the circle.
132
+ * @param radius - The radius of the circle.
133
+ * @param angle - The angle around the circle, in radians.
134
+ * @returns The point at that angle and radius from the centre.
135
+ */
136
+ export declare const pointOnCircle: (centre: Point, radius: number, angle: number) => Point;
137
+ /**
138
+ * Returns the point halfway between two points.
139
+ * @param a - The first point.
140
+ * @param b - The second point.
141
+ * @returns The midpoint of the segment from a to b.
142
+ */
143
+ export declare const getMidPoint: (a: Point, b: Point) => Point;
144
+ /**
145
+ * Places child points evenly spaced around a circle centred on a point.
146
+ * @param centre - The centre of the circle.
147
+ * @param radius - The radius of the circle.
148
+ * @param noOfChildren - The number of points to place around the circle.
149
+ * @returns The evenly spaced points.
150
+ */
151
+ export declare const calculateCirclePositions: (centre: Point, radius: number, noOfChildren: number) => Point[];
152
+ /**
153
+ * Andrew's monotone-chain convex hull.
154
+ * @param points - The points to get the convex hull of.
155
+ * @returns The convex hull of the points.
156
+ */
157
+ export declare const getConvexHull: (points: Point[]) => Point[];
158
+ /**
159
+ * Returns true when the point lies inside or on the boundary of a convex polygon.
160
+ * Works for both clockwise and counter-clockwise vertex order.
161
+ * @param point - The point to test.
162
+ * @param polygon - Convex polygon vertices in order around the boundary.
163
+ * @returns True when the point is inside or on the polygon.
164
+ */
165
+ export declare const isPointInConvexPolygon: (point: Point, polygon: Point[]) => boolean;
166
+ /**
167
+ * Absolute area of a simple polygon via the shoelace formula.
168
+ * @param polygon - Polygon vertices in order around the boundary.
169
+ * @returns The absolute area of the polygon.
170
+ */
171
+ export declare const getPolygonArea: (polygon: Point[]) => number;
@@ -1,5 +1,6 @@
1
- import type { NvlState } from '../modules/state/types';
1
+ import type { Cluster, NvlState } from '../modules/state/types';
2
2
  import type { Node, Relationship } from '../types/graph-element';
3
+ import type { ClusterHitRegion } from './clusterHitRegions';
3
4
  import type { Point } from './geometry';
4
5
  /**
5
6
  * A node that has been hit by a pointer event
@@ -34,7 +35,18 @@ export interface HitTargetRelationship {
34
35
  distance: number;
35
36
  }
36
37
  /**
37
- * A collection of nodes and relationships that have been hit by a pointer event
38
+ * A {@link ClusteringOptions.clusterBy} cluster hull that has been hit by a pointer event
39
+ */
40
+ export interface HitTargetCluster {
41
+ /** The cluster that was hit */
42
+ data: Cluster;
43
+ /** The coordinates of the pointer event */
44
+ pointerCoordinates: Point;
45
+ /** The convex hull used for the hit test */
46
+ hull: Point[];
47
+ }
48
+ /**
49
+ * A collection of nodes, relationships and clusters that have been hit by a pointer event
38
50
  * Part of the result of a {@link NVL}.{@link NVL.getHits} call
39
51
  */
40
52
  export type HitTargets = {
@@ -42,15 +54,29 @@ export type HitTargets = {
42
54
  nodes: HitTargetNode[];
43
55
  /** The relationships that have been hit by the pointer event. */
44
56
  relationships: HitTargetRelationship[];
57
+ /** The cluster hulls that have been hit by the pointer event. */
58
+ clusters: HitTargetCluster[];
45
59
  };
46
- export declare const hitTest: (x: number, y: number, state: NvlState, targets?: string[], options?: {
60
+ export type HitTestTarget = 'node' | 'relationship' | 'cluster';
61
+ /**
62
+ * Finds all cluster hulls that contain the given point.
63
+ * Overlapping hulls are returned smallest-first (most specific).
64
+ * @param x - X coordinate.
65
+ * @param y - Y coordinate.
66
+ * @param regions - Fitted cluster hit regions.
67
+ * @returns Cluster hits sorted by ascending hull area.
68
+ */
69
+ export declare const hitClusterTest: (x: number, y: number, regions: ClusterHitRegion[]) => HitTargetCluster[];
70
+ export declare const hitTest: (x: number, y: number, state: NvlState, targets?: HitTestTarget[], options?: {
47
71
  hitNodeMarginWidth?: number;
72
+ clusterRegions?: ClusterHitRegion[];
48
73
  }) => HitTargets;
49
74
  export declare const hitTestCanvas: (x: number, y: number, parentHandler: {
50
75
  getCanvasNodesAt: (c: Point, m: number) => HitTargetNode[];
51
76
  getCanvasRelsAt: (c: Point) => HitTargetRelationship[];
52
- }, targets?: string[], options?: {
77
+ }, targets?: readonly HitTestTarget[], options?: {
53
78
  hitNodeMarginWidth?: number;
79
+ clusterRegions?: ClusterHitRegion[];
54
80
  }) => HitTargets;
55
81
  export declare const hitTestBox: (x1: number, y1: number, x2: number, y2: number, state: NvlState, targets?: string[]) => {
56
82
  nodes: Node[];
@@ -0,0 +1 @@
1
+ export {};
@@ -16,17 +16,19 @@ export declare const recordCollector: (graphElements: NestedGraphElements[]) =>
16
16
  * @example
17
17
  *
18
18
  * ```ts
19
- * import neo4j from "neo4j-driver";
20
- * import { nvlResultTransformer, NVL } from "@neo4j-nvl/base";
19
+ * import * as neo4j from 'neo4j-driver'
20
+ * import { nvlResultTransformer, NVL } from '@neo4j-nvl/base'
21
21
  *
22
- * const driver = neo4j.driver("{uri}", neo4j.auth.basic("{user}", "{password}"));
23
- * const nvlGraph = await driver.executeQuery(
24
- * "MATCH (a)-[r]-(b) RETURN a,r,b LIMIT 25",
25
- * {},
26
- * { resultTransformer: nvlResultTransformer }
27
- * );
22
+ * const run = async () => {
23
+ * const driver = neo4j.driver('{uri}', neo4j.auth.basic('{user}', '{password}'))
24
+ * const nvlGraph = await driver.executeQuery(
25
+ * 'MATCH (a)-[r]-(b) RETURN a,r,b LIMIT 25',
26
+ * {},
27
+ * { resultTransformer: nvlResultTransformer }
28
+ * )
28
29
  *
29
- * const nvl = new NVL(document.getElementById('viz'), nvlGraph.nodes, nvlGraph.relationships);
30
+ * const nvl = new NVL(document.getElementById('viz'), nvlGraph.nodes, nvlGraph.relationships)
31
+ * }
30
32
  * ```
31
33
  *
32
34
  * @see {@link https://neo4j.com/docs/api/javascript-driver/current/class/lib6/result-transformers.js~ResultTransformers.html|ResultTransformers on Neo4j JS Driver API Docs}
@@ -0,0 +1,7 @@
1
+ import type { Point } from './geometry';
2
+ export type SeedingMethod = 'box' | 'circle';
3
+ export declare const getCircleSeedRadius: (nodeCount: number, seedSpacing: number) => number;
4
+ export declare const getBoxStartSize: (nodeCount: number) => number;
5
+ export declare const getCirclePositionsForNodeCount: (nodeCount: number, center: Point, radius: number) => Point[];
6
+ export declare const getBoxPositionsForNodeCount: (nodeCount: number, center: Point) => Point[];
7
+ export declare const getSeedPositions: (nodeCount: number, seedingMethod: SeedingMethod, center?: Point) => Point[];
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,3 @@
1
- type Layouts = 'CoseBilkentLayout' | 'HierarchicalLayout';
1
+ type Layouts = 'HierarchicalLayout';
2
2
  export declare const initializeWorker: (workerName: Layouts, workersDisabled?: boolean) => SharedWorker;
3
3
  export {};
@@ -1,5 +1,11 @@
1
1
  import type { Node } from '../index';
2
2
  import type { Point } from './geometry';
3
+ /**
4
+ * Gets padding for fitting nodes, which is twice the largest node radius.
5
+ * @param maxNodeRadius - The largest node radius.
6
+ * @returns The padding for fitting nodes.
7
+ */
8
+ declare const getFitNodesPadding: (maxNodeRadius?: number) => number;
3
9
  declare const getExtremeLimits: (nodePositions: Point[]) => Point[];
4
10
  declare const getMaxDistance: (extremeLimits?: Point[]) => number;
5
11
  /**
@@ -40,7 +46,8 @@ declare const createZoomTarget: (zoomX: number, zoomY: number, minZoom?: number,
40
46
  * @param nodePositions - The node positions.
41
47
  * @param containerWidth - The width of the container NVL is displayed in.
42
48
  * @param containerHeight - The height of the container NVL is displayed in.
43
- * @param maxNodeRadius - The maximum node radius, which is added as margin to the scene (defaults to `50`).
49
+ * @param maxNodeRadius - The maximum node radius, which is added as margin to the scene
50
+ * (defaults to 2 * {@link DefaultNodeSize}).
44
51
  * @returns The zoom and pan targets.
45
52
  */
46
53
  declare const getZoomTargetForNodePositions: (nodePositions: Point[], containerWidth: number, containerHeight: number, maxNodeRadius?: number) => {
@@ -55,4 +62,4 @@ declare const getFlexibleZoomLimit: (nodePositions: Point[], rect: HTMLCanvasEle
55
62
  declare const getNewZoomWithinLimits: (newZoom: number, oldZoom: number, minZoom: number, maxZoom: number) => number;
56
63
  declare const isZoomOutAtLimit: (newZoom: number, oldZoom: number, zoomOutLimit: number) => boolean;
57
64
  declare const getDynamicZoom: (nodePositions: Point[] & Node[], minZoom: number, maxZoom: number, rect: HTMLCanvasElement, newZoom: number, currentZoom: number) => number;
58
- export { getFlexibleZoomLimit, getZoomTargetForNodePositions, isZoomOutAtLimit, getNewZoomWithinLimits, getExtremeLimits, getMaxDistance, getPositionBoundaries, getZoomLevel, createZoomTarget, getDynamicZoom };
65
+ export { getFitNodesPadding, getFlexibleZoomLimit, getZoomTargetForNodePositions, isZoomOutAtLimit, getNewZoomWithinLimits, getExtremeLimits, getMaxDistance, getPositionBoundaries, getZoomLevel, createZoomTarget, getDynamicZoom };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neo4j-nvl/base",
3
- "version": "1.2.2",
3
+ "version": "2.0.0-2b04269b",
4
4
  "license": "SEE LICENSE IN 'LICENSE.txt'",
5
5
  "homepage": "https://neo4j.com/docs/nvl/current/",
6
6
  "description": "Base library for the Neo4j Visualization Library",
@@ -16,12 +16,13 @@
16
16
  "types": "dist/types/index.d.ts",
17
17
  "files": [
18
18
  "LICENSE.txt",
19
- "dist"
19
+ "dist",
20
+ "skills"
20
21
  ],
21
22
  "scripts": {
22
- "build": "yarn global:tsc && webpack",
23
- "build:dev": "yarn global:tsc && webpack --mode development",
24
- "watch": "concurrently 'tsc -w' 'webpack -w --mode development' -k -n 'tsc,webpack' -c 'cyan,magenta'",
23
+ "build": "yarn global:tsc && vite build",
24
+ "build:dev": "yarn global:tsc && vite build --mode development",
25
+ "watch": "concurrently 'tsc -w' 'vite build --watch --mode development' -k -n 'tsc,vite' -c 'cyan,magenta'",
25
26
  "test": "yarn global:jest",
26
27
  "test:perf": "yarn global:jest --testPathPattern='.bench.' --testPathIgnorePatterns=",
27
28
  "eslint": "yarn global:eslint ./src/",
@@ -30,7 +31,7 @@
30
31
  "postpack": "rm LICENSE.txt && rm CHANGELOG.md"
31
32
  },
32
33
  "dependencies": {
33
- "@neo4j-nvl/layout-workers": "1.2.2",
34
+ "@neo4j-nvl/layout-workers": "2.0.0-2b04269b",
34
35
  "@segment/analytics-next": "1.81.1",
35
36
  "color-string": "1.9.1",
36
37
  "d3-force": "3.0.0",
@@ -38,26 +39,23 @@
38
39
  "glsl-inject-defines": "1.0.3",
39
40
  "lodash": "4.18.1",
40
41
  "loglevel": "1.9.2",
41
- "mobx": "3.6.2",
42
+ "mobx": "6.15.0",
42
43
  "node-pid-controller": "1.0.1",
43
- "resizelistener": "1.1.0",
44
44
  "tinycolor2": "1.6.0",
45
- "uuid": "14.0.1"
45
+ "uuid": "14.0.2"
46
46
  },
47
47
  "devDependencies": {
48
- "@babel/core": "7.29.7",
49
48
  "@types/color-string": "1.5.5",
50
49
  "@types/d3-force": "3.0.10",
51
50
  "@types/lodash": "4.17.21",
52
51
  "@types/segment-analytics": "0.0.38",
53
52
  "@types/tinycolor2": "1.4.6",
54
- "babel-loader": "8.4.1",
55
- "copy-webpack-plugin": "11.0.0",
56
53
  "neo4j-driver": "5.28.2",
57
- "webpack": "5.104.1",
58
- "webpack-cli": "5.1.4"
54
+ "vite": "7.3.5",
55
+ "vite-plugin-static-copy": "4.1.1"
59
56
  },
60
57
  "peerDependencies": {
61
58
  "neo4j-driver": "*"
62
- }
59
+ },
60
+ "stableVersion": "2.0.0"
63
61
  }
@@ -0,0 +1,39 @@
1
+ # neo4j-nvl-skill
2
+
3
+ Skill for the Neo4j Visualization Library (NVL) — covering:
4
+
5
+ - `@neo4j-nvl/base` — `NVL` class, nodes/relationships, options, callbacks, hit testing, image export
6
+ - `@neo4j-nvl/interaction-handlers` — `ZoomInteraction`, `PanInteraction`, `DragNodeInteraction`, `ClickInteraction`, `HoverInteraction`, `BoxSelectInteraction`, `LassoInteraction`, `KeyboardInteraction`
7
+ - `@neo4j-nvl/react` — `InteractiveNvlWrapper`, `BasicNvlWrapper`, `StaticPictureWrapper`
8
+ - `nvlResultTransformer` for piping `driver.executeQuery` results straight into NVL
9
+ - Canvas vs WebGL renderer selection (~1k vs 100k+ nodes)
10
+ - Layout selection (`forceDirected`, `hierarchical`, `circular`, `grid`, `free`, `d3Force`)
11
+ - force-directed and hierarchical `clusterBy`, cluster decorations, hit testing, and callbacks
12
+ - Container setup, Web Worker fallback, telemetry opt-out
13
+
14
+ **Not covered** (see sibling tools / skills):
15
+ - Out-of-the-box embedded graph view with default styling → `GraphVisualization` component in `@neo4j-ndl/react` (Neo4j Needle design system) — wraps NVL with defaults
16
+ - Python / Jupyter graph visualization → `neo4j/python-graph-visualization` (Python port of NVL)
17
+ - Cypher query authoring → `neo4j-cypher-skill`
18
+ - Driver lifecycle, sessions, `executeQuery` setup → `neo4j-driver-javascript-skill`
19
+ - GDS algorithms → `neo4j-gds-skill` / `neo4j-aura-graph-analytics-skill`
20
+
21
+ **Compatibility:** `@neo4j-nvl` packages 2.0.x; React 19 for `@neo4j-nvl/react`; modern browsers with Canvas2D and WebGL2.
22
+
23
+ **Install:**
24
+
25
+ ```bash
26
+ npm install @neo4j-nvl/base
27
+ npm install @neo4j-nvl/interaction-handlers # optional, for vanilla JS interactions
28
+ npm install @neo4j-nvl/react # optional, for React apps
29
+ ```
30
+
31
+ Starter templates: https://github.com/neo4j-devtools/nvl-boilerplates
32
+
33
+ **Install skill:**
34
+
35
+ This skill ships inside `@neo4j-nvl/base`. After installing the package, sync it into your agent's skills directory:
36
+
37
+ ```bash
38
+ npx skills experimental_sync
39
+ ```