@graphty/graphty-element 2.0.1 → 2.2.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 (81) hide show
  1. package/README.md +3 -3
  2. package/dist/ai.js +4 -4
  3. package/dist/catalog.js +5 -5
  4. package/dist/chunks/{AiManager-awS0MNr1.js → AiManager-Dp1mOkPm.js} +5 -5
  5. package/dist/chunks/{Algorithm-BdcqHKps.js → Algorithm-RQ629NLb.js} +210 -92
  6. package/dist/chunks/{DataSource-DK4GZBKg.js → DataSource-DEg3igzS.js} +3 -3
  7. package/dist/chunks/{GraphSession-D87eymV8.js → GraphSession-D3AV8tpF.js} +2527 -2248
  8. package/dist/chunks/{GraphtyError-B3eKs4yg.js → GraphtyError-BwcnblTH.js} +10 -8
  9. package/dist/chunks/{GraphtyLogger-CK03SnJi.js → GraphtyLogger-5KEttFUo.js} +1 -1
  10. package/dist/chunks/{NodeStyle-CS7dj20m.js → NodeStyle-Cup9O1lu.js} +2 -1
  11. package/dist/chunks/{VoiceInputAdapter-CcnCmxo5.js → VoiceInputAdapter-Bbze1r8k.js} +1 -1
  12. package/dist/chunks/{XRPivotCameraController-UjMsbran.js → XRPivotCameraController-8Il3KxFm.js} +2 -2
  13. package/dist/chunks/{cameras-BeIAlMWR.js → cameras-CeJYi-Na.js} +17 -18
  14. package/dist/chunks/{capability-check-DcKFwS6q.js → capability-check-EUCOfQLP.js} +1 -1
  15. package/dist/chunks/{detect-B-YbbP7i.js → detect-CqN0mC6u.js} +3 -3
  16. package/dist/chunks/{format-detection-DohSEZnb.js → format-detection-C8vbCSlS.js} +1 -1
  17. package/dist/chunks/{index-uohvGegX.js → index-Cz47b_vU.js} +1957 -1318
  18. package/dist/chunks/{paletteRegistry-B-oS4YxP.js → paletteRegistry-NrWOKT-A.js} +17 -17
  19. package/dist/chunks/{registry-DU-e49Y2.js → registry-CSba5QGJ.js} +1 -1
  20. package/dist/chunks/{scales-DvGid5Ln.js → scales-ulKMZPfG.js} +2206 -1357
  21. package/dist/custom-elements.json +1 -1
  22. package/dist/extend.js +26 -27
  23. package/dist/graphty-catalog.json +7 -4
  24. package/dist/graphty.bundle.js +36572 -34379
  25. package/dist/graphty.js +66 -64
  26. package/dist/index.d.ts +1 -1
  27. package/dist/logging.js +2 -2
  28. package/dist/schema.js +1 -1
  29. package/dist/session.d.ts +2 -1
  30. package/dist/session.js +37 -33
  31. package/dist/src/Edge.d.ts +1 -1
  32. package/dist/src/Graph.d.ts +42 -8
  33. package/dist/src/Node.d.ts +3 -4
  34. package/dist/src/acceleration/AccelerationController.d.ts +27 -0
  35. package/dist/src/acceleration/index.d.ts +1 -1
  36. package/dist/src/acceleration/narrow.d.ts +56 -0
  37. package/dist/src/acceleration/types.d.ts +88 -7
  38. package/dist/src/algorithms/Algorithm.d.ts +96 -2
  39. package/dist/src/algorithms/BFSAlgorithm.d.ts +9 -0
  40. package/dist/src/algorithms/DijkstraAlgorithm.d.ts +2 -8
  41. package/dist/src/algorithms/PageRankAlgorithm.d.ts +8 -0
  42. package/dist/src/algorithms/utils/graphUtils.d.ts +13 -0
  43. package/dist/src/cameras/OrbitCameraController.d.ts +1 -0
  44. package/dist/src/catalog/layouts.d.ts +13 -1
  45. package/dist/src/config/GraphBehavior.d.ts +16 -0
  46. package/dist/src/config/GraphStyle.d.ts +1 -1
  47. package/dist/src/config/StyleTemplate.d.ts +10 -0
  48. package/dist/src/data/CSVDataSource.d.ts +1 -0
  49. package/dist/src/data/csv-variant-detection.d.ts +11 -0
  50. package/dist/src/errors/codes.d.ts +14 -1
  51. package/dist/src/events.d.ts +17 -4
  52. package/dist/src/graphty-element.d.ts +52 -4
  53. package/dist/src/layout/ForceAtlas2LayoutEngine.d.ts +28 -45
  54. package/dist/src/layout/LayoutEngine.d.ts +7 -7
  55. package/dist/src/layout/SimulationLayoutEngine.d.ts +458 -0
  56. package/dist/src/layout/SpringElectricalLayoutEngine.d.ts +32 -0
  57. package/dist/src/layout/SpringLayoutEngine.d.ts +22 -32
  58. package/dist/src/managers/DataManager.d.ts +2 -0
  59. package/dist/src/managers/EventManager.d.ts +7 -0
  60. package/dist/src/managers/GraphContext.d.ts +6 -0
  61. package/dist/src/managers/LabelDeclutter.d.ts +97 -0
  62. package/dist/src/managers/LayoutManager.d.ts +98 -4
  63. package/dist/src/managers/RenderManager.d.ts +7 -0
  64. package/dist/src/managers/UpdateManager.d.ts +1 -1
  65. package/dist/src/meshes/NodeEffects.d.ts +29 -5
  66. package/dist/src/meshes/RichTextLabel.d.ts +17 -0
  67. package/dist/src/session/catalog.d.ts +2 -2
  68. package/dist/src/session/query.d.ts +83 -0
  69. package/dist/src/session/runs/types.d.ts +10 -4
  70. package/dist/src/session/selection/targets.d.ts +20 -3
  71. package/dist/src/session/styles/StylesApi.d.ts +18 -0
  72. package/dist/src/session/styles/channels.d.ts +0 -2
  73. package/dist/src/session/styles/legend.d.ts +9 -0
  74. package/dist/src/session/styles/predicate.d.ts +11 -0
  75. package/dist/src/session/styles/sources.d.ts +16 -0
  76. package/dist/src/session/types.d.ts +38 -2
  77. package/dist/src/testing/fakeAccelerator.d.ts +323 -0
  78. package/dist/webgpu.d.ts +23 -1
  79. package/dist/webgpu.js +70 -32
  80. package/package.json +10 -8
  81. package/dist/chunks/types-Dwm9waL2.js +0 -7
@@ -50,6 +50,20 @@ export type AccelerationState = "probing" | "active" | "idle" | "unavailable" |
50
50
  * next visit, is the host application's storage and the host application's job.
51
51
  */
52
52
  export type AccelerationPolicy = "auto" | "off" | "required";
53
+ /** The three values, in the order a control offers them. */
54
+ export declare const ACCELERATION_POLICIES: readonly AccelerationPolicy[];
55
+ /** What the element does when nothing was asked: `auto`. */
56
+ export declare const ACCELERATION_POLICY_DEFAULT: AccelerationPolicy;
57
+ /**
58
+ * Whether a value is one of the three acceleration policies.
59
+ *
60
+ * A host that offers the choice gets the value back from storage, a query string or a change
61
+ * handler, where it is an unknown string. This is the check the element itself runs on the
62
+ * `acceleration` attribute, so a host cannot accept a value the element would refuse.
63
+ * @param value - Anything at all.
64
+ * @returns True when `value` is `"auto"`, `"off"` or `"required"`.
65
+ */
66
+ export declare function isAccelerationPolicy(value: unknown): value is AccelerationPolicy;
53
67
  /**
54
68
  * The arithmetic that produced a set of numbers.
55
69
  *
@@ -74,13 +88,21 @@ export declare const DEFAULT_ACCELERATOR_PRECISION: AccelerationPrecision;
74
88
  *
75
89
  * Three plain strings, so a status chip can render "NVIDIA, ampere" without importing a GPU
76
90
  * type or parsing a renderer string.
91
+ *
92
+ * This side is ALWAYS PRESENT, MAY BE EMPTY: an accelerator fills in what its driver told it and
93
+ * `""` for what it did not, so an implementer never has to choose between `""` and `undefined`.
94
+ * {@link AccelerationStatus}, what a consumer reads, is the opposite -- a field is there only
95
+ * when the backend reported one -- and `AccelerationController` is the single place that
96
+ * converts between the two, dropping every empty string on the way out. Keep it that way: a
97
+ * browser masks the device and the description for an ordinary origin, so empty is the common
98
+ * case and a consumer must never be handed `""` to render.
77
99
  */
78
100
  export interface AcceleratorDeviceInfo {
79
- /** The hardware vendor, as the driver reports it: `"nvidia"`, `"apple"`, `"intel"`. */
101
+ /** The hardware vendor, as the driver reports it: `"nvidia"`, `"apple"`, `""` when unknown. */
80
102
  readonly vendor: string;
81
103
  /** The device family, as the driver reports it: `"ampere"`, `"rdna-3"`, `""` when unknown. */
82
104
  readonly architecture: string;
83
- /** A human-readable description of the device. May be empty; never undefined. */
105
+ /** A human-readable description of the device, `""` when unknown. Never undefined. */
84
106
  readonly description: string;
85
107
  }
86
108
  /**
@@ -115,9 +137,42 @@ export interface GraphAccelerator {
115
137
  }>;
116
138
  /** The arithmetic this accelerator computes in. Absent means {@link DEFAULT_ACCELERATOR_PRECISION}. */
117
139
  readonly precision?: AccelerationPrecision;
140
+ /**
141
+ * Proves this accelerator computes correctly, before any of the element's work is planned
142
+ * onto it.
143
+ *
144
+ * Hardware that answers is not the same thing as hardware that answers correctly. The
145
+ * software renderer that ships with Windows miscomputes shaders that pass a value across a
146
+ * workgroup barrier: it builds, it runs, it returns plausible numbers, and every prefix sum,
147
+ * sort and grid layout over one of them is wrong. Nothing errors. A backend that can tell
148
+ * the difference implements this; one that cannot omits it, and the element attaches it on
149
+ * the strength of the probe as before.
150
+ *
151
+ * Resolve when the hardware is trustworthy. Reject with a `GraphtyError` carrying
152
+ * `E_DEVICE_INCORRECT` when it is not, and the element reports acceleration unavailable with
153
+ * that code and runs the CPU path -- the same place a missing adapter reaches, because a
154
+ * device that lies is no more usable than a device that is not there.
155
+ *
156
+ * The element calls it once, on an accelerator it built from a registered factory, before
157
+ * attaching it. An accelerator handed over already built through `setAccelerator` is not
158
+ * asked -- the element did not construct it and does not own its lifetime, and whoever did
159
+ * both vouched for it by handing it over.
160
+ *
161
+ * It is NOT a way to report a failure part-way through a run: work that has already started
162
+ * on the accelerator and then fails is that work's failure and throws.
163
+ * @returns Resolves when the accelerator is fit to be given work.
164
+ */
165
+ verify?(): Promise<void>;
118
166
  /** Releases the hardware resources. Called by the element when it detaches this accelerator. */
119
167
  dispose?(): void;
120
- /** An accelerated algorithm or layout, looked up by name and feature-tested before use. */
168
+ /**
169
+ * An accelerated algorithm or layout, looked up by name and feature-tested before use.
170
+ *
171
+ * `release(snapshot)` is one of these rather than a declared member: an accelerator that keeps
172
+ * device buffers for a snapshot implements it, and the element calls it when that snapshot
173
+ * stops being the graph, while an accelerator with no residency to free simply has no such
174
+ * member. Both are feature-tested the same way, so neither has to pretend to be the other.
175
+ */
121
176
  [algorithmOrLayout: string]: unknown;
122
177
  }
123
178
  /** What the element tells a factory before the factory builds anything. */
@@ -131,6 +186,14 @@ export interface AcceleratorFactoryOptions {
131
186
  * that does not care ignores the parameter.
132
187
  */
133
188
  readonly exactMaxNodes?: number;
189
+ /**
190
+ * Whether a software adapter (SwiftShader, llvmpipe) is acceptable.
191
+ *
192
+ * Under `"auto"` it is not: a software rasteriser is slower than the element's own CPU
193
+ * path, and attaching it would make the graph slower while reporting "active". Under
194
+ * `"required"` it is: the consumer said "no CPU path", and a software device is a device.
195
+ */
196
+ readonly acceptSoftware?: boolean;
134
197
  }
135
198
  /**
136
199
  * Builds an accelerator, or declines.
@@ -161,11 +224,18 @@ export interface AccelerationStatus {
161
224
  readonly state: AccelerationState;
162
225
  /** The attached accelerator's backend, when one is attached. */
163
226
  readonly backend?: "webgpu" | (string & {});
164
- /** The hardware vendor, when the backend reported one. */
227
+ /**
228
+ * The hardware vendor, when the backend reported one. Absent otherwise, never `""`.
229
+ *
230
+ * The three device facts arrive from an accelerator as {@link AcceleratorDeviceInfo}, where
231
+ * they are always present and an unknown one is `""`. They are published here the other way
232
+ * round, so a consumer can test one with `??` or `!== undefined` and never render an empty
233
+ * string. `AccelerationController` is what converts.
234
+ */
165
235
  readonly vendor?: string;
166
- /** The device family, when the backend reported one. */
236
+ /** The device family, when the backend reported one. Absent otherwise, never `""`. */
167
237
  readonly architecture?: string;
168
- /** The device description, when the backend reported one. */
238
+ /** The device description, when the backend reported one. Absent otherwise, never `""`. */
169
239
  readonly device?: string;
170
240
  /** Why acceleration is unavailable or has stopped, in a sentence a person can read. */
171
241
  readonly reason?: string;
@@ -278,6 +348,17 @@ export declare const ACCELERATION_MIN_NODES_KEY = "acceleration.minNodes";
278
348
  *
279
349
  * Raise it when a graph is small enough that uploading it costs more than computing it. There
280
350
  * is no defensible non-zero default, because the crossover has to be measured on the machine
281
- * the graph is drawn on.
351
+ * the graph is drawn on -- and this zero is a measurement, not a guess. On the dev box
352
+ * (RTX 4070 SUPER, headless Chromium, 2026-09-22) the accelerated layout's frame time was at or
353
+ * below the CPU simulation's at every size measured, starting with the smallest: 50.0 against
354
+ * 50.0 ms at 500 nodes, 116.7 against 116.7 at 1,000 and 183.3 against 216.6 at 2,000, three runs
355
+ * of sixty working frames per arm, all at average degree 10. A fourth size, 5,000 nodes, read
356
+ * 466.6 against 566.7 -- but from ONE run of five frames, so read it as indicative and not as what
357
+ * the default rests on. The crossover is therefore below the smallest graph worth accelerating,
358
+ * and the default stays 0.
359
+ *
360
+ * `scripts/measure-min-nodes.mjs` is the measurement, protocol in its header; the table and what
361
+ * it does not cover are in section 3 of `graphty-element/docs/decisions/G6.md` IN THE REPOSITORY,
362
+ * which is not part of the published documentation site.
282
363
  */
283
364
  export declare const ACCELERATION_MIN_NODES_DEFAULT = 0;
@@ -1,5 +1,7 @@
1
- import type { Graph as AlgorithmGraph } from "@graphty/algorithms";
2
- import type { AlgorithmDescriptor, FieldDescriptor } from "../catalog/types";
1
+ import { type AcceleratedAlgorithms, type Graph as AlgorithmGraph } from "@graphty/algorithms";
2
+ import { type GraphSnapshot, type U32 } from "@graphty/graph-format";
3
+ import { type AccelerationPrecision } from "../acceleration/types";
4
+ import type { AlgorithmDescriptor, FieldDescriptor, NodeId } from "../catalog/types";
3
5
  import { type OptionsSchema as ZodOptionsSchema } from "../config";
4
6
  import { Graph } from "../Graph";
5
7
  import type { RunResult } from "../session/results";
@@ -70,6 +72,57 @@ export interface AlgorithmStatics {
70
72
  /** Check if this algorithm has a Zod-based options schema */
71
73
  hasZodOptions(): boolean;
72
74
  }
75
+ /**
76
+ * One piece of accelerable work, with the decision "accelerator or CPU" already taken.
77
+ *
78
+ * An adapter reads the snapshot it is over, runs the work through {@link run}, and writes ONE
79
+ * loop over an index-aligned result whichever path produced it. The precision that comes back is
80
+ * what the run publishes as `caveats.precision`: a result computed on an accelerator says `f32`
81
+ * and one computed on the CPU port says `f64`, and a reader comparing two numbers has the
82
+ * qualification that explains the difference.
83
+ *
84
+ * Exported only because it is the return type of a protected member, which declaration emit
85
+ * requires to be nameable. An adapter receives one from `Algorithm.accelerated`; nothing outside
86
+ * this module constructs one or needs to name it.
87
+ * @internal
88
+ */
89
+ export interface AcceleratedAlgorithmRun {
90
+ /**
91
+ * The snapshot the work runs over: the declared one for `"directed"`, the undirected view for
92
+ * `"undirected"`, in either case with every group of parallel edges collapsed to one edge
93
+ * carrying the group's summed weight. Its `ids` map is how a node id becomes the index every
94
+ * result is keyed by, and the node space is the declared one either way.
95
+ */
96
+ readonly snapshot: GraphSnapshot;
97
+ /**
98
+ * Declared edge index -> edge index in {@link snapshot}, or null when the edge space is the
99
+ * declared one.
100
+ *
101
+ * This is the direction an edge-carrying result is read in: an adapter walks the element's own
102
+ * edges, maps each one's `Edge.index` through this, and asks whether that index is in the
103
+ * result. Read the other way (`edgeOrigin`) a merged group names only its survivor, so every
104
+ * edge the reader declared but one would silently go unflagged -- both halves of a reciprocal
105
+ * pair the undirected view collapsed, and every member of a group of parallel edges.
106
+ */
107
+ readonly edgeRemap: U32 | null;
108
+ /**
109
+ * Runs the work, on the accelerator when the controller said so and on the CPU port when it
110
+ * did not.
111
+ *
112
+ * A property rather than a method, so an adapter may take it out of the object it came in --
113
+ * `const { run } = this.accelerated(...)` -- which is how every one of them reads.
114
+ * @param fn - The work, written once against the dispatcher.
115
+ * @returns What the work produced, and the arithmetic it was produced in.
116
+ * @throws Whatever the accelerator threw, with its code. A failure after the work started is
117
+ * the run's failure: nothing is recomputed on the CPU.
118
+ */
119
+ readonly run: <T>(fn: (dispatch: AcceleratedAlgorithms, snapshot: GraphSnapshot) => Promise<T>) => Promise<{
120
+ /** What `fn` returned. */
121
+ readonly value: T;
122
+ /** The arithmetic it was computed in. */
123
+ readonly precision: AccelerationPrecision;
124
+ }>;
125
+ }
73
126
  /**
74
127
  * Base class for all graph algorithms
75
128
  * @template TOptions - The options type for this algorithm (defaults to empty object)
@@ -151,6 +204,47 @@ export declare abstract class Algorithm<TOptions extends Record<string, unknown>
151
204
  * @returns a freshly built Graph for the algorithm package
152
205
  */
153
206
  protected algorithmGraph(mode: AlgorithmGraphMode): AlgorithmGraph;
207
+ /**
208
+ * The route an algorithm with an accelerated implementation takes.
209
+ *
210
+ * It is the counterpart of {@link algorithmGraph} for the algorithms `@graphty/algorithms`
211
+ * can dispatch: instead of copying the snapshot into an object graph, the work runs over the
212
+ * snapshot itself, on the attached accelerator or on the index-based CPU port, and the adapter
213
+ * writes one loop over an index-aligned result either way.
214
+ *
215
+ * THE DECISION IS TAKEN ONCE, HERE, BEFORE ANY WORK STARTS. The controller answers "the policy
216
+ * is off", "no accelerator", "below `acceleration.minNodes`" or "this accelerator does not
217
+ * implement that" up front, and under `acceleration="required"` it throws `E_NO_ACCELERATOR`
218
+ * rather than answering quietly. After the work has started there is no second decision: a
219
+ * failure from the accelerator propagates with its code and fails the run, because a number
220
+ * that silently came from somewhere else is worse than no number.
221
+ * @param capability - The accelerator member this work would use, such as `"pageRank"`.
222
+ * @param mode - The shape this algorithm needs; see {@link AlgorithmGraphMode}. `"undirected"`
223
+ * takes the snapshot's undirected view, which is what collapses a reciprocal pair into one
224
+ * edge.
225
+ * @returns The snapshot, the edge map onto it, and the runner.
226
+ * @example
227
+ * ```ts
228
+ * const { snapshot, run } = this.accelerated("connectedComponents", "undirected");
229
+ * const { value, precision } = await run((dispatch, s) => dispatch.connectedComponents(s));
230
+ * const group = value.labels[snapshot.ids.indexOf(nodeId)];
231
+ * ```
232
+ */
233
+ protected accelerated(capability: string, mode: AlgorithmGraphMode): AcceleratedAlgorithmRun;
234
+ /**
235
+ * The dense row of a node the reader named in an option.
236
+ *
237
+ * A search takes its source as an id and the snapshot answers in indices, so this is where the
238
+ * two meet -- and where an id that names no node in the graph is reported as what it is: an
239
+ * option whose value is outside the permitted range, carrying the option's name and what was
240
+ * passed, rather than a silent empty result or a search from row zero.
241
+ * @param snapshot - The graph the work runs over.
242
+ * @param option - The option the id came from, named in the error.
243
+ * @param id - The node id the reader gave.
244
+ * @returns The node's dense row.
245
+ * @throws A `GraphtyError` with `E_OPTION_RANGE` when the graph has no such node.
246
+ */
247
+ protected nodeIndex(snapshot: GraphSnapshot, option: string, id: NodeId): number;
154
248
  /**
155
249
  * Resolves and validates options against the schema
156
250
  * @param options - User-provided options (partial)
@@ -50,5 +50,14 @@ export declare class BFSAlgorithm extends DeclaredAlgorithm<BFSOptions> {
50
50
  * @returns The layered result, or null when there is nothing to walk.
51
51
  */
52
52
  compute(context: AlgorithmRunContext): Promise<AlgorithmOutput | null>;
53
+ /**
54
+ * Walk with an early stop at a target, on the CPU reference implementation.
55
+ * @param context - What the element gave the run.
56
+ * @param nodeIds - The nodes to publish for.
57
+ * @param source - Where the walk starts.
58
+ * @param targetNode - Where it stops.
59
+ * @returns The layered result, or null when the source is not in the graph.
60
+ */
61
+ private legacyWalk;
53
62
  }
54
63
  export {};
@@ -9,14 +9,14 @@ interface DijkstraOptions extends Record<string, unknown> {
9
9
  source: number | string | null;
10
10
  /** Destination node for shortest path (defaults to last node if not provided) */
11
11
  target: number | string | null;
12
- /** Use bidirectional search optimization for point-to-point queries */
12
+ /** Accepted and ignored; see the option's description. */
13
13
  bidirectional: boolean;
14
14
  }
15
15
  /**
16
16
  * Dijkstra's algorithm for finding shortest paths
17
17
  *
18
18
  * Computes shortest paths from a source node to all other nodes using
19
- * non-negative edge weights. Supports bidirectional search optimization.
19
+ * non-negative edge weights.
20
20
  */
21
21
  export declare class DijkstraAlgorithm extends DeclaredAlgorithm<DijkstraOptions> {
22
22
  static namespace: string;
@@ -53,11 +53,5 @@ export declare class DijkstraAlgorithm extends DeclaredAlgorithm<DijkstraOptions
53
53
  * @returns The route, or null when there are no nodes to search.
54
54
  */
55
55
  compute(context: AlgorithmRunContext): Promise<AlgorithmOutput | null>;
56
- /**
57
- * Get set of edge keys that are part of the path
58
- * @param path - Array of node IDs representing the path
59
- * @returns Set of edge keys in "srcId:dstId" format
60
- */
61
- private getPathEdges;
62
56
  }
63
57
  export {};
@@ -138,6 +138,14 @@ export declare class PageRankAlgorithm extends MetricAlgorithm<PageRankOptions>
138
138
  * Resolved options using the NEW Zod-based validation
139
139
  */
140
140
  private zodOptions;
141
+ /**
142
+ * The two Map-valued options, kept from what the caller passed.
143
+ *
144
+ * NEITHER SCHEMA CARRIES THEM -- a Map is not a value a form or a saved document can hold --
145
+ * and `resolveOptions` returns only the keys its schema declares, so reading them back off the
146
+ * resolved options found nothing and a personalized run quietly ran an unpersonalized one.
147
+ */
148
+ private readonly programmaticOptions;
141
149
  /**
142
150
  * Creates a new PageRank algorithm instance
143
151
  * @param g - The graph to run the algorithm on
@@ -15,6 +15,19 @@
15
15
  * @returns the lookup key
16
16
  */
17
17
  export declare function edgePairKey(source: string | number, target: string | number): string;
18
+ /**
19
+ * Refuse a node id option that names no node in the graph.
20
+ *
21
+ * `@graphty/algorithms` answers a query about a missing node with an empty result rather than an
22
+ * error, so without this check an unknown id publishes zeros as if they were a measurement.
23
+ * @param algorithm - The algorithm's key, for the message.
24
+ * @param option - The option name the id came in on.
25
+ * @param value - The id the caller passed.
26
+ * @param nodeIds - Every node id in the graph.
27
+ * @returns The id as the string the algorithms package keys nodes by.
28
+ * @throws A `GraphtyError` coded `E_OPTION_RANGE` when no node has that id.
29
+ */
30
+ export declare function requireNodeOption(algorithm: string, option: string, value: string | number, nodeIds: readonly (string | number)[]): string;
18
31
  /**
19
32
  * Minimal edge data interface required by graph utilities
20
33
  */
@@ -15,6 +15,7 @@ export interface OrbitConfig {
15
15
  * Provides trackball-style rotation and keyboard/touch controls.
16
16
  */
17
17
  export declare class OrbitCameraController {
18
+ #private;
18
19
  scene: Scene;
19
20
  camera: UniversalCamera;
20
21
  cameraDistance: number;
@@ -2,7 +2,7 @@
2
2
  * @file The layout catalogue: the arrangements the element offers, and the engines behind them.
3
3
  *
4
4
  * A public layout name says what the arrangement IS -- "force", "hierarchical", "circular" --
5
- * and never which library draws it. The element registers sixteen engines whose registered
5
+ * and never which library draws it. The element registers seventeen engines whose registered
6
6
  * names ARE their implementations ("ngraph", "d3", "forceatlas2"), and freezing those into the
7
7
  * public API makes swapping an implementation a rename every consumer can see. So the engine is
8
8
  * data on the descriptor instead: `LayoutDescriptor.engine` names the implementation the element
@@ -46,6 +46,18 @@ export interface LayoutImplementation {
46
46
  * catalogue cannot claim a weight channel an engine does not have.
47
47
  */
48
48
  honoursWeights: boolean;
49
+ /**
50
+ * What has to be true before this engine can run at all, in the same shape an algorithm
51
+ * declares it.
52
+ *
53
+ * `accelerator: true` means the engine is computed on hardware and has no processor
54
+ * implementation, so a picker greys the entry out when `capabilities.acceleration.state` says
55
+ * nothing is attached. It belongs to the ENGINE rather than to the arrangement: `force` is
56
+ * drawn by six engines, five of which need nothing.
57
+ */
58
+ requires?: {
59
+ accelerator?: boolean;
60
+ };
49
61
  }
50
62
  /** One semantic layout, with every engine that can draw it. */
51
63
  export interface LayoutCatalogEntry {
@@ -1,6 +1,17 @@
1
1
  import { z } from "zod/v4";
2
2
  import type { Graph } from "../Graph";
3
3
  import type { Node as GraphNode } from "../Node";
4
+ declare const GraphLayoutOpts: z.ZodObject<{
5
+ type: z.ZodDefault<z.ZodString>;
6
+ preSteps: z.ZodDefault<z.ZodNumber>;
7
+ stepMultiplier: z.ZodDefault<z.ZodNumber>;
8
+ minDelta: z.ZodDefault<z.ZodNumber>;
9
+ zoomStepInterval: z.ZodDefault<z.ZodNumber>;
10
+ iterationsPerStep: z.ZodOptional<z.ZodNumber>;
11
+ maxInFlight: z.ZodDefault<z.ZodNumber>;
12
+ }, z.core.$strict>;
13
+ /** How the element drives a layout, as the behaviour configuration resolves it. */
14
+ export type GraphLayoutBehavior = z.infer<typeof GraphLayoutOpts>;
4
15
  /** How the element drives the layout, as a caller supplies it: every field optional. */
5
16
  export type GraphBehaviorConfig = z.input<typeof GraphBehaviorOpts>;
6
17
  export declare const GraphBehaviorOpts: z.ZodObject<{
@@ -10,10 +21,15 @@ export declare const GraphBehaviorOpts: z.ZodObject<{
10
21
  stepMultiplier: z.ZodDefault<z.ZodNumber>;
11
22
  minDelta: z.ZodDefault<z.ZodNumber>;
12
23
  zoomStepInterval: z.ZodDefault<z.ZodNumber>;
24
+ iterationsPerStep: z.ZodOptional<z.ZodNumber>;
25
+ maxInFlight: z.ZodDefault<z.ZodNumber>;
13
26
  }, z.core.$strict>>;
14
27
  node: z.ZodPrefault<z.ZodObject<{
15
28
  pinOnDrag: z.ZodDefault<z.ZodBoolean>;
16
29
  }, z.core.$strict>>;
30
+ labels: z.ZodPrefault<z.ZodObject<{
31
+ declutter: z.ZodDefault<z.ZodBoolean>;
32
+ }, z.core.$strict>>;
17
33
  fetchNodes: z.ZodOptional<z.ZodCustom<Function, Function>>;
18
34
  fetchEdges: z.ZodOptional<z.ZodCustom<Function, Function>>;
19
35
  }, z.core.$strict>;
@@ -42,7 +42,7 @@ declare const GraphSelectionStyle: z.ZodObject<{
42
42
  /** How solid the halo is, in `[0, 1]`. Low enough to read as a highlight rather than a node. */
43
43
  opacity: z.ZodDefault<z.ZodNumber>;
44
44
  }, z.core.$strict>;
45
- /** What a selected node looks like, as it parses. See {@link GraphSelectionStyle}. */
45
+ /** What a selected node looks like, as it parses. See {@link GraphSelectionStyleOpts}. */
46
46
  export type GraphSelectionStyleConfig = z.infer<typeof GraphSelectionStyle>;
47
47
  /** What a caller may say about the selection highlight: every field optional. */
48
48
  export type GraphSelectionStyleInput = z.input<typeof GraphSelectionStyle>;
@@ -922,10 +922,15 @@ declare const StyleTemplateV1: z.ZodObject<{
922
922
  stepMultiplier: z.ZodDefault<z.ZodNumber>;
923
923
  minDelta: z.ZodDefault<z.ZodNumber>;
924
924
  zoomStepInterval: z.ZodDefault<z.ZodNumber>;
925
+ iterationsPerStep: z.ZodOptional<z.ZodNumber>;
926
+ maxInFlight: z.ZodDefault<z.ZodNumber>;
925
927
  }, z.core.$strict>>;
926
928
  node: z.ZodPrefault<z.ZodObject<{
927
929
  pinOnDrag: z.ZodDefault<z.ZodBoolean>;
928
930
  }, z.core.$strict>>;
931
+ labels: z.ZodPrefault<z.ZodObject<{
932
+ declutter: z.ZodDefault<z.ZodBoolean>;
933
+ }, z.core.$strict>>;
929
934
  fetchNodes: z.ZodOptional<z.ZodCustom<Function, Function>>;
930
935
  fetchEdges: z.ZodOptional<z.ZodCustom<Function, Function>>;
931
936
  }, z.core.$strict>>;
@@ -1853,10 +1858,15 @@ export declare const StyleTemplate: z.ZodDiscriminatedUnion<[z.ZodObject<{
1853
1858
  stepMultiplier: z.ZodDefault<z.ZodNumber>;
1854
1859
  minDelta: z.ZodDefault<z.ZodNumber>;
1855
1860
  zoomStepInterval: z.ZodDefault<z.ZodNumber>;
1861
+ iterationsPerStep: z.ZodOptional<z.ZodNumber>;
1862
+ maxInFlight: z.ZodDefault<z.ZodNumber>;
1856
1863
  }, z.core.$strict>>;
1857
1864
  node: z.ZodPrefault<z.ZodObject<{
1858
1865
  pinOnDrag: z.ZodDefault<z.ZodBoolean>;
1859
1866
  }, z.core.$strict>>;
1867
+ labels: z.ZodPrefault<z.ZodObject<{
1868
+ declutter: z.ZodDefault<z.ZodBoolean>;
1869
+ }, z.core.$strict>>;
1860
1870
  fetchNodes: z.ZodOptional<z.ZodCustom<Function, Function>>;
1861
1871
  fetchEdges: z.ZodOptional<z.ZodCustom<Function, Function>>;
1862
1872
  }, z.core.$strict>>;
@@ -1,6 +1,7 @@
1
1
  import { type CSVVariant } from "./csv-variant-detection.js";
2
2
  import { BaseDataSourceConfig, DataSource, DataSourceChunk } from "./DataSource.js";
3
3
  interface CSVDataSourceConfig extends BaseDataSourceConfig {
4
+ /** The column separator. Worked out from the first line (comma, tab, semicolon or pipe) when unset. */
4
5
  delimiter?: string;
5
6
  variant?: CSVVariant;
6
7
  /**
@@ -10,6 +10,17 @@ export interface CSVVariantInfo {
10
10
  typeColumn?: string;
11
11
  interactionColumn?: string;
12
12
  }
13
+ /**
14
+ * Work out a delimited file's column separator from its first line.
15
+ *
16
+ * Papaparse's own guess is not used because it guesses from the rows it previews, and the one-row
17
+ * preview that reads the header row sees too little to tell a tab from a comma: it answers "," and
18
+ * the header `source<TAB>target` comes back as one column.
19
+ * @param content - The file, or at least its first line.
20
+ * @returns Whichever of comma, tab, semicolon and pipe appears most often outside quotes on the
21
+ * first line, or a comma when none does.
22
+ */
23
+ export declare function sniffDelimiter(content: string): string;
13
24
  /**
14
25
  * Detect CSV variant from headers and sample data
15
26
  * @param headers - Array of column header names
@@ -243,6 +243,19 @@ export type GraphtyErrorCode =
243
243
  * silence.
244
244
  */
245
245
  | "E_SOFTWARE_ONLY"
246
+ /**
247
+ * An adapter was found, it answered, and its answers are wrong. Before any of the element's
248
+ * work goes to an accelerator, the accelerator is asked to compute something whose answer is
249
+ * already known; a device that gets that wrong is refused, and the CPU path runs. The
250
+ * software renderer that ships with Windows is the device this exists for: it miscomputes
251
+ * shaders that pass a value across a workgroup barrier, so every prefix sum, sort and grid
252
+ * layout above one comes back wrong -- with plausible numbers and no error anywhere.
253
+ *
254
+ * `details` carry what the accelerator reported about the disagreement. Reported through
255
+ * `capabilities.acceleration` rather than thrown during ordinary use. Nothing the caller
256
+ * changes helps; a driver update might.
257
+ */
258
+ | "E_DEVICE_INCORRECT"
246
259
  /**
247
260
  * The GPU device was lost mid-session -- a driver reset, a tab suspension, or the browser
248
261
  * reclaiming the device. `details.reason` carries what the runtime said. The element reports
@@ -292,7 +305,7 @@ export declare const GRAPHTY_ERROR_CODES: readonly GraphtyErrorCode[];
292
305
  * This is the type of `capabilities.acceleration.code`, where a code is reported rather than
293
306
  * thrown: absence of acceleration is a state the consumer renders, not a failure it catches.
294
307
  */
295
- export type AccelerationErrorCode = "E_NO_WEBGPU" | "E_NO_ADAPTER" | "E_SOFTWARE_ONLY" | "E_DEVICE_LOST" | "E_TOO_LARGE";
308
+ export type AccelerationErrorCode = "E_NO_WEBGPU" | "E_NO_ADAPTER" | "E_SOFTWARE_ONLY" | "E_DEVICE_INCORRECT" | "E_DEVICE_LOST" | "E_TOO_LARGE";
296
309
  /**
297
310
  * Every code that can appear on `capabilities.acceleration.code`.
298
311
  */
@@ -13,7 +13,7 @@ export type GraphEventType = GraphEvent["type"];
13
13
  export type NodeEventType = NodeEvent["type"];
14
14
  export type EdgeEventType = EdgeEvent["type"];
15
15
  type AiEventType = AiEvent["type"];
16
- export type GraphEvent = GraphSettledEvent | GraphErrorEvent | GraphDataLoadedEvent | GraphDataAddedEvent | GraphSnapshotReplacedEvent | GraphLayoutInitializedEvent | CameraStateChangedEvent | GraphGenericEvent | DataLoadingProgressEvent | DataLoadingErrorEvent | DataLoadingErrorSummaryEvent | DataLoadingCompleteEvent | ElementsRemovedEvent | SelectionChangedEvent;
16
+ export type GraphEvent = GraphSettledEvent | GraphErrorEvent | GraphDataLoadedEvent | GraphDataAddedEvent | GraphSnapshotReplacedEvent | GraphSnapshotDroppedEvent | GraphLayoutInitializedEvent | CameraStateChangedEvent | GraphGenericEvent | DataLoadingProgressEvent | DataLoadingErrorEvent | DataLoadingErrorSummaryEvent | DataLoadingCompleteEvent | ElementsRemovedEvent | SelectionChangedEvent;
17
17
  /**
18
18
  * The graph event types that stay INSIDE the element: emitted on the internal graph observable so
19
19
  * the element's own managers can react, and never re-dispatched to the DOM.
@@ -69,9 +69,11 @@ export interface GraphDataAddedEvent {
69
69
  * Emitted by DataManager after every freeze, once the element's position column is attached to the
70
70
  * new snapshot (graph-format design 14.4 rule 11).
71
71
  *
72
- * Listeners release per-snapshot resources: at E1 `Graph` releases the accelerator's GPU buffers for
73
- * `previous` and its derived views, and caches drop their entries. Nothing a WeakMap can do for
74
- * them -- GPU memory is not garbage collected.
72
+ * Listeners release per-snapshot resources: `Graph` releases the accelerator's buffers for
73
+ * `previous` and for its undirected copy when that is a distinct snapshot (the release list of the
74
+ * WebGPU design 9.4 item 2), and caches drop their entries. Nothing a WeakMap can do for them --
75
+ * GPU memory is not garbage collected. A dataset that is cleared rather than replaced has no
76
+ * `next` to freeze and is announced by {@link GraphSnapshotDroppedEvent} instead.
75
77
  */
76
78
  export interface GraphSnapshotReplacedEvent {
77
79
  type: "snapshot-replaced";
@@ -84,6 +86,17 @@ export interface GraphSnapshotReplacedEvent {
84
86
  /** freezeWithReport's report, relative to the PREVIOUS freeze of the same builder. */
85
87
  report: FreezeReport;
86
88
  }
89
+ /**
90
+ * Emitted by DataManager when the dataset is cleared: the store and every snapshot it froze are
91
+ * discarded without a replacement, so no `snapshot-replaced` ever carries that boundary.
92
+ *
93
+ * Listeners drop their per-snapshot resources exactly as they do on a replacement -- `Graph`
94
+ * releases the accelerator's buffers for the snapshot it was showing. Emitted while the outgoing
95
+ * store is still usable, so a listener can still ask it for a derived view of what it is freeing.
96
+ */
97
+ export interface GraphSnapshotDroppedEvent {
98
+ type: "snapshot-dropped";
99
+ }
87
100
  export interface GraphLayoutInitializedEvent {
88
101
  type: "layout-initialized";
89
102
  layoutType: string;