@graphty/graphty-element 2.3.1 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/AGENTS.md +4 -3
  2. package/dist/ai.js +3 -3
  3. package/dist/catalog.js +28 -27
  4. package/dist/chunks/{AiManager-BBmGJbH4.js → AiManager-DNJCoeTO.js} +5 -5
  5. package/dist/chunks/{DataSource-OeN3NeyD.js → DataSource-xL3Yn0Pa.js} +72 -61
  6. package/dist/chunks/{GraphSession-Bef1AYw9.js → GraphSession-PFm2tJ_j.js} +2942 -2822
  7. package/dist/chunks/{GraphtyLogger-5KEttFUo.js → GraphtyLogger-kbOx2zq3.js} +170 -222
  8. package/dist/chunks/{NodeStyle-DKj7HjMJ.js → NodeStyle-CtmA7dXi.js} +16 -14
  9. package/dist/chunks/{VoiceInputAdapter-Dr9Gcmds.js → VoiceInputAdapter-CDNKQgUK.js} +1 -1
  10. package/dist/chunks/{XRPivotCameraController-BbfgZWpS.js → XRPivotCameraController-JdlLBcD7.js} +146 -134
  11. package/dist/chunks/{algorithms-CpX56sUB.js → algorithms-B87OPYw4.js} +780 -635
  12. package/dist/chunks/{capability-check-Blhb2aBB.js → capability-check-B2oYf_30.js} +1 -1
  13. package/dist/chunks/{detect-Cqwshr9a.js → detect-tuYQLJbT.js} +2 -2
  14. package/dist/chunks/{format-detection-BXGO1lSn.js → format-detection-BG6CMwPO.js} +1 -1
  15. package/dist/chunks/{index-C0mIoumR.js → index-6GDfNfwJ.js} +3185 -2731
  16. package/dist/chunks/{optionsFromZod-17lkrAJs.js → optionsFromZod-DHLLiX_8.js} +275 -267
  17. package/dist/chunks/{paletteRegistry-x7WOEKZY.js → paletteRegistry-jg9uS7wo.js} +72 -70
  18. package/dist/chunks/pluginRegistry-MaTIDh6l.js +238 -0
  19. package/dist/chunks/{registry-CSba5QGJ.js → registry-DQeq4B2K.js} +8 -8
  20. package/dist/chunks/{scales-BRwl51k8.js → scales-BXHmwPXC.js} +572 -399
  21. package/dist/chunks/{types-B7bX5c0K.js → types-C_c53VgR.js} +31 -26
  22. package/dist/commands.d.ts +4 -0
  23. package/dist/custom-elements.json +1 -1
  24. package/dist/extend.js +8 -8
  25. package/dist/graphty-catalog.json +245 -12
  26. package/dist/graphty.bundle.js +37843 -36551
  27. package/dist/graphty.js +69 -65
  28. package/dist/index.d.ts +3 -0
  29. package/dist/logging.js +2 -2
  30. package/dist/schema.d.ts +1 -1
  31. package/dist/schema.js +42 -40
  32. package/dist/session.js +6 -6
  33. package/dist/src/Edge.d.ts +4 -4
  34. package/dist/src/Graph.d.ts +79 -7
  35. package/dist/src/acceleration/AccelerationController.d.ts +20 -3
  36. package/dist/src/acceleration/registry.d.ts +3 -0
  37. package/dist/src/acceleration/types.d.ts +85 -0
  38. package/dist/src/algorithms/Algorithm.d.ts +13 -0
  39. package/dist/src/algorithms/KCoreAlgorithm.d.ts +26 -0
  40. package/dist/src/algorithms/LinkPredictionAlgorithm.d.ts +41 -0
  41. package/dist/src/cameras/InputUtils.d.ts +67 -0
  42. package/dist/src/cameras/XRInputHandler.d.ts +0 -8
  43. package/dist/src/catalog/algorithms.d.ts +5 -5
  44. package/dist/src/catalog/index.d.ts +2 -2
  45. package/dist/src/catalog/layouts.d.ts +7 -6
  46. package/dist/src/catalog/pluginRegistry.d.ts +62 -0
  47. package/dist/src/catalog/registry.d.ts +7 -0
  48. package/dist/src/catalog/types.d.ts +77 -6
  49. package/dist/src/config/EdgeStyle.d.ts +35 -0
  50. package/dist/src/config/index.d.ts +1 -1
  51. package/dist/src/data/DataSource.d.ts +1 -1
  52. package/dist/src/data/GEXFDataSource.d.ts +23 -0
  53. package/dist/src/errors/codes.d.ts +16 -1
  54. package/dist/src/events.d.ts +30 -0
  55. package/dist/src/graphty-element.d.ts +66 -26
  56. package/dist/src/layout/GridLayoutEngine.d.ts +37 -0
  57. package/dist/src/layout/LayoutEngine.d.ts +7 -7
  58. package/dist/src/layout/NGraphLayoutEngine.d.ts +2 -0
  59. package/dist/src/layout/RadialLayoutEngine.d.ts +37 -0
  60. package/dist/src/layout/SimulationLayoutEngine.d.ts +12 -0
  61. package/dist/src/managers/DataManager.d.ts +69 -2
  62. package/dist/src/managers/EventManager.d.ts +10 -4
  63. package/dist/src/managers/GraphContext.d.ts +2 -1
  64. package/dist/src/managers/LayoutManager.d.ts +30 -3
  65. package/dist/src/meshes/CustomLineRenderer.d.ts +11 -9
  66. package/dist/src/meshes/EdgeMesh.d.ts +18 -9
  67. package/dist/src/meshes/FilledArrowRenderer.d.ts +61 -23
  68. package/dist/src/meshes/MeshCache.d.ts +18 -0
  69. package/dist/src/meshes/NodeEffects.d.ts +16 -11
  70. package/dist/src/meshes/NodeMesh.d.ts +2 -2
  71. package/dist/src/meshes/PatternedLineRenderer.d.ts +5 -37
  72. package/dist/src/meshes/PerSceneMaterials.d.ts +49 -0
  73. package/dist/src/meshes/RichTextParser.d.ts +26 -0
  74. package/dist/src/meshes/RichTextRenderer.d.ts +0 -1
  75. package/dist/src/session/cost/estimate.d.ts +1 -1
  76. package/dist/src/session/layout.d.ts +3 -3
  77. package/dist/src/session/runs/RunsApi.d.ts +1 -1
  78. package/dist/src/session/styles/StylesApi.d.ts +6 -0
  79. package/dist/src/session/styles/intern.d.ts +26 -5
  80. package/dist/src/session/styles/repaint.d.ts +2 -1
  81. package/dist/src/session/types.d.ts +6 -6
  82. package/dist/src/xr/XRSessionManager.d.ts +1 -1
  83. package/dist/webgpu.d.ts +8 -0
  84. package/dist/webgpu.js +2 -2
  85. package/package.json +6 -6
  86. package/dist/chunks/GraphtyError-BwcnblTH.js +0 -132
@@ -3,6 +3,14 @@ type GEXFDataSourceConfig = BaseDataSourceConfig;
3
3
  /**
4
4
  * Data source for loading graph data from GEXF (Graph Exchange XML Format) files.
5
5
  * Supports node and edge attributes, attribute types, and dynamic graphs.
6
+ *
7
+ * Dynamic graphs keep their time data on each record rather than acting on it:
8
+ * - a node's or edge's `start` / `end` / `timestamp` (see {@link readInterval}) go onto its data
9
+ * under those names, and its `<spells>` go onto `spells` as a list of the same intervals;
10
+ * - an attribute with time-sliced `attvalue`s becomes a list of `{ value, start, end }` slices
11
+ * instead of a single value. An attribute with no timed `attvalue` keeps its plain value.
12
+ *
13
+ * Dynamic `viz:*` elements (timed positions, colours or sizes) are not read.
6
14
  */
7
15
  export declare class GEXFDataSource extends DataSource {
8
16
  static readonly type = "gexf";
@@ -60,6 +68,21 @@ export declare class GEXFDataSource extends DataSource {
60
68
  * @returns the edge records, and how many edges stated each direction
61
69
  */
62
70
  private parseEdges;
71
+ /**
72
+ * Copy a node's or edge's lifetime, spells and attribute values onto its record.
73
+ *
74
+ * Every `attvalue` for one attribute is kept: if any of them is timed, the attribute becomes
75
+ * the list of all its slices, `{ value, start, end }`, in file order; otherwise it keeps its
76
+ * plain value, so a static file reads exactly as it always has.
77
+ * @param obj - the parsed `<node>` or `<edge>`
78
+ * @param obj.attvalues - its `<attvalues>` element, if any
79
+ * @param obj.attvalues.attvalue - the `<attvalue>` children
80
+ * @param obj.spells - its `<spells>` element, if any
81
+ * @param obj.spells.spell - the `<spell>` children
82
+ * @param record - the record being built, written in place
83
+ * @param attributes - the attribute definitions for this element class
84
+ */
85
+ private readTimeData;
63
86
  private parseValue;
64
87
  }
65
88
  export {};
@@ -163,7 +163,8 @@ export type GraphtyErrorCode =
163
163
  /**
164
164
  * A source could not be fetched: a network failure, a non-2xx status, a CORS refusal or an
165
165
  * unreadable file. `details` carry the url and the status where there was one, and `cause`
166
- * carries the original failure. Usually recoverable by retrying.
166
+ * carries the original failure. Recoverable by retrying, except a client error (a 4xx other
167
+ * than 408 and 429), which fails after one request with `recoverable: false`.
167
168
  */
168
169
  | "E_FETCH_FAILED"
169
170
  /**
@@ -185,6 +186,20 @@ export type GraphtyErrorCode =
185
186
  * import plan or the data.
186
187
  */
187
188
  | "E_ID_MISSING"
189
+ /**
190
+ * A load read its source to the end and found nothing in it: no node records and no edge
191
+ * records. It is reported as a failure rather than as a success with zero counts, and a
192
+ * load asked to `replace` keeps the graph it would have replaced. `details` carry the
193
+ * format. The caller checks the file, or the format it was read as.
194
+ */
195
+ | "E_EMPTY_LOAD"
196
+ /**
197
+ * A load was overtaken: a REPLACING load was called after it, or `clearData` ran, so its data
198
+ * would have replaced or mixed into the newer dataset. It stops without touching the graph.
199
+ * `details` carry the format. Not a fault in the source; the caller ignores it, or loads
200
+ * again.
201
+ */
202
+ | "E_SUPERSEDED"
188
203
  /**
189
204
  * The graph exceeds a hard structural limit of an index or of the accelerator, and no scope
190
205
  * or sample makes the work runnable. `details` carry the size and the limit. Distinct from
@@ -56,6 +56,12 @@ export interface GraphDataLoadedEvent {
56
56
  dataSourceType: string;
57
57
  /** What the load did: the endpoint spelling it resolved, and the counts it produced. */
58
58
  report: ImportReport;
59
+ /**
60
+ * Which load this is about: the id `addDataFromSource`, `loadFromFile` and `loadFromUrl`
61
+ * resolve to, and that every event about one load carries. Absent on a report about records
62
+ * handed to a setter, which is not a load.
63
+ */
64
+ loadId?: number;
59
65
  };
60
66
  }
61
67
  export interface GraphDataAddedEvent {
@@ -155,6 +161,12 @@ export interface DataLoadingProgressEvent {
155
161
  */
156
162
  edgeRecordsLoaded: number;
157
163
  chunksProcessed: number;
164
+ /**
165
+ * Which load this is about: the id `addDataFromSource`, `loadFromFile` and `loadFromUrl`
166
+ * resolve to, and that every event about one load carries. Absent on a report about records
167
+ * handed to a setter, which is not a load.
168
+ */
169
+ loadId?: number;
158
170
  }
159
171
  export interface DataLoadingErrorEvent {
160
172
  type: "data-loading-error";
@@ -165,6 +177,12 @@ export interface DataLoadingErrorEvent {
165
177
  nodeId?: unknown;
166
178
  edgeId?: string;
167
179
  canContinue: boolean;
180
+ /**
181
+ * Which load this is about: the id `addDataFromSource`, `loadFromFile` and `loadFromUrl`
182
+ * resolve to, and that every event about one load carries. Absent on a report about records
183
+ * handed to a setter, which is not a load.
184
+ */
185
+ loadId?: number;
168
186
  }
169
187
  export interface DataLoadingErrorSummaryEvent {
170
188
  type: "data-loading-error-summary";
@@ -174,6 +192,12 @@ export interface DataLoadingErrorSummaryEvent {
174
192
  message: string;
175
193
  suggestion?: string;
176
194
  detailedReport: string;
195
+ /**
196
+ * Which load this is about: the id `addDataFromSource`, `loadFromFile` and `loadFromUrl`
197
+ * resolve to, and that every event about one load carries. Absent on a report about records
198
+ * handed to a setter, which is not a load.
199
+ */
200
+ loadId?: number;
177
201
  }
178
202
  export interface DataLoadingCompleteEvent {
179
203
  type: "data-loading-complete";
@@ -203,6 +227,12 @@ export interface DataLoadingCompleteEvent {
203
227
  success: boolean;
204
228
  /** What the load did: the endpoint spelling, the repeat policy, and every count. */
205
229
  report: ImportReport;
230
+ /**
231
+ * Which load this is about: the id `addDataFromSource`, `loadFromFile` and `loadFromUrl`
232
+ * resolve to, and that every event about one load carries. Absent on a report about records
233
+ * handed to a setter, which is not a load.
234
+ */
235
+ loadId?: number;
206
236
  }
207
237
  /**
208
238
  * Emitted once per `removeNodes` call, naming everything that went.
@@ -122,8 +122,9 @@ export declare class Graphty extends LitElement {
122
122
  /**
123
123
  * Array of node data objects to visualize.
124
124
  * @remarks
125
- * Setting this property replaces all existing nodes. For incremental
126
- * updates, use the `graph.addNodes()` method instead.
125
+ * Setting this property REPLACES all existing nodes: a node whose id is
126
+ * not in the new array is removed, with the edges attached to it. For
127
+ * incremental updates, use the `addNodes()` method instead.
127
128
  *
128
129
  * Each node object should have an ID field (default: "id"). Additional
129
130
  * properties can be used in style selectors and accessed via `node.data`.
@@ -148,7 +149,7 @@ export declare class Graphty extends LitElement {
148
149
  */
149
150
  get nodeData(): Record<string, unknown>[] | undefined;
150
151
  /**
151
- * Sets the node data array. Triggers addition of nodes to the graph.
152
+ * Sets the node data array. Replaces the graph's nodes with these.
152
153
  */
153
154
  set nodeData(value: Record<string, unknown>[] | undefined);
154
155
  /**
@@ -190,7 +191,8 @@ export declare class Graphty extends LitElement {
190
191
  */
191
192
  get dataSource(): string | undefined;
192
193
  /**
193
- * Sets the data source type. Initializes data loading when combined with dataSourceConfig.
194
+ * Sets the data source type. Starts a load when combined with dataSourceConfig; see
195
+ * `dataSourceConfig` for what a second assignment does.
194
196
  */
195
197
  set dataSource(value: string | undefined);
196
198
  /**
@@ -200,18 +202,23 @@ export declare class Graphty extends LitElement {
200
202
  */
201
203
  get dataSourceConfig(): Record<string, unknown> | undefined;
202
204
  /**
203
- * Sets the data source configuration. Initializes data loading when combined with dataSource.
205
+ * Sets the data source configuration. Starts a load when combined with dataSource.
206
+ *
207
+ * Every assignment of the pair starts a load, and assigning both halves in one task starts
208
+ * one. Assigning the pair already loaded -- the same type and the same config object --
209
+ * starts none, unless that load failed; pass a new object to load again. The first load adds
210
+ * to the graph; each later one REPLACES it, but only once the new source has parsed -- a
211
+ * malformed or empty source leaves the graph as it was and reports `data-loading-error`.
212
+ * The pair assigned LAST wins: a slower earlier load that finishes afterwards is dropped.
213
+ * Every event about the load carries its `loadId`. A caller that wants to await the load
214
+ * calls `loadFromUrl`, `loadFromFile` or `addDataFromSource` instead.
204
215
  */
205
216
  set dataSourceConfig(value: Record<string, unknown> | undefined);
206
217
  /**
207
- * Removes every node and edge, and lets a later data source load.
218
+ * Removes every node and edge, and forgets the data-source pair. A load still in flight is
219
+ * abandoned: it rejects with `E_SUPERSEDED` and adds nothing.
208
220
  *
209
- * The guard below is per LOAD, not per element lifetime. Latching it for the
210
- * element's whole life refused every dataset after the first: a second
211
- * `dataSource` / `dataSourceConfig` assignment set both properties and started no
212
- * load, so a host that loaded a second file saw the element report the new source
213
- * while the old graph stayed on screen. Clearing the data is the statement that the
214
- * previous load is over, so it is where the guard resets.
221
+ * The next pair assigned after it loads into an empty graph, as the first one did.
215
222
  *
216
223
  * The two properties are reset with it, and deliberately through the private fields
217
224
  * rather than the setters: a setter would call `#tryInitializeDataSource` again, and
@@ -1043,16 +1050,27 @@ export declare class Graphty extends LitElement {
1043
1050
  }[], options?: import("./utils/queue-migration").QueueableOptions): Promise<void>;
1044
1051
  /**
1045
1052
  * Add data from a data source.
1053
+ *
1054
+ * Every load has an id: the promise resolves to it, and every load event about this load
1055
+ * (`data-loading-progress`, `data-loading-complete`, `data-loading-error`, `data-loaded`)
1056
+ * carries it as `loadId`. A source with no nodes and no edges rejects with `E_EMPTY_LOAD`.
1046
1057
  * @param type - Data source type (e.g., "json", "csv", "graphml")
1047
1058
  * @param opts - Data source configuration options
1048
- * @returns Promise that resolves when data is loaded
1059
+ * @param options - How to load
1060
+ * @param options.replace - Replace the graph with this data, but only once it has all parsed:
1061
+ * a malformed or empty source rejects and leaves the current graph untouched
1062
+ * @returns Promise that resolves to `{ loadId }` when data is loaded
1049
1063
  * @since 1.5.0
1050
1064
  * @example
1051
1065
  * ```typescript
1052
- * await element.addDataFromSource('json', { url: 'https://example.com/data.json' });
1066
+ * const { loadId } = await element.addDataFromSource('json', { url: 'https://example.com/data.json' });
1053
1067
  * ```
1054
1068
  */
1055
- addDataFromSource(type: string, opts?: object): Promise<void>;
1069
+ addDataFromSource(type: string, opts?: object, options?: {
1070
+ replace?: boolean;
1071
+ }): Promise<{
1072
+ loadId: number;
1073
+ }>;
1056
1074
  /**
1057
1075
  * Load graph data from a URL.
1058
1076
  * @param url - URL to fetch graph data from
@@ -1062,7 +1080,9 @@ export declare class Graphty extends LitElement {
1062
1080
  * @param options.edgeSource - Where the node an edge starts at is named in the record. Left
1063
1081
  * unset, the element reads `source`, then `src`, then `from`
1064
1082
  * @param options.edgeTarget - Where the node an edge ends at is named in the record
1065
- * @returns Promise that resolves when data is loaded
1083
+ * @param options.replace - Replace the graph with this data, but only once it has all parsed:
1084
+ * a malformed or empty file rejects and leaves the current graph untouched
1085
+ * @returns Promise that resolves to `{ loadId }`, the id every event about this load carries
1066
1086
  * @since 1.5.0
1067
1087
  * @example
1068
1088
  * ```typescript
@@ -1074,7 +1094,10 @@ export declare class Graphty extends LitElement {
1074
1094
  nodeIdPath?: string;
1075
1095
  edgeSource?: string;
1076
1096
  edgeTarget?: string;
1077
- }): Promise<void>;
1097
+ replace?: boolean;
1098
+ }): Promise<{
1099
+ loadId: number;
1100
+ }>;
1078
1101
  /**
1079
1102
  * Load graph data from a File object.
1080
1103
  * @param file - File object from file input
@@ -1084,7 +1107,9 @@ export declare class Graphty extends LitElement {
1084
1107
  * @param options.edgeSource - Where the node an edge starts at is named in the record. Left
1085
1108
  * unset, the element reads `source`, then `src`, then `from`
1086
1109
  * @param options.edgeTarget - Where the node an edge ends at is named in the record
1087
- * @returns Promise that resolves when data is loaded
1110
+ * @param options.replace - Replace the graph with this data, but only once it has all parsed:
1111
+ * a malformed or empty file rejects and leaves the current graph untouched
1112
+ * @returns Promise that resolves to `{ loadId }`, the id every event about this load carries
1088
1113
  * @since 1.5.0
1089
1114
  * @example
1090
1115
  * ```typescript
@@ -1098,7 +1123,10 @@ export declare class Graphty extends LitElement {
1098
1123
  nodeIdPath?: string;
1099
1124
  edgeSource?: string;
1100
1125
  edgeTarget?: string;
1101
- }): Promise<void>;
1126
+ replace?: boolean;
1127
+ }): Promise<{
1128
+ loadId: number;
1129
+ }>;
1102
1130
  /**
1103
1131
  * Pin nodes where they are, so no layout moves them again.
1104
1132
  *
@@ -1279,6 +1307,10 @@ export declare class Graphty extends LitElement {
1279
1307
  * result shape derives. This is the verb for a run started with `{ style: false }`, or for
1280
1308
  * putting a picture back after a reader cleared it. Applying twice replaces the layer bound
1281
1309
  * to that run and channel rather than stacking a second one on it.
1310
+ *
1311
+ * It starts the style edits and returns at once. To wait for the picture -- for a
1312
+ * screenshot, an export or a test -- await `waitForStableFrame()` after the call: it
1313
+ * settles only once every suggested layer is added, stacked in the order named and painted.
1282
1314
  * @param algorithmKey - A catalogue key such as "degree", a 1.10 address such as
1283
1315
  * "graphty:degree", or an array of either.
1284
1316
  * @returns True if anything was applied, false when no finished run of that algorithm has
@@ -1288,6 +1320,7 @@ export declare class Graphty extends LitElement {
1288
1320
  * ```typescript
1289
1321
  * await element.run('degree', undefined, { style: false });
1290
1322
  * element.applySuggestedStyles('degree');
1323
+ * await element.waitForStableFrame();
1291
1324
  * ```
1292
1325
  */
1293
1326
  applySuggestedStyles(algorithmKey: string | string[]): boolean;
@@ -1307,7 +1340,10 @@ export declare class Graphty extends LitElement {
1307
1340
  getSuggestedStyles(algorithmKey: string): readonly import("./session/styles").StyleSuggestion[];
1308
1341
  /**
1309
1342
  * Set the layout algorithm.
1310
- * @param type - Layout algorithm name
1343
+ *
1344
+ * Takes a layout id from `catalog.layouts()` (such as `"force"`), which runs that layout's
1345
+ * default engine, or a registered engine name (such as `"ngraph"`).
1346
+ * @param type - Layout id or engine name
1311
1347
  * @param opts - Layout-specific options
1312
1348
  * @param options - Queue options
1313
1349
  * @returns Promise that resolves when layout is initialized
@@ -1315,6 +1351,7 @@ export declare class Graphty extends LitElement {
1315
1351
  * @example
1316
1352
  * ```typescript
1317
1353
  * await element.setLayout('circular', { radius: 5 });
1354
+ * await element.setLayout('force'); // the catalogue id; runs the "ngraph" engine
1318
1355
  * await element.setLayout('ngraph', { springLength: 100 });
1319
1356
  * ```
1320
1357
  */
@@ -1546,9 +1583,11 @@ export declare class Graphty extends LitElement {
1546
1583
  * camera, picking and styling stay live. There is no event for this: `isRunning()` reports
1547
1584
  * the state and `graph-settled` reports the arrangement coming to rest.
1548
1585
  *
1549
- * A pause is not a mode the element remembers: anything that (re)starts a layout -- loading
1550
- * more nodes, an accelerator attaching, setting another layout, dropping a dragged node --
1551
- * runs it again, so pause it after those, not before.
1586
+ * A pause holds until `setRunning(true)`. Loading more nodes, a freeze, an accelerator
1587
+ * attaching, setting another layout and dragging a node all still happen -- new nodes are
1588
+ * placed and a dragged node moves -- but none of them resumes the layout. To tell a paused,
1589
+ * half-finished arrangement from a converged one, read `getLayoutManager().isPaused` and
1590
+ * `isSettled`.
1552
1591
  * @param running - True to run the layout, false to pause it.
1553
1592
  * @since 2.0.0
1554
1593
  * @example
@@ -1910,9 +1949,10 @@ export declare class Graphty extends LitElement {
1910
1949
  * The node count at or above which accelerated work uses the accelerator.
1911
1950
  *
1912
1951
  * Below it the element takes the CPU path even with an accelerator attached, and
1913
- * `capabilities.acceleration.state` reads `"idle"`. Default 0: use the accelerator whenever
1914
- * there is one. Raise it when the graphs you show are small enough that uploading costs more
1915
- * than computing; the number is machine-specific, which is why the element does not guess.
1952
+ * `capabilities.acceleration.state` reads `"idle"`. Unset, layouts use the accelerator
1953
+ * whenever there is one and each algorithm keeps a built-in floor measured on one card (see
1954
+ * the acceleration guide). Any value you set, including 0, replaces those floors for every
1955
+ * layout and algorithm; set it when you have measured the machine your graphs are drawn on.
1916
1956
  * @since 2.0.0
1917
1957
  * @example
1918
1958
  * ```html
@@ -0,0 +1,37 @@
1
+ import { z } from "zod/v4";
2
+ import { type OptionsSchema } from "../config";
3
+ import { SimpleLayoutEngine } from "./LayoutEngine";
4
+ declare const GridLayoutConfig: z.ZodObject<{
5
+ columns: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
6
+ scale: z.ZodDefault<z.ZodNumber>;
7
+ center: z.ZodDefault<z.ZodUnion<[z.ZodArray<z.ZodNumber>, z.ZodNull]>>;
8
+ scalingFactor: z.ZodDefault<z.ZodNumber>;
9
+ }, z.core.$strict>;
10
+ type GridLayoutConfigType = z.infer<typeof GridLayoutConfig>;
11
+ type GridLayoutOpts = Partial<GridLayoutConfigType>;
12
+ /**
13
+ * Grid layout engine that places nodes in rows and columns on an evenly spaced lattice
14
+ */
15
+ export declare class GridLayout extends SimpleLayoutEngine {
16
+ static type: string;
17
+ static maxDimensions: number;
18
+ static zodOptionsSchema: OptionsSchema;
19
+ scalingFactor: number;
20
+ config: GridLayoutConfigType;
21
+ /**
22
+ * Create a grid layout engine
23
+ * @param opts - Configuration options including the column count
24
+ */
25
+ constructor(opts: GridLayoutOpts);
26
+ /**
27
+ * Get dimension-specific options for grid layout
28
+ * @param dimension - The desired dimension (2 or 3)
29
+ * @returns Empty object for 2D, null for 3D (unsupported)
30
+ */
31
+ static getOptionsForDimension(dimension: 2 | 3): object | null;
32
+ /**
33
+ * Compute node positions on the lattice
34
+ */
35
+ doLayout(): void;
36
+ }
37
+ export {};
@@ -48,15 +48,15 @@ export interface LayoutEngineStatics {
48
48
  /**
49
49
  * Whether this engine arranges a graph differently when its edges carry weights.
50
50
  *
51
- * Optional, and false for all but two of the element's own seventeen. It exists so that a
51
+ * Optional, and false for all but two of the element's own nineteen. It exists so that a
52
52
  * picker can tell a reader which arrangements the `weighted` option actually does something
53
- * for, instead of offering it on fifteen layouts that ignore it.
53
+ * for, instead of offering it on seventeen layouts that ignore it.
54
54
  */
55
55
  honoursWeights?: boolean;
56
56
  /**
57
57
  * What the catalogue publishes about this layout, so a picker can offer it.
58
58
  *
59
- * REQUIRED OF A THIRD PARTY'S ENGINE and absent from the element's own seventeen, whose
59
+ * REQUIRED OF A THIRD PARTY'S ENGINE and absent from the element's own nineteen, whose
60
60
  * arrangements are authored in `src/catalog/layouts.ts` instead. `descriptor.id` must equal
61
61
  * {@link LayoutEngineStatics.type}: one key, so nothing is named twice and `layoutIdForEngine`
62
62
  * can answer a plugin's own id.
@@ -94,7 +94,7 @@ export declare abstract class LayoutEngine {
94
94
  * Whether this engine reads edge weights. See {@link LayoutEngineStatics.honoursWeights}.
95
95
  *
96
96
  * False here because most layouts have no weight channel at all: of the element's own
97
- * seventeen, only Kamada-Kawai and ForceAtlas2 can read one, and the other fifteen would be
97
+ * nineteen, only Kamada-Kawai and ForceAtlas2 can read one, and the other seventeen would be
98
98
  * advertising a control that changes nothing.
99
99
  */
100
100
  static honoursWeights: boolean;
@@ -162,7 +162,7 @@ export declare abstract class LayoutEngine {
162
162
  * Take a node out of the layout, before the element disposes the mesh that drew it.
163
163
  *
164
164
  * Declared here, with a default that does nothing, because it used to be duck-typed by the
165
- * element's data manager and implemented by none of the seventeen engines that ship here: an
165
+ * element's data manager and implemented by none of the nineteen engines that ship here: an
166
166
  * author learned it existed by reading the element's source, and got no worked example. An
167
167
  * engine that keeps its own node list must override this, or it holds every removed node --
168
168
  * and everything that node references -- for as long as the engine lives.
@@ -260,7 +260,7 @@ export declare abstract class LayoutEngine {
260
260
  * freeze counts as placed, which is what makes a file's own coordinates yield to it.
261
261
  *
262
262
  * A PINNED ROW REFUSES A LAYOUT STEP. This is the whole of "a pin is meaningful under every
263
- * arrangement": twelve of the element's seventeen engines implement `pin()` as a no-op and
263
+ * arrangement": fourteen of the element's nineteen engines implement `pin()` as a no-op and
264
264
  * `setNodePosition` as a no-op too, so before this guard a reader who dragged a node under a
265
265
  * static layout watched it snap back the next time the layout recomputed. One refusal here
266
266
  * covers every engine, including one written by a third party that has never heard of pinning,
@@ -351,7 +351,7 @@ export declare abstract class LayoutEngine {
351
351
  * offered by a picker, described in a reader's language, or found by `layoutIdForEngine`.
352
352
  *
353
353
  * A third party's class must declare a `static descriptor` whose `id` equals its
354
- * `static type`. The element's own seventeen are the one exemption, because their arrangements
354
+ * `static type`. The element's own nineteen are the one exemption, because their arrangements
355
355
  * are authored centrally in the layout catalogue where several engines may sit behind one
356
356
  * public name.
357
357
  * @param cls - The layout engine class.
@@ -24,6 +24,8 @@ export declare class NGraphEngine extends LayoutEngine {
24
24
  _settled: boolean;
25
25
  _stepCount: number;
26
26
  _lastMoves: number[];
27
+ /** Places each new node when `seed` is set; null leaves placement to ngraph. */
28
+ private seededPlacement;
27
29
  /**
28
30
  * Create an NGraph layout engine
29
31
  * @param config - Configuration options for the NGraph simulation
@@ -0,0 +1,37 @@
1
+ import { z } from "zod/v4";
2
+ import { type OptionsSchema } from "../config";
3
+ import { SimpleLayoutEngine } from "./LayoutEngine";
4
+ declare const RadialLayoutConfig: z.ZodObject<{
5
+ root: z.ZodDefault<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
6
+ scale: z.ZodDefault<z.ZodNumber>;
7
+ center: z.ZodDefault<z.ZodUnion<[z.ZodArray<z.ZodNumber>, z.ZodNull]>>;
8
+ scalingFactor: z.ZodDefault<z.ZodNumber>;
9
+ }, z.core.$strict>;
10
+ type RadialLayoutConfigType = z.infer<typeof RadialLayoutConfig>;
11
+ type RadialLayoutOpts = Partial<RadialLayoutConfigType>;
12
+ /**
13
+ * Radial layout engine that places nodes on rings by hop distance from a root node
14
+ */
15
+ export declare class RadialLayout extends SimpleLayoutEngine {
16
+ static type: string;
17
+ static maxDimensions: number;
18
+ static zodOptionsSchema: OptionsSchema;
19
+ scalingFactor: number;
20
+ config: RadialLayoutConfigType;
21
+ /**
22
+ * Create a radial layout engine
23
+ * @param opts - Configuration options including the root node
24
+ */
25
+ constructor(opts: RadialLayoutOpts);
26
+ /**
27
+ * Get dimension-specific options for radial layout
28
+ * @param dimension - The desired dimension (2 or 3)
29
+ * @returns Empty object for 2D, null for 3D (unsupported)
30
+ */
31
+ static getOptionsForDimension(dimension: 2 | 3): object | null;
32
+ /**
33
+ * Compute node positions on rings around the root
34
+ */
35
+ doLayout(): void;
36
+ }
37
+ export {};
@@ -323,6 +323,18 @@ export declare class SimulationLayoutEngine extends LayoutEngine {
323
323
  * @returns A promise that resolves when the batch has landed, or rejects with its failure.
324
324
  */
325
325
  stepAsync(iterations: number): Promise<void>;
326
+ /**
327
+ * Whether the manager has stopped stepping this layout -- a consumer's pause, or any other
328
+ * stop. A paused layout's work span closes once its in-flight batches land, because nothing
329
+ * is being submitted after them.
330
+ * @returns True while the layout is not being stepped.
331
+ */
332
+ get paused(): boolean;
333
+ /**
334
+ * Tells the bridge whether the manager is stepping it.
335
+ * @param value - True when the manager has stopped stepping this layout.
336
+ */
337
+ set paused(value: boolean);
326
338
  /**
327
339
  * Starts the settle count again, on a simulation that has one.
328
340
  *
@@ -112,6 +112,12 @@ export declare class DataManager implements Manager {
112
112
  private loadEndpoints;
113
113
  /** The tally the load in progress is counting into, or null outside a load. */
114
114
  private loadTally;
115
+ /**
116
+ * Bumped by every REPLACING load as it is asked for, and by `supersedeLoads`. A load that
117
+ * sees it move has been overtaken, and stops with `E_SUPERSEDED` rather than touching the
118
+ * graph: see `addDataFromSource`.
119
+ */
120
+ private replaceGeneration;
115
121
  /**
116
122
  * Creates an instance of DataManager
117
123
  * @param eventManager - Event manager for emitting data events
@@ -273,6 +279,22 @@ export declare class DataManager implements Manager {
273
279
  * @param idPath - JMESPath expression to extract node ID from data
274
280
  */
275
281
  addNode(node: AdHocData, idPath?: string): void;
282
+ /**
283
+ * The id `addNodes` reads off a node record.
284
+ * @param node - the record
285
+ * @param idPath - JMESPath expression to extract the id; the configured node id path when unset
286
+ * @returns the node's id
287
+ */
288
+ nodeIdOf(node: Record<string | number, unknown>, idPath?: string): NodeIdType;
289
+ /**
290
+ * Refuse a replacing node set the renderer cannot hold, before the replace removes anything.
291
+ *
292
+ * The node half of what {@link setEdges} decides first: the new set is counted against an
293
+ * emptied graph, so a refused replace keeps the nodes the graph had.
294
+ * @param count - how many distinct nodes the graph would hold afterwards
295
+ * @throws A `GraphtyError` with `E_TOO_LARGE` when `count` is past the ceiling
296
+ */
297
+ refuseNodeSetAboveCeiling(count: number): void;
276
298
  /**
277
299
  * Adds multiple nodes to the graph
278
300
  * @param nodes - Array of node data objects
@@ -472,12 +494,57 @@ export declare class DataManager implements Manager {
472
494
  * while the source has still declared nothing
473
495
  */
474
496
  private applyDeclaredDirection;
497
+ /**
498
+ * Reserve a load's place in line, at the moment the caller asked for it.
499
+ *
500
+ * A caller that reads a file or sniffs a URL before it loads calls this FIRST, so a load that
501
+ * was asked for later still wins however long the earlier one spends reading. A replacing load
502
+ * supersedes every load reserved before it.
503
+ * @param replace - Whether the load will replace the graph
504
+ * @returns The generation to hand to `addDataFromSource` and `throwIfSuperseded`
505
+ */
506
+ beginLoad(replace: boolean): number;
507
+ /**
508
+ * Abandon every load in flight: each rejects with `E_SUPERSEDED` and adds nothing more.
509
+ * The element's `clearData` calls this, so a load finishing after the graph was closed does
510
+ * not bring its data back.
511
+ */
512
+ supersedeLoads(): void;
513
+ /**
514
+ * Throw `E_SUPERSEDED` when a load reserved at `generation` has been overtaken.
515
+ * @param generation - What `beginLoad` returned for the load
516
+ * @param type - The load's format, for the message
517
+ */
518
+ throwIfSuperseded(generation: number, type: string): void;
475
519
  /**
476
520
  * Loads data from a registered data source
521
+ *
522
+ * A REPLACING load reads the whole source into memory before it touches the store, and only
523
+ * once the source has finished without an error does it clear the graph and add what it read.
524
+ * A malformed or empty file therefore leaves the graph it would have replaced exactly as it
525
+ * was. An additive load streams each chunk straight in, as it always has.
526
+ *
527
+ * A load that reads no node records and no edge records at all fails with `E_EMPTY_LOAD`
528
+ * rather than completing with zero counts. A file of edges alone is not empty: its endpoints
529
+ * become nodes.
530
+ *
531
+ * The load that STARTED last wins. Once a replacing load has started, every load started
532
+ * before it -- replacing or additive -- is superseded: it adds nothing more and rejects with
533
+ * `E_SUPERSEDED`, whichever order the sources finish in. A superseded load emits no
534
+ * `data-loading-error`, because nothing went wrong with its source.
477
535
  * @param type - Data source type identifier
478
536
  * @param opts - Options to pass to the data source
479
- */
480
- addDataFromSource(type: string, opts?: object): Promise<void>;
537
+ * @param load - Which load this is, for every event it emits, and whether it replaces the graph
538
+ * @param load.loadId - The id every event about this load carries
539
+ * @param load.replace - Swap the graph for what the source holds, once it has all parsed
540
+ * @param load.generation - The place `beginLoad` reserved for this load when the caller's call
541
+ * was made; left unset, the load takes its place now
542
+ */
543
+ addDataFromSource(type: string, opts?: object, load?: {
544
+ loadId?: number;
545
+ replace?: boolean;
546
+ generation?: number;
547
+ }): Promise<void>;
481
548
  /**
482
549
  * Freeze one load's counters into the report a consumer reads, and keep it for `lastImport`.
483
550
  * @param format - the data source that read the file
@@ -65,8 +65,9 @@ export declare class EventManager implements Manager {
65
65
  * @param chunksLoaded - Number of data chunks loaded
66
66
  * @param dataSourceType - Type of data source used
67
67
  * @param report - What the load did, including which endpoint spelling resolved
68
+ * @param loadId - Which load this is, when it is one
68
69
  */
69
- emitGraphDataLoaded(graph: Graph | GraphContext, chunksLoaded: number, dataSourceType: string, report: ImportReport): void;
70
+ emitGraphDataLoaded(graph: Graph | GraphContext, chunksLoaded: number, dataSourceType: string, report: ImportReport, loadId?: number): void;
70
71
  /**
71
72
  * Emits the removal event naming every node and edge one removal call took away.
72
73
  * @param nodes - the nodes that were removed
@@ -122,8 +123,9 @@ export declare class EventManager implements Manager {
122
123
  * @param nodeRecordsLoaded - How many node RECORDS the source has handed over so far
123
124
  * @param edgeRecordsLoaded - How many edge RECORDS the source has handed over so far
124
125
  * @param chunksProcessed - Number of data chunks processed
126
+ * @param loadId - Which load this is, when it is one
125
127
  */
126
- emitDataLoadingProgress(format: string, bytesProcessed: number, totalBytes: number | undefined, nodeRecordsLoaded: number, edgeRecordsLoaded: number, chunksProcessed: number): void;
128
+ emitDataLoadingProgress(format: string, bytesProcessed: number, totalBytes: number | undefined, nodeRecordsLoaded: number, edgeRecordsLoaded: number, chunksProcessed: number, loadId?: number): void;
127
129
  /**
128
130
  * Emits a data loading error event when an error occurs during import
129
131
  * @param error - Error object
@@ -134,12 +136,14 @@ export declare class EventManager implements Manager {
134
136
  * @param details.nodeId - Node ID related to error
135
137
  * @param details.edgeId - Edge ID related to error
136
138
  * @param details.canContinue - Whether loading can continue after this error
139
+ * @param details.loadId - Which load this is, when it is one
137
140
  */
138
141
  emitDataLoadingError(error: Error, context: DataLoadingErrorEvent["context"], format: string | undefined, details: {
139
142
  line?: number;
140
143
  nodeId?: unknown;
141
144
  edgeId?: string;
142
145
  canContinue: boolean;
146
+ loadId?: number;
143
147
  }): void;
144
148
  /**
145
149
  * Emits a summary of all data loading errors after import completes
@@ -149,8 +153,9 @@ export declare class EventManager implements Manager {
149
153
  * @param detailedReport - Detailed error report
150
154
  * @param primaryCategory - Primary error category
151
155
  * @param suggestion - Suggested fix for the errors
156
+ * @param loadId - Which load this is, when it is one
152
157
  */
153
- emitDataLoadingErrorSummary(format: string, totalErrors: number, message: string, detailedReport: string, primaryCategory?: string, suggestion?: string): void;
158
+ emitDataLoadingErrorSummary(format: string, totalErrors: number, message: string, detailedReport: string, primaryCategory?: string, suggestion?: string, loadId?: number): void;
154
159
  /**
155
160
  * Emits a data loading complete event when import finishes
156
161
  * @param format - Data format that was loaded
@@ -161,8 +166,9 @@ export declare class EventManager implements Manager {
161
166
  * @param warnings - Number of warnings encountered
162
167
  * @param success - Whether loading was successful
163
168
  * @param report - What the load did, including which endpoint spelling resolved
169
+ * @param loadId - Which load this is, when it is one
164
170
  */
165
- emitDataLoadingComplete(format: string, nodesLoaded: number, edgesLoaded: number, duration: number, errors: number, warnings: number, success: boolean, report: ImportReport): void;
171
+ emitDataLoadingComplete(format: string, nodesLoaded: number, edgesLoaded: number, duration: number, errors: number, warnings: number, success: boolean, report: ImportReport, loadId?: number): void;
166
172
  /**
167
173
  * Emits a selection changed event when node selection changes
168
174
  * @param previousNode - Previously selected node (or null)