@graphty/graphty-element 2.6.2 → 3.0.0

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 (163) hide show
  1. package/dist/ai.js +3 -3
  2. package/dist/catalog.js +53 -54
  3. package/dist/chunks/{AiManager-4iQpsJW1.js → AiManager-Bhh0rR_p.js} +706 -655
  4. package/dist/chunks/GraphSession-DPoTaT3b.js +21175 -0
  5. package/dist/chunks/{GraphtyLogger-B_O67a6c.js → GraphtyLogger-BtcBJQPL.js} +1 -1
  6. package/dist/chunks/{VoiceInputAdapter-Cc6mHXTI.js → VoiceInputAdapter-CdLsJ_nG.js} +1 -1
  7. package/dist/chunks/{XRPivotCameraController-BLa89LXn.js → XRPivotCameraController-CiLJ9Gz6.js} +2 -2
  8. package/dist/chunks/algorithms-qij74zEN.js +6811 -0
  9. package/dist/chunks/{capability-check-Am2zliFj.js → capability-check-BbgTejS3.js} +1 -1
  10. package/dist/chunks/definePalette-BYt2Llxs.js +1333 -0
  11. package/dist/chunks/fields-5uVC1Pll.js +4999 -0
  12. package/dist/chunks/{format-detection-BHwrAVzW.js → format-detection-FKaDMshR.js} +1 -1
  13. package/dist/chunks/{index-BkBLbvui.js → index-Cc_6D9hV.js} +6034 -7127
  14. package/dist/chunks/interpolation-Dk206AhZ.js +105 -0
  15. package/dist/chunks/paletteRegistry-De3CGdst.js +357 -0
  16. package/dist/chunks/parse-SVp77JbE.js +669 -0
  17. package/dist/chunks/{pluginRegistry-Bs8bEkz9.js → pluginRegistry-Ddfl6Mv2.js} +27 -24
  18. package/dist/chunks/{registry-BdGvyZou.js → registry-CgMqldp4.js} +1 -1
  19. package/dist/chunks/{DataSource-BL2UzPff.js → sources-BbAJCDIH.js} +279 -108
  20. package/dist/commands.d.ts +128 -19
  21. package/dist/commands.js +49 -1
  22. package/dist/custom-elements.json +1 -1
  23. package/dist/extend.d.ts +10 -2
  24. package/dist/extend.js +64 -57
  25. package/dist/graphty-catalog.json +6 -3
  26. package/dist/graphty.bundle.js +267177 -240648
  27. package/dist/graphty.js +84 -78
  28. package/dist/index.d.ts +4 -0
  29. package/dist/logging.js +2 -2
  30. package/dist/schema.js +70 -71
  31. package/dist/session.d.ts +5 -6
  32. package/dist/session.js +40 -86
  33. package/dist/src/Edge.d.ts +31 -67
  34. package/dist/src/Graph.d.ts +335 -77
  35. package/dist/src/Node.d.ts +36 -3
  36. package/dist/src/NodeBehavior.d.ts +28 -0
  37. package/dist/src/Styles.d.ts +15 -4
  38. package/dist/src/acceleration/AccelerationController.d.ts +8 -0
  39. package/dist/src/acceleration/narrow.d.ts +9 -1
  40. package/dist/src/acceleration/types.d.ts +10 -0
  41. package/dist/src/ai/AiController.d.ts +12 -0
  42. package/dist/src/ai/AiManager.d.ts +7 -0
  43. package/dist/src/ai/commands/AlgorithmCommands.d.ts +1 -1
  44. package/dist/src/ai/commands/LayoutCommands.d.ts +1 -1
  45. package/dist/src/ai/commands/StyleCommands.d.ts +1 -1
  46. package/dist/src/ai/commands/types.d.ts +20 -1
  47. package/dist/src/algorithms/Algorithm.d.ts +21 -4
  48. package/dist/src/algorithms/BFSAlgorithm.d.ts +0 -9
  49. package/dist/src/algorithms/BellmanFordAlgorithm.d.ts +0 -14
  50. package/dist/src/algorithms/DFSAlgorithm.d.ts +1 -1
  51. package/dist/src/algorithms/FloydWarshallAlgorithm.d.ts +5 -0
  52. package/dist/src/algorithms/GirvanNewmanAlgorithm.d.ts +5 -0
  53. package/dist/src/algorithms/LeidenAlgorithm.d.ts +5 -0
  54. package/dist/src/algorithms/PageRankAlgorithm.d.ts +1 -1
  55. package/dist/src/algorithms/StronglyConnectedComponentsAlgorithm.d.ts +1 -1
  56. package/dist/src/algorithms/metrics/fields.d.ts +23 -1
  57. package/dist/src/algorithms/utils/graphUtils.d.ts +13 -1
  58. package/dist/src/catalog/paletteRegistry.d.ts +4 -4
  59. package/dist/src/catalog/registry.d.ts +3 -2
  60. package/dist/src/catalog/types.d.ts +18 -1
  61. package/dist/src/config/GraphStyle.d.ts +1 -1
  62. package/dist/src/config/StyleTemplate.d.ts +2 -2
  63. package/dist/src/config/xr-config-schema.d.ts +4 -4
  64. package/dist/src/data/CSVDataSource.d.ts +77 -22
  65. package/dist/src/data/ErrorAggregator.d.ts +5 -0
  66. package/dist/src/data/GEXFDataSource.d.ts +12 -61
  67. package/dist/src/data/GraphMLDataSource.d.ts +3 -44
  68. package/dist/src/data/GraphStore.d.ts +322 -15
  69. package/dist/src/data/JsonDataSource.d.ts +43 -1
  70. package/dist/src/data/graph-io-import.d.ts +89 -0
  71. package/dist/src/data/graph-io-records.d.ts +64 -0
  72. package/dist/src/data/lane.d.ts +23 -0
  73. package/dist/src/data/positions.d.ts +13 -0
  74. package/dist/src/data/seedPosition.d.ts +16 -0
  75. package/dist/src/errors/GraphtyError.d.ts +3 -1
  76. package/dist/src/errors/codes.d.ts +23 -0
  77. package/dist/src/events.d.ts +12 -0
  78. package/dist/src/graphty-element.d.ts +149 -54
  79. package/dist/src/input/types.d.ts +2 -0
  80. package/dist/src/layout/D3GraphLayoutEngine.d.ts +17 -3
  81. package/dist/src/layout/FixedLayoutEngine.d.ts +20 -4
  82. package/dist/src/layout/KamadaKawaiLayoutEngine.d.ts +6 -0
  83. package/dist/src/layout/LayoutEngine.d.ts +214 -116
  84. package/dist/src/layout/NGraphLayoutEngine.d.ts +10 -3
  85. package/dist/src/layout/SimulationLayoutEngine.d.ts +8 -3
  86. package/dist/src/managers/AlgorithmManager.d.ts +24 -5
  87. package/dist/src/managers/DataManager.d.ts +258 -181
  88. package/dist/src/managers/EventManager.d.ts +5 -2
  89. package/dist/src/managers/GraphContext.d.ts +7 -0
  90. package/dist/src/managers/InputManager.d.ts +11 -0
  91. package/dist/src/managers/LayoutManager.d.ts +129 -50
  92. package/dist/src/managers/RenderManager.d.ts +14 -1
  93. package/dist/src/managers/UpdateManager.d.ts +20 -0
  94. package/dist/src/screenshot/ScreenshotCapture.d.ts +1 -1
  95. package/dist/src/session/GraphSession.d.ts +83 -6
  96. package/dist/src/session/commands/algo.d.ts +169 -0
  97. package/dist/src/session/commands/config.d.ts +45 -0
  98. package/dist/src/session/commands/data.d.ts +178 -0
  99. package/dist/src/session/commands/doors.d.ts +93 -0
  100. package/dist/src/session/commands/index.d.ts +20 -0
  101. package/dist/src/session/commands/layout.d.ts +104 -0
  102. package/dist/src/session/commands/positions.d.ts +30 -0
  103. package/dist/src/session/commands/sets.d.ts +113 -0
  104. package/dist/src/session/commands/style.d.ts +92 -0
  105. package/dist/src/session/commands/view.d.ts +57 -0
  106. package/dist/src/session/commands/visibility.d.ts +41 -0
  107. package/dist/src/session/data.d.ts +131 -4
  108. package/dist/src/session/index.d.ts +1 -1
  109. package/dist/src/session/planning.d.ts +25 -8
  110. package/dist/src/session/project/Dispatcher.d.ts +905 -0
  111. package/dist/src/session/project/History.d.ts +382 -0
  112. package/dist/src/session/project/arrangement.d.ts +247 -0
  113. package/dist/src/session/project/derive.d.ts +132 -0
  114. package/dist/src/session/project/digest.d.ts +33 -0
  115. package/dist/src/session/project/draft.d.ts +194 -0
  116. package/dist/src/session/project/graphOps.d.ts +304 -0
  117. package/dist/src/session/project/ingest.d.ts +364 -0
  118. package/dist/src/session/project/state.d.ts +145 -0
  119. package/dist/src/session/project/strict.d.ts +68 -0
  120. package/dist/src/session/results/RunResult.d.ts +48 -0
  121. package/dist/src/session/results/statistics.d.ts +20 -0
  122. package/dist/src/session/runs/Run.d.ts +80 -4
  123. package/dist/src/session/runs/RunsApi.d.ts +23 -6
  124. package/dist/src/session/runs/types.d.ts +25 -6
  125. package/dist/src/session/scope/ElementMask.d.ts +14 -0
  126. package/dist/src/session/scope/ScopeApi.d.ts +3 -22
  127. package/dist/src/session/scope/spaces.d.ts +29 -0
  128. package/dist/src/session/sealed.d.ts +22 -0
  129. package/dist/src/session/selection/SelectionApi.d.ts +14 -4
  130. package/dist/src/session/sets/SetsApi.d.ts +13 -5
  131. package/dist/src/session/sets/store.d.ts +54 -53
  132. package/dist/src/session/sets/types.d.ts +5 -2
  133. package/dist/src/session/styles/Layer.d.ts +5 -0
  134. package/dist/src/session/styles/StylesApi.d.ts +68 -17
  135. package/dist/src/session/styles/autoApply.d.ts +64 -53
  136. package/dist/src/session/styles/index.d.ts +3 -3
  137. package/dist/src/session/styles/predicate.d.ts +7 -0
  138. package/dist/src/session/styles/repaint.d.ts +16 -1
  139. package/dist/src/session/styles/sources.d.ts +1 -1
  140. package/dist/src/session/types.d.ts +625 -54
  141. package/dist/src/session/visibility/VisibilityApi.d.ts +38 -18
  142. package/dist/src/session/visibility/filter.d.ts +10 -0
  143. package/dist/src/simple/defineAlgorithm.d.ts +28 -0
  144. package/dist/src/simple/defineLayout.d.ts +35 -0
  145. package/dist/src/simple/defineLogDestination.d.ts +31 -0
  146. package/dist/src/simple/definePalette.d.ts +26 -0
  147. package/dist/src/simple/definition.d.ts +106 -0
  148. package/dist/src/simple/options.d.ts +33 -0
  149. package/dist/src/simple/source.d.ts +49 -0
  150. package/dist/src/simple/types.d.ts +366 -0
  151. package/dist/src/simple/view.d.ts +107 -0
  152. package/dist/webgpu.js +2 -2
  153. package/package.json +10 -12
  154. package/dist/chunks/GraphSession-BhuHSXIo.js +0 -12819
  155. package/dist/chunks/GraphStyle-Cwr55SAE.js +0 -65
  156. package/dist/chunks/algorithms-BJ6DQMOe.js +0 -3777
  157. package/dist/chunks/detect-fyuVnlCT.js +0 -88
  158. package/dist/chunks/interpolation-DY-PNpqX.js +0 -43
  159. package/dist/chunks/optionsFromZod-CKMYSwTz.js +0 -3636
  160. package/dist/chunks/paletteRegistry-BCFSwJGK.js +0 -1196
  161. package/dist/chunks/parse-BMTqt4SS.js +0 -3658
  162. package/dist/src/data/csv-variant-detection.d.ts +0 -29
  163. package/dist/src/data/ingest.d.ts +0 -104
@@ -21,16 +21,49 @@ import { type GraphSession } from "./session";
21
21
  import type { Run, StartOptions } from "./session/runs";
22
22
  import type { SelectionDelta, SelectionOp, SelectionTarget } from "./session/selection";
23
23
  import type { StyleSuggestion } from "./session/styles";
24
+ import type { TransactionScope } from "./session/types";
24
25
  import { Styles } from "./Styles";
25
26
  import type { QueueableOptions, RunAlgorithmOptions, SetLayoutOptions } from "./utils/queue-migration";
26
27
  import { XRSessionManager } from "./xr/XRSessionManager";
28
+ /**
29
+ * Load the element's data-source pair through `addDataFromSource`, as every load goes, with what
30
+ * only the pair has: a coalesce key, so the two halves assigned in one tick are one load, and
31
+ * whether the page declared it at construction, which makes it the baseline. No entry point
32
+ * exports it.
33
+ * @param graph - The graph.
34
+ * @param type - The data source type.
35
+ * @param config - Its configuration.
36
+ * @param how - The coalesce key, and whether it is setup.
37
+ * @param how.coalesce - The key two pair loads coalesce under while the first waits.
38
+ * @param how.setup - Declared at construction.
39
+ * @returns The load, as `addDataFromSource` returns it.
40
+ */
41
+ export declare function loadSourcePair(graph: Graph, type: string, config: object, how: {
42
+ readonly coalesce: string;
43
+ readonly setup: boolean;
44
+ }): Promise<{
45
+ loadId: number;
46
+ }>;
47
+ /**
48
+ * A graph's operation queue: what the element's own parts (the element's data doors, the
49
+ * screenshot capture) and its tests queue work on and wait for. Not published: code queued there
50
+ * could run between the steps of a command, so a consumer waits with `graph.waitForSettled()`.
51
+ * @param graph - The graph.
52
+ * @returns Its queue.
53
+ */
54
+ export declare function operationQueueOf(graph: Graph): OperationQueueManager;
27
55
  /**
28
56
  * Main orchestrator class for graph visualization and interaction.
29
57
  * Integrates Babylon.js scene management, coordinates nodes, edges, layouts, and styling.
30
58
  */
31
59
  export declare class Graph implements GraphContext {
32
60
  #private;
33
- styles: Styles;
61
+ /**
62
+ * The element's configuration document, read-only: its `config` is the frozen merged view.
63
+ * Change a setting through `getSession().config.set`, which is an undoable step.
64
+ * @returns The configuration document.
65
+ */
66
+ get styles(): Styles;
34
67
  element: Element;
35
68
  canvas: HTMLCanvasElement;
36
69
  engine: WebGPUEngine | Engine;
@@ -38,7 +71,6 @@ export declare class Graph implements GraphContext {
38
71
  camera: CameraManager;
39
72
  private initialCameraState?;
40
73
  private initialCameraStateCaptured;
41
- private userCameraPresets;
42
74
  skybox?: string;
43
75
  xrHelper: WebXRDefaultExperience | null;
44
76
  needRays: boolean;
@@ -46,8 +78,13 @@ export declare class Graph implements GraphContext {
46
78
  fetchNodes?: FetchNodesFn;
47
79
  fetchEdges?: FetchEdgesFn;
48
80
  initialized: boolean;
49
- runAlgorithmsOnLoad: boolean;
50
81
  enableDetailedProfiling?: boolean;
82
+ /** The view settings, as set; see {@link ViewSettings}. Written only through `writeViewSettings`. */
83
+ private readonly viewSettings;
84
+ /** Moves on every write of the view settings, so the frozen configuration knows to rebuild. */
85
+ private viewVersion;
86
+ /** The frozen configuration, and the three write counts it was built at. */
87
+ private configCache;
51
88
  private wasSettled;
52
89
  /** How many loads `addDataFromSource` has started; the last one's id. */
53
90
  private loadCount;
@@ -72,6 +109,10 @@ export declare class Graph implements GraphContext {
72
109
  private updateManager;
73
110
  private algorithmManager;
74
111
  private inputManager;
112
+ /** While an immersive session is active: its mode and when it started, stamped on steps. */
113
+ private immersiveSince;
114
+ /** How many `batchOperations` callbacks are open. */
115
+ private openBatches;
75
116
  private selectionManager;
76
117
  /**
77
118
  * What the session's style stack resolved for each element, and which stack owns the paint.
@@ -90,18 +131,24 @@ export declare class Graph implements GraphContext {
90
131
  * it is why every data question this class answers is forwarded rather than computed.
91
132
  */
92
133
  private readonly session;
93
- operationQueue: OperationQueueManager;
134
+ /** The queue loads, layouts, runs and style passes take their turn in; see {@link operationQueueOf}. */
135
+ private readonly operationQueue;
94
136
  private xrSessionManager;
95
137
  private xrUIManager;
96
138
  private graphContext;
97
139
  private activeCapture;
98
- private savedZPositions;
99
140
  /**
100
141
  * Creates a new Graph instance and initializes the rendering engine and managers.
101
142
  * @param element - DOM element or element ID to attach the graph canvas to
102
143
  * @param useMockInput - Whether to use mock input for testing (defaults to false)
103
144
  */
104
145
  constructor(element: Element | string, useMockInput?: boolean);
146
+ /**
147
+ * Build the engine for the `layout` slice when nothing has yet: the default layout, until one
148
+ * is chosen, in the dimension the slice holds.
149
+ * @param signal - Fires when a layout the consumer asked for replaces this one first.
150
+ */
151
+ private buildOpeningLayout;
105
152
  private cleanup;
106
153
  /**
107
154
  * Shuts down the graph, stopping animations and disposing all resources.
@@ -133,6 +180,17 @@ export declare class Graph implements GraphContext {
133
180
  * The entry's run options ride along either way, with no per-algorithm branch.
134
181
  * @param entry - An algorithm, or an algorithm with its run options.
135
182
  */
183
+ /**
184
+ * Run the on-load algorithms, when `runAlgorithmsOnLoad` is set. Each is queued, not awaited.
185
+ * @param dispatch - Where their commands go: the deferred members of the command that added
186
+ * the rows, so they merge into its step.
187
+ */
188
+ private startOnLoadRuns;
189
+ /**
190
+ * Run one entry of the load-time algorithm list.
191
+ * @param entry - An algorithm, or an algorithm with its run options.
192
+ * @param dispatch - Where a catalogue run's command goes.
193
+ */
136
194
  private runOnLoad;
137
195
  /**
138
196
  * Initializes the graph instance, setting up managers, styles, and rendering pipeline.
@@ -143,15 +201,27 @@ export declare class Graph implements GraphContext {
143
201
  * All update logic is now handled by UpdateManager
144
202
  */
145
203
  update(): void;
204
+ /**
205
+ * Whether the algorithms in the configuration's `data.algorithms` run once data has loaded.
206
+ * A project setting: setting it is one step, which undo takes back.
207
+ * @returns The setting.
208
+ */
209
+ get runAlgorithmsOnLoad(): boolean;
210
+ /**
211
+ * Set whether the on-load algorithms run.
212
+ * @param value - The setting.
213
+ */
214
+ set runAlgorithmsOnLoad(value: boolean);
146
215
  /**
147
216
  * Set what the graph is drawn against: a flat colour, or a photo-dome skybox.
148
217
  *
149
- * The colour reaches the scene's clear colour and a skybox builds a `PhotoDome` around the
150
- * graph, announcing `skybox-loaded` once its texture has arrived. The value is also written
151
- * into the configuration document, so a later read of `styles.config.graph.background` and a
152
- * rebuild of the scene both see what was asked for.
218
+ * A project setting: one step, which undo takes back. The colour reaches the scene's clear
219
+ * colour and a skybox builds a `PhotoDome` around the graph, announcing `skybox-loaded` once
220
+ * its texture has arrived; the scene never holds more than one dome. A later read of
221
+ * `styles.config.graph.background` sees the value, parsed.
153
222
  * @param background - A colour (`{backgroundType: "color", color}`) or a skybox
154
223
  * (`{backgroundType: "skybox", data}`), where `data` is an image URL or a base64 PNG.
224
+ * @throws A Zod error when the value is not a background; nothing is changed then.
155
225
  */
156
226
  setBackground(background: GraphBackgroundConfig): void;
157
227
  /**
@@ -159,8 +229,8 @@ export declare class Graph implements GraphContext {
159
229
  * node, and how solid it is.
160
230
  *
161
231
  * MERGED, NOT REPLACED: naming the colour leaves the scale and the opacity where they were.
162
- * It takes effect immediately, on a selection that is already on screen as well as on the
163
- * next one.
232
+ * A project setting: one step, which undo takes back. It takes effect on a selection that is
233
+ * already on screen as well as on the next one.
164
234
  *
165
235
  * THE HALO IS NOT A STYLE LAYER, deliberately. A selection is what a person is pointing at
166
236
  * rather than a property of the data, so it is drawn by the renderer from the selection mask
@@ -178,32 +248,62 @@ export declare class Graph implements GraphContext {
178
248
  * means that field and not "reset every other pacing setting to its default", which is what
179
249
  * parsing a partial document against a schema of defaults would do.
180
250
  *
251
+ * `layout.preSteps`, `layout.stepMultiplier` and `layout.minDelta` are project settings:
252
+ * setting any of them is one step, which undo takes back. The rest -- label declutter, pin on
253
+ * drag, the throughput settings, the fetchers -- are preferences of this view, and undo does
254
+ * not touch them.
255
+ *
181
256
  * The settings take effect on the next layout the element runs. `preSteps` is read when a
182
257
  * layout starts, so setting it after a graph has already settled changes nothing that is
183
258
  * already on screen. `labels.declutter` is the exception: it takes effect on the next frame.
184
259
  * @param behavior - The fields to change. Anything omitted keeps its current value.
260
+ * @throws A Zod error when a value is outside what the schema allows; nothing is changed then.
185
261
  */
186
262
  setLayoutBehavior(behavior: GraphBehaviorConfig): void;
187
263
  /**
188
- * Adds graph data from a registered data source.
189
- *
190
- * PAINTS WHAT IT LOADED, and that is not incidental. Data reaches the element two ways and a
191
- * consumer chooses between them by which method they call: records handed in through
192
- * `addNodes`/`setEdges`, which are queued operations, or a file, string or URL read by a data
193
- * source, which is this method and which deliberately bypasses the queue (`DataManager`
194
- * streams chunks straight into the store so a large file does not queue an operation per
195
- * chunk). The element's whole-graph repaint hangs off the QUEUED path, so a graph
196
- * loaded this way was never painted from the style stack at all: every node and edge kept the
197
- * bootstrap appearance `DataManager` gives it at construction, `styleOf` answered `{}`, and
198
- * `styles.explain(...)` truthfully reported that no layer -- not even the element's own
199
- * defaults -- had painted anything. The picture happened to resemble the default layer's
200
- * colour, so it read as success until a story asked for something else.
201
- *
202
- * The repaint is here, once per load, rather than on the `data-added` event, which fires per
203
- * chunk and per kind and would put a whole-graph pass behind each one.
264
+ * The layout behaviour: the view preferences somebody set on this graph, and the pacing
265
+ * settings saved with the project (`preSteps`, `stepMultiplier`, `minDelta`) as they are in
266
+ * effect. Those three always read their value, so assigning one its default reads back even
267
+ * though it records no step.
268
+ * @returns The behaviour settings.
269
+ */
270
+ getLayoutBehavior(): GraphBehaviorConfig | undefined;
271
+ /**
272
+ * Change project settings as one step, reporting a refusal rather than leaving it unhandled:
273
+ * the doors that call this hand their caller no promise.
274
+ * @param values - The settings.
275
+ */
276
+ private setProjectConfig;
277
+ /**
278
+ * Write the view settings, so the frozen configuration is rebuilt on its next read.
279
+ * @param write - Changes the settings.
280
+ */
281
+ private writeViewSettings;
282
+ /**
283
+ * The configuration document `styles.config` reads: frozen, merged from the project settings
284
+ * and the view settings, and rebuilt only when one of them has changed since the last read,
285
+ * so two reads with no change between them return the same object.
286
+ * @returns The document.
287
+ */
288
+ private configDocument;
289
+ /**
290
+ * Merge project settings, the layout and the view settings into one frozen configuration
291
+ * document. `graph.viewMode` and the deprecated `graph.twoD` are computed from the layout's
292
+ * dimension, and from the immersive session the view is in; they are stored nowhere.
293
+ * @param project - The project settings.
294
+ * @param layout - The `layout` slice.
295
+ * @returns The document.
296
+ */
297
+ private mergeConfig;
298
+ /**
299
+ * Adds graph data from a registered data source, as one undoable step.
204
300
  *
205
- * A load that fails part-way still paints: the rows that did arrive are in the store and on
206
- * screen, so leaving them unpainted would be the same defect with a smaller blast radius.
301
+ * The load takes its turn on the operation queue behind the loads and layouts asked for
302
+ * before it, and is added to what the graph holds unless it replaces it. It paints what it
303
+ * loaded before the promise settles: the pass that follows its last chunk repaints the graph
304
+ * from the style stack, so a graph loaded this way is painted exactly as one built from
305
+ * records is. A load that fails part way records nothing and takes back the rows that did
306
+ * arrive, so a replacing load that fails leaves the graph it would have replaced.
207
307
  *
208
308
  * EVERY LOAD HAS AN ID. The promise resolves to it, and every event about this load --
209
309
  * `data-loading-progress`, `data-loading-complete`, `data-loading-error`, `data-loaded` and
@@ -231,7 +331,7 @@ export declare class Graph implements GraphContext {
231
331
  */
232
332
  private reserveLoad;
233
333
  /**
234
- * Run a load whose place `reserveLoad` already took, then repaint what it loaded.
334
+ * Run a load whose place `reserveLoad` already took.
235
335
  * @param type - Type/name of the registered data source
236
336
  * @param opts - Options to pass to the data source
237
337
  * @param load - The reservation
@@ -403,7 +503,7 @@ export declare class Graph implements GraphContext {
403
503
  */
404
504
  setEdges(edges: Record<string | number, unknown>[], options?: AddEdgesOptions & QueueableOptions): Promise<void>;
405
505
  /**
406
- * Replace every node in the graph with a new set.
506
+ * Replace every node in the graph with a new set, as one undoable step.
407
507
  *
408
508
  * What the `node-data` property does, and the node half of {@link setEdges}. A node whose id is
409
509
  * not in the new set is removed the way {@link removeNodes} removes one, so the edges attached
@@ -479,6 +579,13 @@ export declare class Graph implements GraphContext {
479
579
  * @since 2.5.0
480
580
  */
481
581
  setLayoutScope(scope: ScopeInput | undefined): Promise<void>;
582
+ /**
583
+ * A layout scope as the `layout` slice keeps it.
584
+ * @param scope - The scope as given.
585
+ * @returns Its canonical form; `"graph"` for the whole graph.
586
+ * @throws A `GraphtyError` with `E_BAD_COMMAND` when it is not a scope.
587
+ */
588
+ private canonicalLayoutScope;
482
589
  /**
483
590
  * Run a graph algorithm, addressed the 1.10 way.
484
591
  * @remarks
@@ -538,6 +645,7 @@ export declare class Graph implements GraphContext {
538
645
  * @param options - Algorithm options and queue settings.
539
646
  * @param start - Run options for a catalogue run, such as `style`; a plugin without a
540
647
  * descriptor has no run to give them to.
648
+ * @param dispatch - Where a catalogue run's command goes; the session's own by default.
541
649
  */
542
650
  private runLegacyAddress;
543
651
  /**
@@ -575,8 +683,10 @@ export declare class Graph implements GraphContext {
575
683
  * @param mapping - The catalogue key to start, and the parameters it needs.
576
684
  * @param namespace - The 1.10 namespace, for the error event and the suggested styles.
577
685
  * @param type - The 1.10 type, for the same two.
578
- * @param options - What the caller passed.
686
+ * @param options - What the caller passed. `applySuggestedStyles` is carried out in the run's
687
+ * own step, so one undo takes the run and those layers away together.
579
688
  * @param start - Run options to start it with, such as `style`.
689
+ * @param dispatch - Where the run's command goes; the session's own by default.
580
690
  */
581
691
  private runLegacyAsRun;
582
692
  /**
@@ -622,7 +732,8 @@ export declare class Graph implements GraphContext {
622
732
  */
623
733
  getSuggestedStyles(algorithmKey: string): readonly StyleSuggestion[];
624
734
  /**
625
- * Remove nodes from the graph by their IDs, and with them every edge attached to one.
735
+ * Remove nodes from the graph by their IDs, and with them every edge attached to one, as one
736
+ * undoable step. Undo puts them back at the rows they held.
626
737
  *
627
738
  * One `elements-removed` event is emitted per call, naming the nodes and every edge
628
739
  * that went with them. A removal used to be silent, so a consumer watching the element saw its
@@ -630,24 +741,58 @@ export declare class Graph implements GraphContext {
630
741
  * which is why the notification lands with the cascade rather than after it.
631
742
  * @param nodeIds - Array of node IDs to remove
632
743
  * @param options - Queue options for operation ordering
744
+ * @returns Settles once the change is drawn
633
745
  */
634
746
  removeNodes(nodeIds: (string | number)[], options?: QueueableOptions): Promise<void>;
635
747
  /**
636
- * Write each update into its node's attributes through the one attribute writer, so the
637
- * revision of every field written moves. `id` is the address, not an attribute, and is not
638
- * written.
639
- * @param updates - the updates, each naming its node by `id`
748
+ * Remove edges from the graph by their ids, as one undoable step. Undo puts them back at the
749
+ * rows they held, with their weights and ids.
750
+ * @param edgeIds - The element-assigned edge ids
751
+ * @param options - Queue options for operation ordering
752
+ * @returns Settles once the change is drawn
640
753
  */
641
- private writeNodeUpdates;
754
+ removeEdges(edgeIds: string[], options?: QueueableOptions): Promise<void>;
642
755
  /**
643
- * Update node data for existing nodes in the graph.
756
+ * Update node data for existing nodes in the graph, as one undoable step.
644
757
  * @param updates - Array of update objects containing node ID and properties to update
645
758
  * @param options - Queue options for operation ordering
759
+ * @returns Settles once the change is drawn
646
760
  */
647
761
  updateNodes(updates: {
648
762
  id: string | number;
649
763
  [key: string]: unknown;
650
764
  }[], options?: QueueableOptions): Promise<void>;
765
+ /**
766
+ * Update edge data for existing edges in the graph, as one undoable step. Keys not named are
767
+ * kept; an id the graph does not hold is skipped.
768
+ * @param updates - The edge id and the new values of each edge
769
+ * @param options - Queue options for operation ordering
770
+ * @returns Settles once the change is drawn
771
+ */
772
+ updateEdges(updates: {
773
+ id: string;
774
+ [key: string]: unknown;
775
+ }[], options?: QueueableOptions): Promise<void>;
776
+ /**
777
+ * Tell the selection about a removal before it is written, whichever door dispatched it.
778
+ *
779
+ * THE SELECTION IS TOLD FIRST, and that ordering is the whole of it. The session's masks are
780
+ * keyed by dense index; an id is resolved to an index through the current snapshot. Once the
781
+ * builder has tombstoned these rows, the next freeze compacts and every surviving edge slides
782
+ * down -- so a mask still holding the dead indices would silently be holding the SURVIVORS
783
+ * instead, and a removal would leave two edges the reader never selected highlighted on screen.
784
+ * @param nodeIds - The nodes removed, whose incident edges go with them.
785
+ * @param edgeIds - The edges removed.
786
+ */
787
+ private selectRemoval;
788
+ /**
789
+ * Dispatch one `data.apply`, or a batch of them. It takes its turn on the operation queue,
790
+ * which keeps an add ordered against the loads and layouts queued before it, or starts at once
791
+ * with `skipQueue`.
792
+ * @param mutation - The mutation, or the batch.
793
+ * @param options - Queue options.
794
+ */
795
+ private applyData;
651
796
  /**
652
797
  * Activate the camera that belongs to the current view mode: `"2d"` in 2D, `"orbit"` in 3D.
653
798
  *
@@ -669,11 +814,31 @@ export declare class Graph implements GraphContext {
669
814
  */
670
815
  setRenderSettings(_settings: Record<string, unknown>, options?: QueueableOptions): Promise<void>;
671
816
  /**
672
- * Execute multiple operations as a batch
673
- * Operations will be queued and executed in dependency order
674
- * @param fn - Function containing operations to batch
817
+ * Make several changes one undoable step.
818
+ *
819
+ * A transaction of this graph's session: what `fn` does through `tx` -- `tx.data.addNodes`,
820
+ * `tx.layout.set`, `tx.run`, `tx.styles.add` -- is recorded as one step once `fn` settles, and
821
+ * a throw rolls all of it back. A call on this graph itself while `fn` runs is a step of its
822
+ * own, and logs a warning naming the `tx` verb to use instead.
823
+ * @param fn - The changes, made through `tx`.
824
+ * @param label - The step's label.
825
+ * @returns Once the step is recorded and drawn.
826
+ * @since 3.0.0
827
+ * @example
828
+ * ```typescript
829
+ * await graph.batchOperations(async (tx) => {
830
+ * await tx.data.addNodes([{ id: "a" }, { id: "b" }]);
831
+ * await tx.data.addEdges([{ src: "a", dst: "b" }]);
832
+ * await tx.layout.set("circular");
833
+ * });
834
+ * ```
835
+ */
836
+ batchOperations(fn: (tx: TransactionScope) => Promise<void> | void, label?: string): Promise<void>;
837
+ /**
838
+ * While a batch is open, make each of this graph's doors warn that it is a step of its own,
839
+ * naming the `tx` verb that would join the batch.
675
840
  */
676
- batchOperations(fn: () => Promise<void> | void): Promise<void>;
841
+ private warnOutsideBatch;
677
842
  /**
678
843
  * The headless model behind this renderer: the graph data, the coordinates, the statistics,
679
844
  * the catalogue, the configuration and what this machine can do.
@@ -739,7 +904,8 @@ export declare class Graph implements GraphContext {
739
904
  */
740
905
  removeListener(id: symbol): boolean;
741
906
  /**
742
- * Remove every node and edge, leaving the graph empty and ready for the next dataset.
907
+ * Remove every node and edge, leaving the graph empty and ready for the next dataset, as one
908
+ * undoable step.
743
909
  *
744
910
  * The verb the data guide has always taught -- as `graph.clear()`, which has never existed.
745
911
  * `<graphty-element>` has had `clearData()` throughout; a consumer holding a `Graph` had to
@@ -814,6 +980,12 @@ export declare class Graph implements GraphContext {
814
980
  * or the pass was stopped.
815
981
  */
816
982
  private repaintFromSession;
983
+ /**
984
+ * Strict state: the drawn maps are keyed exactly like the `graph` slice, and the layout engine
985
+ * holds each drawn edge once, where it can place it.
986
+ * @param slice - The `graph` slice the pass derived.
987
+ */
988
+ private checkDrawn;
817
989
  /**
818
990
  * Get the DataManager instance.
819
991
  * @returns The DataManager instance
@@ -979,14 +1151,13 @@ export declare class Graph implements GraphContext {
979
1151
  *
980
1152
  * WHY THE ELEMENT NEEDED THIS AT ALL. `setupCameras` ends with an unconditional
981
1153
  * `activateCamera("orbit")` and RenderManager is handed no configuration, so a freshly built
982
- * scene was always perspective 3D no matter what `config.graph.viewMode` said. The only route
983
- * to the orthographic camera was `_setViewModeInternal`, which is a TRANSITION: it clears the
984
- * mesh cache, rebuilds every node and edge, saves and restores Z, and reframes the camera. A
985
- * graph whose opening state is 2D has nothing to transition from -- there are no meshes yet
986
- * and no Z to save -- and a consumer who wrote `<graphty-element view-mode="2d">` or set
987
- * `config.graph.viewMode` on a bare `Graph` got a graph that reported "2d" from every property
988
- * while drawing through a perspective camera, spreading the layout through three dimensions
989
- * and building every edge as a 3D tube.
1154
+ * scene was always perspective 3D no matter what the `layout` slice's dimension said. The
1155
+ * other route to the orthographic camera is the `layout` hook, which is a TRANSITION: it
1156
+ * clears the mesh cache, rebuilds every node and edge, and reframes the camera. A graph whose
1157
+ * opening state is 2D has nothing to transition from -- there are no meshes yet -- and a
1158
+ * consumer who wrote `<graphty-element view-mode="2d">` got a graph that reported "2d" from
1159
+ * every property while drawing through a perspective camera, spreading the layout through
1160
+ * three dimensions and building every edge as a 3D tube.
990
1161
  *
991
1162
  * WHY HERE. This runs immediately before `markCategoryCompleted("style-init")`, and the
992
1163
  * position is load-bearing: `data-add` depends on `style-init`, so no node or edge mesh can be
@@ -1000,11 +1171,27 @@ export declare class Graph implements GraphContext {
1000
1171
  *
1001
1172
  * AR AND VR OPEN AS 3D, deliberately. Entering an immersive session is `requestSession`,
1002
1173
  * which browsers only grant inside a user gesture, so it cannot happen during init; the
1003
- * XR session manager is merely constructed later in `init()`. An opening `viewMode` of "ar"
1004
- * or "vr" therefore gets the perspective camera and is recorded in the scene metadata, and
1005
- * the session begins when a consumer calls `setViewMode` from a click.
1174
+ * XR session manager is merely constructed later in `init()`, and the session begins when a
1175
+ * consumer calls `setViewMode` from a click.
1006
1176
  */
1007
1177
  private applyOpeningViewMode;
1178
+ /**
1179
+ * The dimension the `layout` slice holds: the one home of 2D versus 3D.
1180
+ * @returns "2d" or "3d".
1181
+ */
1182
+ private dimension;
1183
+ /**
1184
+ * Record in the scene whether it is drawn flat, which the edge meshes read. The only writer of
1185
+ * `scene.metadata.twoD`: the `layout` hook and the opening view call it, from the slice.
1186
+ * @param twoD - Whether the scene is 2D.
1187
+ */
1188
+ private writeSceneDimension;
1189
+ /**
1190
+ * Whether the scene already draws a value of the `layout` slice in its dimension.
1191
+ * @param choice - The value.
1192
+ * @returns True when nothing about the scene needs to change for it.
1193
+ */
1194
+ private sceneDrawn;
1008
1195
  /**
1009
1196
  * Frame the graph on the element's own initiative -- after a data load, a new layout, or the
1010
1197
  * first settlement -- unless the configuration placed the camera itself with
@@ -1029,8 +1216,14 @@ export declare class Graph implements GraphContext {
1029
1216
  /**
1030
1217
  * Set the view mode.
1031
1218
  * This controls the camera type, input handling, and rendering approach.
1219
+ *
1220
+ * Switching between 2D and 3D is one undoable step (`view.dimension`). Entering VR or AR is
1221
+ * not a step -- it is a device session -- but VR and AR draw in 3D, so asking for one from 2D
1222
+ * switches to 3D first, and the switch and the entry are one step. When entry fails, because
1223
+ * the browser has no WebXR or the session is refused, nothing is recorded, the graph stays in
1224
+ * the dimension it was in, and the failure is logged rather than thrown.
1032
1225
  * @param mode - The view mode to set: "2d", "3d", "ar", or "vr"
1033
- * @param options - Optional queueing options
1226
+ * @param options - Optional queueing options; `skipQueue` switches at once.
1034
1227
  * @returns Promise that resolves when view mode is set
1035
1228
  * @example
1036
1229
  * ```typescript
@@ -1043,25 +1236,49 @@ export declare class Graph implements GraphContext {
1043
1236
  */
1044
1237
  setViewMode(mode: ViewMode, options?: QueueableOptions): Promise<void>;
1045
1238
  /**
1046
- * Internal method for setting view mode - bypasses queue
1047
- * Used by operations that are already queued
1048
- *
1049
- * WHAT "PREVIOUS" MEANS HERE IS THE SCENE, NOT THE CONFIGURATION, and the distinction is the
1050
- * whole reason an opening 2D used to be impossible. This method's job is to move the scene
1051
- * from the view it is drawing to the view that was asked for, so the only honest reading of
1052
- * "the view it is drawing" is the scene itself -- which camera is active and what
1053
- * `scene.metadata` records. The configuration is a statement of what the graph should be,
1054
- * written by `applyOpeningViewMode` at init and by the public `setViewMode` before its
1055
- * operation is queued, so diffing against it answers "has anyone asked for this yet" rather
1056
- * than "is it already so", and those are different questions the moment a mode is asked for
1057
- * before there is a scene to put it in.
1058
- *
1059
- * Reading the scene also makes the method idempotent and self-repairing: a redundant switch
1060
- * to the mode already on screen costs nothing, and a scene that has drifted out of step with
1061
- * its configuration is brought back rather than declared fine.
1062
- * @param mode - The view mode to set
1239
+ * Dispatch a door's command, resolving rather than rejecting when a newer request of the same
1240
+ * kind made it redundant before it ran: that is the caller's own later decision, not a failure
1241
+ * they have to handle. Undone or failed, it rejects.
1242
+ * @param command - The command.
1243
+ * @param options - How it joins the queue.
1244
+ * @param options.beside - Start at once, beside the queue.
1245
+ */
1246
+ private dispatchSuperseded;
1247
+ /**
1248
+ * Bring the engine, the scene's dimension and the camera to a value of the `layout` slice:
1249
+ * the `layout` hook. Run inline by `layout.set` and `view.dimension`, and by the derivation
1250
+ * pass after undo, redo or a rollback.
1251
+ * @param choice - The value.
1252
+ * @param how - `restoring` for undo, redo, a restore or a rollback; `signal` stops the build.
1253
+ * @param how.restoring - Whether this is a restore: no pre-steps, the layout left at rest.
1254
+ * @param how.signal - The asking command's signal.
1255
+ * @param how.explicitScope - Whether the command named the scope, so a scope that cannot be
1256
+ * laid out is refused rather than left inactive.
1257
+ * @returns Settles once the engine is built and its pre-steps have landed.
1258
+ */
1259
+ private applyLayout;
1260
+ /**
1261
+ * Rebuild the scene for a new dimension, before the engine is rebuilt: the mesh cache, the
1262
+ * scene's record, the camera, and every node and edge mesh.
1263
+ * @param twoD - Whether the scene becomes 2D.
1063
1264
  */
1064
- private _setViewModeInternal;
1265
+ private enterDimension;
1266
+ /**
1267
+ * Put the nodes and edges where the new dimension draws them, once the engine is rebuilt:
1268
+ * flat in 2D, and at the coordinates the position array holds in 3D.
1269
+ * @param twoD - Whether the scene is 2D now.
1270
+ * @param frame - Frame the camera on the nodes, as a forward switch does.
1271
+ */
1272
+ private settleDimension;
1273
+ /**
1274
+ * Enter or leave an immersive session: `view.immersive`. Exempt from history -- a device
1275
+ * session is not the document -- and refused from 2D, which the caller switches out of in
1276
+ * the same step first.
1277
+ * @param mode - VR, AR, or null to leave.
1278
+ * @throws A `GraphtyError` with `E_BAD_COMMAND` from 2D, or `E_UNSUPPORTED` without WebXR;
1279
+ * whatever the browser rejects the session with otherwise.
1280
+ */
1281
+ private setImmersive;
1065
1282
  /**
1066
1283
  * Check if ray updates are needed for edge arrows.
1067
1284
  * @returns True if rays need updating
@@ -1547,6 +1764,37 @@ export declare class Graph implements GraphContext {
1547
1764
  * @returns Promise that resolves when camera is reset
1548
1765
  */
1549
1766
  resetCamera(options?: import("./screenshot/types.js").CameraAnimationOptions): Promise<void>;
1767
+ /**
1768
+ * Move the camera one step nearer or further, the way a Zoom in or Zoom out button does.
1769
+ *
1770
+ * One step is a factor of 1.25: the 3D orbit camera's distance from its pivot is divided or
1771
+ * multiplied by it, and the 2D camera's zoom multiplied or divided. The
1772
+ * camera is view state, so this is not an undoable step.
1773
+ * @param direction - `"in"` to approach, `"out"` to withdraw.
1774
+ * @param options - Optional animation configuration.
1775
+ * @returns Promise that resolves when the camera has moved.
1776
+ * @since 3.0.0
1777
+ * @example
1778
+ * ```typescript
1779
+ * await graph.zoomStep("in");
1780
+ * ```
1781
+ */
1782
+ zoomStep(direction: "in" | "out", options?: import("./screenshot/types.js").CameraAnimationOptions): Promise<void>;
1783
+ /**
1784
+ * Centre the camera on the selected nodes, keeping where it stands.
1785
+ *
1786
+ * The camera turns to look at the centre of the box around the selected nodes; with nothing
1787
+ * selected it does not move. The camera is view state, so this is not an undoable step.
1788
+ * @param options - Optional animation configuration.
1789
+ * @returns Promise that resolves when the camera has moved.
1790
+ * @since 3.0.0
1791
+ * @example
1792
+ * ```typescript
1793
+ * await graph.select({ nodes: ["n1"] });
1794
+ * await graph.zoomToSelection();
1795
+ * ```
1796
+ */
1797
+ zoomToSelection(options?: import("./screenshot/types.js").CameraAnimationOptions): Promise<void>;
1550
1798
  /**
1551
1799
  * Get default camera state for current camera type
1552
1800
  * Lazily captures the initial state on first use, or returns captured state
@@ -1607,15 +1855,25 @@ export declare class Graph implements GraphContext {
1607
1855
  params?: Readonly<Record<string, unknown>>;
1608
1856
  } & import("./screenshot/types.js").CameraAnimationOptions): Promise<void>;
1609
1857
  /**
1610
- * Save where the camera is now under a name of the consumer's choosing.
1858
+ * Save where the camera is now under a name of the consumer's choosing. One undoable step.
1611
1859
  *
1612
1860
  * A snapshot records a POSITION, not a rule: it cannot re-derive itself for a different graph
1613
1861
  * the way a camera view does. Which is why a name a view already holds -- the element's own
1614
1862
  * or a registered one -- is refused rather than shadowed.
1615
1863
  * @param name - The name to save it under.
1864
+ * @param camera - The camera state to save instead of where the camera is now.
1616
1865
  * @throws A `GraphtyError` with `E_PROTECTED` when a camera view already answers to the name.
1617
1866
  */
1618
- saveCameraPreset(name: string): void;
1867
+ saveCameraPreset(name: string, camera?: import("./screenshot/types.js").CameraState): void;
1868
+ /**
1869
+ * Forget a camera state saved with `saveCameraPreset` or `importCameraPresets`. One undoable
1870
+ * step.
1871
+ * @param name - The name it was saved under.
1872
+ * @returns Settles once the step is recorded.
1873
+ * @throws A `GraphtyError` (as a rejection) with `E_BAD_COMMAND` when nothing is saved under
1874
+ * the name.
1875
+ */
1876
+ removeCameraPreset(name: string): Promise<void>;
1619
1877
  /**
1620
1878
  * Load a camera preset (built-in or user-defined)
1621
1879
  * @param name - Name of the preset to load
@@ -1643,7 +1901,7 @@ export declare class Graph implements GraphContext {
1643
1901
  */
1644
1902
  exportCameraPresets(): Record<string, import("./screenshot/types.js").CameraState>;
1645
1903
  /**
1646
- * Import user-defined presets from JSON
1904
+ * Import user-defined presets from JSON, as one undoable step.
1647
1905
  * @param presets - Object mapping preset names to camera states
1648
1906
  */
1649
1907
  importCameraPresets(presets: Record<string, import("./screenshot/types.js").CameraState>): void;