@cosmos.gl/graph 3.0.0-beta.8 → 3.0.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,7 +31,7 @@ npm install @cosmos.gl/graph
31
31
 
32
32
  Get the data, [configure](https://cosmosgl.github.io/graph/?path=/docs/configuration--docs) the graph and run the simulation:
33
33
 
34
- ```javascript
34
+ ```ts
35
35
  import { Graph } from '@cosmos.gl/graph'
36
36
 
37
37
  const div = document.querySelector('div')
@@ -85,9 +85,13 @@ cosmos.gl v3.0 brings a new rendering engine, async initialization, and several
85
85
  - **Link sampling** — sample visible links on screen with `getSampledLinks()` and `getSampledLinkPositionsMap()` for rendering labels or overlays along links.
86
86
  - **Context menu support** — new callbacks for right-click interactions: `onContextMenu`, `onPointContextMenu`, `onLinkContextMenu`, `onBackgroundContextMenu`.
87
87
  - **Fit viewport to points** — `setZoomTransformByPointPositions()` zooms and pans to fit a set of points into view.
88
- - **Hover improvements** — `onPointMouseOver` now includes an `isSelected` parameter; hover correctly highlights the topmost point when points overlap.
88
+ - **Config-driven highlighting** — imperative selection methods replaced by `highlightedPointIndices`, `highlightedLinkIndices`, and `outlinedPointIndices` config properties. Points and links are highlighted independently. Focused points are rendered with rings via `focusedPointIndex`; focused links are rendered wider via `focusedLinkIndex`. New `findPointsInRect()`, `findPointsInPolygon()`, `getNeighboringPointIndices()`, `getConnectedLinkIndices()`, and `getConnectedPointIndices()` methods.
89
+ - **Hover improvements** — `onPointMouseOver` now includes `isHighlighted` and `isOutlined` parameters; hover correctly highlights the topmost point when points overlap.
89
90
  - **Config API changes** — `setConfig()` now resets all values to defaults before applying; use the new `setConfigPartial()` to update individual properties without resetting the rest.
90
- - **Init-only config fields** — `enableSimulation`, `initialZoomLevel`, `randomSeed`, and `attribution` can only be set during initialization and are preserved across config updates.
91
+ - **Init-only config fields** — `initialZoomLevel`, `randomSeed`, and `attribution` can only be set during initialization and are preserved across config updates.
92
+ - **Runtime simulation toggle** — `enableSimulation` can now be changed at runtime via `setConfig()` or `setConfigPartial()`.
93
+ - **GPU transitions** — point positions, point colors/sizes, and link colors/widths now animate by default (`transitionDuration: 800`, `transitionEasing: TransitionEasing.CubicInOut`). Use `transitionDuration: 0` to keep snap updates.
94
+ - **Transition callbacks** — use `onTransitionStart`, `onTransition`, and `onTransitionEnd` to track transition lifecycle and progress.
91
95
  - **Default point shape** — new `pointDefaultShape` config property lets you set the fallback shape for all points when no per-point shapes are provided. Accepts a `PointShape` enum value (e.g., `PointShape.Star`), a plain number (e.g., `6`), or a numeric string (e.g., `"6"`).
92
96
  - **Exported defaults** — `defaultConfigValues` is now part of the public API.
93
97
  - **Optimized hover detection** — skips GPU work when the mouse hasn't moved.
@@ -111,7 +115,7 @@ Check the [Migration Guide](./migration-notes.md) for upgrading from v1.
111
115
 
112
116
  ### Examples
113
117
 
114
- - [Basic Set-Up](https://cosmosgl.github.io/graph/?path=/story/examples-beginners--basic-set-up)
118
+ - [Actions](https://cosmosgl.github.io/graph/?path=/story/examples-beginners--actions)
115
119
 
116
120
  ---
117
121
 
package/dist/config.d.ts CHANGED
@@ -2,14 +2,44 @@ import { D3ZoomEvent } from 'd3-zoom';
2
2
  import { D3DragEvent } from 'd3-drag';
3
3
  import { Hovered } from './modules/Store';
4
4
  import { PointShape } from './modules/GraphData';
5
+ import { TransitionEasing } from './modules/Transition';
5
6
  export interface GraphConfigInterface {
6
7
  /**
7
8
  * If set to `false`, the simulation will not run.
8
- * This property will be applied only on component initialization and it
9
- * can't be changed using the `setConfig` or `setConfigPartial` methods.
9
+ * Can be toggled at runtime using `setConfig` or `setConfigPartial`.
10
10
  * Default value: `true`
11
11
  */
12
12
  enableSimulation: boolean;
13
+ /**
14
+ * Transition duration in milliseconds.
15
+ * Default value: `800`
16
+ * @note When a position transition is triggered via `setPointPositions()`, the simulation
17
+ * is automatically paused for the duration and remains paused afterwards so forces do not
18
+ * pull nodes away from the target layout. Call `unpause()` to resume the simulation explicitly.
19
+ */
20
+ transitionDuration: number;
21
+ /**
22
+ * Easing curve for transitions.
23
+ * Default value: `TransitionEasing.CubicInOut`
24
+ */
25
+ transitionEasing: TransitionEasing | `${TransitionEasing}`;
26
+ /**
27
+ * Callback function that will be called when a transition starts.
28
+ * Default value: `undefined`
29
+ */
30
+ onTransitionStart?: () => void;
31
+ /**
32
+ * Callback function that will be called on every transition frame.
33
+ * The `progress` value ranges from 0 to 1.
34
+ * Default value: `undefined`
35
+ */
36
+ onTransition?: (progress: number) => void;
37
+ /**
38
+ * Callback function that will be called when a transition ends.
39
+ * `interrupted` is `true` when a transition was replaced or aborted before completion.
40
+ * Default value: `undefined`
41
+ */
42
+ onTransitionEnd?: (interrupted: boolean) => void;
13
43
  /**
14
44
  * Canvas background color.
15
45
  * Can be either a hex color string (e.g., '#b3b3b3') or an array of RGBA values.
@@ -30,7 +60,7 @@ export interface GraphConfigInterface {
30
60
  */
31
61
  pointDefaultColor: string | [number, number, number, number];
32
62
  /**
33
- * The color to use for points when they are greyed out (when selection is active).
63
+ * The color to use for points when they are greyed out (when highlighting is active).
34
64
  * This can be either a hex color string (e.g., '#b3b3b3') or an array of RGBA values
35
65
  * in the format `[red, green, blue, alpha]` where each value is a number between 0 and 1.
36
66
  *
@@ -44,12 +74,9 @@ export interface GraphConfigInterface {
44
74
  */
45
75
  pointGreyoutColor?: string | [number, number, number, number];
46
76
  /**
47
- * Opacity multiplier for points when they are greyed out (when selection is active).
48
- * Values range from 0 (completely transparent) to 1 (fully opaque).
49
- *
50
- * When defined, this value is multiplied with the point's final alpha instead of the
51
- * default `pointOpacity`. When `undefined`, greyed-out points use `pointOpacity` as their multiplier.
52
- *
77
+ * Opacity of greyed-out points when highlighting is active.
78
+ * Range: 0 (fully transparent) to 1 (fully opaque).
79
+ * When set, used instead of `pointOpacity` for greyed-out points.
53
80
  * Default value: `undefined`
54
81
  */
55
82
  pointGreyoutOpacity?: number;
@@ -106,11 +133,32 @@ export interface GraphConfigInterface {
106
133
  */
107
134
  focusedPointRingColor: string | [number, number, number, number];
108
135
  /**
109
- * Set focus on a point by index. A ring will be highlighted around the focused point.
136
+ * Set focus on a point by index. A ring will be rendered around the focused point.
137
+ * The focused ring is larger than outline rings to create a clear visual hierarchy.
110
138
  * When set to `undefined`, no point is focused.
111
139
  * Default value: `undefined`
112
140
  */
113
141
  focusedPointIndex?: number;
142
+ /**
143
+ * Array of point indices to highlight. When set, all points NOT in this array will be
144
+ * greyed out. An empty array `[]` activates highlighting with all points greyed out.
145
+ * Set to `undefined` to clear highlighting and show all points normally.
146
+ * Default value: `undefined`
147
+ */
148
+ highlightedPointIndices?: number[];
149
+ /**
150
+ * Array of point indices to draw an outline ring around. The outline ring is a circle
151
+ * rendered around the point regardless of the point's shape. When a point is both
152
+ * outlined and greyed out (not highlighted), the ring color is dimmed to match.
153
+ * Default value: `undefined`
154
+ */
155
+ outlinedPointIndices?: number[];
156
+ /**
157
+ * Color of the outline ring drawn around outlined points.
158
+ * Can be either a hex color string (e.g., '#b3b3b3') or an array of RGBA values.
159
+ * Default value: `'white'`
160
+ */
161
+ outlinedPointRingColor: string | [number, number, number, number];
114
162
  /**
115
163
  * Turns link rendering on / off.
116
164
  * Default value: `true`
@@ -132,10 +180,30 @@ export interface GraphConfigInterface {
132
180
  */
133
181
  linkOpacity: number;
134
182
  /**
135
- * Greyed out link opacity value when the selection is active.
183
+ * Greyed-out link opacity value when link highlighting is active.
136
184
  * Default value: `0.1`
137
185
  */
138
186
  linkGreyoutOpacity: number;
187
+ /**
188
+ * Array of link indices to highlight. When set, all links NOT in this array will be
189
+ * greyed out. An empty array `[]` activates highlighting with all links greyed out.
190
+ * Set to `undefined` to clear highlighting and show all links normally.
191
+ * Link highlighting is independent of point highlighting.
192
+ * Default value: `undefined`
193
+ */
194
+ highlightedLinkIndices?: number[];
195
+ /**
196
+ * Set focus on a link by index. The focused link will be rendered with extra width.
197
+ * When set to `undefined`, no link is focused.
198
+ * Default value: `undefined`
199
+ */
200
+ focusedLinkIndex?: number;
201
+ /**
202
+ * Number of pixels to add to the link width when focused.
203
+ * The focused width is calculated as: originalWidth + focusedLinkWidthIncrease
204
+ * Default value: `5`
205
+ */
206
+ focusedLinkWidthIncrease: number;
139
207
  /**
140
208
  * The default width value to use for links when no link widths are provided or if the width value in the array is `undefined` or `null`.
141
209
  * Default value: `1`
@@ -377,12 +445,13 @@ export interface GraphConfigInterface {
377
445
  * Callback function that will be called when a point appears under the mouse
378
446
  * as a result of a mouse event, zooming and panning, or movement of points.
379
447
  * The point index will be passed as the first argument, position as the second argument,
380
- * the corresponding mouse event or D3's zoom event as the third argument, and whether
381
- * the hovered point is selected as the fourth argument:
382
- * `(index: number, pointPosition: [number, number], event: MouseEvent | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | D3ZoomEvent<HTMLCanvasElement, undefined> | undefined, isSelected: boolean) => void`.
448
+ * the corresponding mouse event or D3's zoom event as the third argument,
449
+ * whether the hovered point is highlighted as the fourth argument,
450
+ * and whether the hovered point is outlined as the fifth argument:
451
+ * `(index, pointPosition, event, isHighlighted, isOutlined) => void`.
383
452
  * Default value: `undefined`
384
453
  */
385
- onPointMouseOver?: (index: number, pointPosition: [number, number], event: MouseEvent | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | D3ZoomEvent<HTMLCanvasElement, undefined> | undefined, isSelected: boolean) => void;
454
+ onPointMouseOver?: (index: number, pointPosition: [number, number], event: MouseEvent | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | D3ZoomEvent<HTMLCanvasElement, undefined> | undefined, isHighlighted: boolean, isOutlined: boolean) => void;
386
455
  /**
387
456
  * Callback function that will be called when a point is no longer underneath
388
457
  * the mouse pointer because of a mouse event, zoom/pan event, or movement of points.
@@ -591,22 +660,32 @@ export type Complete<T> = {
591
660
  * to their defaults, not retain their previous values.
592
661
  */
593
662
  export type GraphConfig = Partial<GraphConfigInterface>;
594
- /** Returns a fresh copy of `defaultConfigValues` with arrays cloned to prevent shared references. */
663
+ /**
664
+ * Returns a fresh copy of `defaultConfigValues` with arrays cloned so each Graph instance
665
+ * gets its own copy rather than sharing array references with it.
666
+ * `defaultConfigValues` is a module-level object — one instance shared across the entire codebase.
667
+ * Called at construction time to initialise `Graph.config`, and via `resetConfigToDefaults` on every `setConfig()` call.
668
+ */
595
669
  export declare function createDefaultConfig(): GraphConfigInterface;
596
670
  /**
597
671
  * Resets the config object to default values in place, preserving the object reference
598
672
  * so that modules (Zoom, Store, etc.) that hold a reference to it stay in sync.
673
+ * Called at the start of `setConfig()` to wipe previous values before applying the new ones.
599
674
  */
600
675
  export declare function resetConfigToDefaults(target: GraphConfigInterface): void;
601
676
  /**
602
- * Applies only the provided `source` values onto `target`, leaving all other
603
- * properties unchanged.
677
+ * Applies `source` values onto `target` in place, leaving absent keys unchanged.
678
+ *
679
+ * Mutates in place rather than returning a new object, because multiple modules
680
+ * (Zoom, Store, etc.) hold a reference to the same config object and need to
681
+ * see updates immediately.
604
682
  *
605
- * Mutates `target` in place (via `Object.assign`) rather than replacing it,
606
- * because multiple modules (Zoom, Store, etc.) hold a reference to the same config object.
683
+ * Called in three places:
684
+ * - Constructor: applies the optional initial config on top of defaults.
685
+ * - `setConfig()`: applies a full replacement after `resetConfigToDefaults`.
686
+ * - `setConfigPartial()`: with `useDefaultsForUndefined = true`, so explicit
687
+ * `undefined` values reset that property to its default.
607
688
  *
608
- * - When `useDefaultsForUndefined` is `false` (default): explicit `undefined` values in `source` are skipped.
609
- * - When `useDefaultsForUndefined` is `true`: explicit `undefined` values are replaced with their defaults.
610
- * - Array values are shallow-cloned to prevent shared references.
689
+ * Arrays from `source` are stored by reference callers must not mutate them after passing.
611
690
  */
612
691
  export declare function applyConfig(target: GraphConfigInterface, source: GraphConfig, useDefaultsForUndefined?: boolean): void;
package/dist/helper.d.ts CHANGED
@@ -47,6 +47,11 @@ export declare function rgbToBrightness(r: number, g: number, b: number): number
47
47
  * @note Cosmos currently supports WebGL only; support for other device types will be added later.
48
48
  */
49
49
  export declare function readPixels(device: Device, fbo: Framebuffer, sourceX?: number, sourceY?: number, sourceWidth?: number, sourceHeight?: number): Float32Array;
50
+ /**
51
+ * Extracts point indices from a pixel readback buffer.
52
+ * Every 4th value (R channel) is checked — non-zero means the point at that index was found.
53
+ */
54
+ export declare function extractIndicesFromPixels(pixels: Float32Array): number[];
50
55
  /**
51
56
  * Returns the maximum point size supported by the device, scaled by pixel ratio.
52
57
  * For WebGL devices, reads the limit from the context; for other device types, uses MAX_POINT_SIZE from Store.
package/dist/index.d.ts CHANGED
@@ -34,6 +34,7 @@ export declare class Graph {
34
34
  private forceMouse;
35
35
  private clusters;
36
36
  private zoomInstance;
37
+ private transition;
37
38
  private dragInstance;
38
39
  private fpsMonitor;
39
40
  private currentEvent;
@@ -128,6 +129,8 @@ export declare class Graph {
128
129
  * @param {boolean | undefined} dontRescale - For this call only, don't rescale the points.
129
130
  * - `true`: Don't rescale.
130
131
  * - `false` or `undefined` (default): Use the behavior defined by `config.rescalePositions`.
132
+ * @note If `transitionDuration > 0` and the simulation is running, the simulation is automatically
133
+ * paused for the transition and remains paused afterwards. Call `unpause()` to resume it.
131
134
  */
132
135
  setPointPositions(pointPositions: Float32Array, dontRescale?: boolean | undefined): void;
133
136
  /**
@@ -385,56 +388,47 @@ export declare class Graph {
385
388
  */
386
389
  setZoomTransformByPointPositions(positions: Float32Array, duration?: number, scale?: number, padding?: number, enableSimulation?: boolean): void;
387
390
  /**
388
- * Get points indices inside a rectangular area.
389
- * @param selection - Array of two corner points `[[left, top], [right, bottom]]`.
390
- * The `left` and `right` coordinates should be from 0 to the width of the canvas.
391
- * The `top` and `bottom` coordinates should be from 0 to the height of the canvas.
392
- * @returns A Float32Array containing the indices of points inside a rectangular area.
391
+ * Find point indices inside a rectangular area.
392
+ *
393
+ * **Important:** This method is synchronous and must only be called when the graph is ready.
394
+ * Ensure `await graph.ready` has resolved (or use the result inside `graph.ready.then(...)`) before
395
+ * calling. If called before initialization completes, returns an empty array.
396
+ *
397
+ * @param rect - Array of two corner points `[[left, top], [right, bottom]]`.
398
+ * The coordinates should be from 0 to the width/height of the canvas.
399
+ * @returns Array of point indices inside the rectangle.
393
400
  */
394
- getPointsInRect(selection: [[number, number], [number, number]]): Float32Array;
401
+ findPointsInRect(rect: [[number, number], [number, number]]): number[];
395
402
  /**
396
- * Get points indices inside a polygon area.
397
- * @param polygonPath - Array of points `[[x1, y1], [x2, y2], ..., [xn, yn]]` that defines the polygon.
398
- * The coordinates should be from 0 to the width/height of the canvas.
399
- * @returns A Float32Array containing the indices of points inside the polygon area.
400
- */
401
- getPointsInPolygon(polygonPath: [number, number][]): Float32Array;
402
- /** Select points inside a rectangular area.
403
- * @param selection - Array of two corner points `[[left, top], [right, bottom]]`.
404
- * The `left` and `right` coordinates should be from 0 to the width of the canvas.
405
- * The `top` and `bottom` coordinates should be from 0 to the height of the canvas. */
406
- selectPointsInRect(selection: [[number, number], [number, number]] | null): void;
407
- /** Select points inside a polygon area.
403
+ * Find point indices inside a polygon area.
404
+ *
405
+ * **Important:** This method is synchronous and must only be called when the graph is ready.
406
+ * Ensure `await graph.ready` has resolved (or use the result inside `graph.ready.then(...)`) before
407
+ * calling. If called before initialization completes, returns an empty array.
408
+ *
408
409
  * @param polygonPath - Array of points `[[x1, y1], [x2, y2], ..., [xn, yn]]` that defines the polygon.
409
410
  * The coordinates should be from 0 to the width/height of the canvas.
410
- * Set to null to clear selection. */
411
- selectPointsInPolygon(polygonPath: [number, number][] | null): void;
412
- /**
413
- * Select a point by index. If you want the adjacent points to get selected too, provide `true` as the second argument.
414
- * @param index The index of the point in the array of points.
415
- * @param selectAdjacentPoints When set to `true`, selects adjacent points (`false` by default).
411
+ * @returns Array of point indices inside the polygon.
416
412
  */
417
- selectPointByIndex(index: number, selectAdjacentPoints?: boolean): void;
413
+ findPointsInPolygon(polygonPath: [number, number][]): number[];
418
414
  /**
419
- * Select multiples points by their indices.
420
- * @param indices Array of points indices.
415
+ * Get point indices that are neighbors of the given point(s) — connected by a link in either direction.
416
+ * @param pointIndices A single point index or an array of point indices.
417
+ * @returns Deduplicated array of neighboring point indices.
421
418
  */
422
- selectPointsByIndices(indices?: (number | undefined)[] | null): void;
419
+ getNeighboringPointIndices(pointIndices: number | number[]): number[];
423
420
  /**
424
- * Unselect all points.
421
+ * Get link indices where both endpoints are within the given point(s).
422
+ * @param pointIndices A single point index or an array of point indices.
423
+ * @returns Deduplicated array of link indices connecting points within the provided set.
425
424
  */
426
- unselectPoints(): void;
425
+ getConnectedLinkIndices(pointIndices: number | number[]): number[];
427
426
  /**
428
- * Get indices of points that are currently selected.
429
- * @returns Array of selected indices of points.
427
+ * Get point indices at the endpoints of the given link(s).
428
+ * @param linkIndices A single link index or an array of link indices.
429
+ * @returns Deduplicated array of point indices at the ends of the provided links.
430
430
  */
431
- getSelectedIndices(): number[] | null;
432
- /**
433
- * Get indices that are adjacent to a specific point by its index.
434
- * @param index Index of the point.
435
- * @returns Array of adjacent indices.
436
- */
437
- getAdjacentIndices(index: number): number[] | undefined;
431
+ getConnectedPointIndices(linkIndices: number | number[]): number[];
438
432
  /**
439
433
  * Converts the X and Y point coordinates from the space coordinate system to the screen coordinate system.
440
434
  * @param spacePosition Array of x and y coordinates in the space coordinate system.
@@ -528,6 +522,9 @@ export declare class Graph {
528
522
  /**
529
523
  * Start the simulation.
530
524
  * This only controls the simulation state, not rendering.
525
+ * If the simulation is already running, calling `start(alpha)` reheats it by
526
+ * resetting `alpha` and `simulationProgress` without firing
527
+ * `onSimulationStart` again.
531
528
  * @param alpha Value from 0 to 1. The higher the value, the more initial energy the simulation will get.
532
529
  */
533
530
  start(alpha?: number): void;
@@ -575,15 +572,20 @@ export declare class Graph {
575
572
  */
576
573
  pair(pointPositions: number[]): [number, number][];
577
574
  /**
578
- * Restores init-only fields (`enableSimulation`, `initialZoomLevel`, `randomSeed`, `attribution`)
575
+ * Restores init-only fields (`initialZoomLevel`, `randomSeed`, `attribution`)
579
576
  * to their pre-update values, preventing runtime changes via setConfig/setConfigPartial.
580
577
  */
581
578
  private preserveInitOnlyFields;
579
+ private getFitViewPositions;
582
580
  /**
583
581
  * Compares the previous config snapshot with the current `this.config` and
584
582
  * applies any necessary side effects (updating renderers, store, behaviors, etc.).
585
583
  */
586
584
  private updateStateFromConfig;
585
+ /**
586
+ * Applies `enableSimulation` lifecycle changes triggered by config updates.
587
+ */
588
+ private applyEnableSimulationConfigChange;
587
589
  /**
588
590
  * Ensures device is initialized before executing a method.
589
591
  * If device is not ready, queues the method to run after initialization.
@@ -623,6 +625,8 @@ export declare class Graph {
623
625
  */
624
626
  private runSimulationStep;
625
627
  private initPrograms;
628
+ private ensureSimulationModules;
629
+ private destroySimulationModules;
626
630
  /**
627
631
  * The rendering loop - schedules itself to run continuously
628
632
  */
@@ -649,12 +653,15 @@ export declare class Graph {
649
653
  private resizeCanvas;
650
654
  private updateZoomDragBehaviors;
651
655
  private findHoveredItem;
656
+ /** Detect hovered point and update store state. Returns flags for deferred callback firing. */
652
657
  private findHoveredPoint;
658
+ /** Detect hovered link and update store state. Returns flags for deferred callback firing. */
653
659
  private findHoveredLine;
654
660
  private updateCanvasCursor;
655
661
  private addAttribution;
656
662
  }
657
663
  export type { GraphConfig } from './config';
658
664
  export { PointShape } from './modules/GraphData';
665
+ export { TransitionEasing } from './modules/Transition';
659
666
  export * from './variables';
660
667
  export * from './helper';