@graphty/graphty-element 2.3.1 → 2.4.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 (69) 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-BD9XK30e.js} +5 -5
  5. package/dist/chunks/{DataSource-OeN3NeyD.js → DataSource-B8vf2uhW.js} +3 -3
  6. package/dist/chunks/{GraphSession-Bef1AYw9.js → GraphSession-dcwOjGJh.js} +2821 -2743
  7. package/dist/chunks/{GraphtyError-BwcnblTH.js → GraphtyError-B93WRH3e.js} +8 -6
  8. package/dist/chunks/{GraphtyLogger-5KEttFUo.js → GraphtyLogger-CqOVV13Y.js} +2 -2
  9. package/dist/chunks/{NodeStyle-DKj7HjMJ.js → NodeStyle-CtmA7dXi.js} +16 -14
  10. package/dist/chunks/{VoiceInputAdapter-Dr9Gcmds.js → VoiceInputAdapter-D0tHHi9G.js} +1 -1
  11. package/dist/chunks/{XRPivotCameraController-BbfgZWpS.js → XRPivotCameraController-DTfhvhHz.js} +2 -2
  12. package/dist/chunks/{algorithms-CpX56sUB.js → algorithms-BF0X6RPw.js} +780 -635
  13. package/dist/chunks/{capability-check-Blhb2aBB.js → capability-check-BJzlK4oL.js} +1 -1
  14. package/dist/chunks/{detect-Cqwshr9a.js → detect-vJxK7n0D.js} +2 -2
  15. package/dist/chunks/{format-detection-BXGO1lSn.js → format-detection-C80TLQ2e.js} +1 -1
  16. package/dist/chunks/{index-C0mIoumR.js → index-2xkq7wyD.js} +2623 -2241
  17. package/dist/chunks/{optionsFromZod-17lkrAJs.js → optionsFromZod-BuTOFgVM.js} +146 -139
  18. package/dist/chunks/{paletteRegistry-x7WOEKZY.js → paletteRegistry-A63C71Gn.js} +8 -6
  19. package/dist/chunks/{registry-CSba5QGJ.js → registry-jB46Gmeb.js} +1 -1
  20. package/dist/chunks/{scales-BRwl51k8.js → scales-B2d-7Bf0.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 +37836 -36835
  27. package/dist/graphty.js +11 -11
  28. package/dist/logging.js +2 -2
  29. package/dist/schema.d.ts +1 -1
  30. package/dist/schema.js +42 -40
  31. package/dist/session.js +6 -6
  32. package/dist/src/Graph.d.ts +79 -7
  33. package/dist/src/acceleration/AccelerationController.d.ts +14 -3
  34. package/dist/src/acceleration/types.d.ts +78 -0
  35. package/dist/src/algorithms/KCoreAlgorithm.d.ts +26 -0
  36. package/dist/src/algorithms/LinkPredictionAlgorithm.d.ts +41 -0
  37. package/dist/src/catalog/algorithms.d.ts +5 -5
  38. package/dist/src/catalog/index.d.ts +2 -2
  39. package/dist/src/catalog/layouts.d.ts +7 -6
  40. package/dist/src/catalog/types.d.ts +77 -6
  41. package/dist/src/config/EdgeStyle.d.ts +35 -0
  42. package/dist/src/config/index.d.ts +1 -1
  43. package/dist/src/data/GEXFDataSource.d.ts +23 -0
  44. package/dist/src/errors/codes.d.ts +14 -0
  45. package/dist/src/events.d.ts +30 -0
  46. package/dist/src/graphty-element.d.ts +66 -26
  47. package/dist/src/layout/GridLayoutEngine.d.ts +37 -0
  48. package/dist/src/layout/LayoutEngine.d.ts +7 -7
  49. package/dist/src/layout/NGraphLayoutEngine.d.ts +2 -0
  50. package/dist/src/layout/RadialLayoutEngine.d.ts +37 -0
  51. package/dist/src/layout/SimulationLayoutEngine.d.ts +12 -0
  52. package/dist/src/managers/DataManager.d.ts +69 -2
  53. package/dist/src/managers/EventManager.d.ts +10 -4
  54. package/dist/src/managers/GraphContext.d.ts +2 -1
  55. package/dist/src/managers/LayoutManager.d.ts +30 -3
  56. package/dist/src/meshes/MeshCache.d.ts +18 -0
  57. package/dist/src/meshes/NodeEffects.d.ts +16 -11
  58. package/dist/src/meshes/NodeMesh.d.ts +2 -2
  59. package/dist/src/meshes/RichTextParser.d.ts +26 -0
  60. package/dist/src/meshes/RichTextRenderer.d.ts +0 -1
  61. package/dist/src/session/cost/estimate.d.ts +1 -1
  62. package/dist/src/session/layout.d.ts +3 -3
  63. package/dist/src/session/runs/RunsApi.d.ts +1 -1
  64. package/dist/src/session/styles/StylesApi.d.ts +6 -0
  65. package/dist/src/session/styles/intern.d.ts +26 -5
  66. package/dist/src/session/styles/repaint.d.ts +2 -1
  67. package/dist/src/session/types.d.ts +6 -6
  68. package/dist/webgpu.js +2 -2
  69. package/package.json +6 -6
@@ -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 seventeen engines whose registered
5
+ * and never which library draws it. The element registers nineteen 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
@@ -14,10 +14,11 @@
14
14
  * descriptor a consumer reads carries the default engine and that engine's options; the rest of
15
15
  * the list is there for a consumer that wants to choose.
16
16
  *
17
- * Two names in the built-in layout list have no engine behind them yet, and two engines describe
18
- * an arrangement that list has no name for. Both are recorded here -- {@link UNSERVED_LAYOUT_IDS}
19
- * and the `spiral` and `planar` entries -- rather than left for a consumer to discover by asking
20
- * for a layout that never answers, or by never learning a capability exists.
17
+ * A name in the built-in layout list with no engine behind it would be recorded in
18
+ * {@link UNSERVED_LAYOUT_IDS} (none is, today), and two engines describe an arrangement that list
19
+ * has no name for, which the `spiral` and `planar` entries record -- rather than left for a
20
+ * consumer to discover by asking for a layout that never answers, or by never learning a
21
+ * capability exists.
21
22
  *
22
23
  * `sizeRating` is the largest graph the default engine is recommended for, read from its cost: a
23
24
  * placement that visits each node once rates "any", an iterative all-pairs force rates 2000.
@@ -78,7 +79,7 @@ export declare const LAYOUT_DESCRIPTORS: readonly LayoutDescriptor[];
78
79
  /**
79
80
  * The built-in layout names no registered engine draws yet. Listed rather than omitted, because
80
81
  * a name that is in the type and missing from the catalogue is otherwise discovered by asking
81
- * for it and getting an error.
82
+ * for it and getting an error. Empty today: every built-in name has an engine.
82
83
  */
83
84
  export declare const UNSERVED_LAYOUT_IDS: readonly UnservedLayout[];
84
85
  /**
@@ -53,10 +53,29 @@ export type Query = string;
53
53
  /**
54
54
  * The built-in algorithms. The list is also available at runtime so a consumer can enumerate
55
55
  * the built-in set without a catalogue instance.
56
+ *
57
+ * Two of these names are deprecated: `all-paths` and `clustering-coefficient` are reserved but
58
+ * not implemented, and starting either fails with `E_UNSUPPORTED`. See
59
+ * {@link DEPRECATED_ALGORITHMS}.
56
60
  */
57
61
  export declare const KNOWN_ALGORITHMS: readonly ["degree", "betweenness", "closeness", "pagerank", "eigenvector", "katz", "hits", "louvain", "leiden", "label-propagation", "components", "shortest-path", "all-pairs-distance", "all-paths", "max-flow", "min-cut", "k-core", "clustering-coefficient", "girvan-newman", "bfs", "dfs", "kruskal", "prim", "bipartite-matching", "link-prediction"];
58
- /** One of the built-in algorithms. */
62
+ /**
63
+ * One of the built-in algorithms. `all-paths` and `clustering-coefficient` are deprecated and do
64
+ * not run; see {@link DEPRECATED_ALGORITHMS}.
65
+ */
59
66
  export type KnownAlgorithm = (typeof KNOWN_ALGORITHMS)[number];
67
+ /**
68
+ * The built-in algorithm names the element reserves but does not run.
69
+ *
70
+ * Nothing implements these two yet. The names stay in {@link KNOWN_ALGORITHMS}, so no plugin can
71
+ * claim them and no code that names them stops compiling, but starting one fails with
72
+ * `E_UNSUPPORTED` rather than `E_UNKNOWN_ALGORITHM`. Each is removed at the next major release
73
+ * unless it is implemented first: `all-paths` is tracked by issue #329 and
74
+ * `clustering-coefficient` by issue #330.
75
+ */
76
+ export declare const DEPRECATED_ALGORITHMS: readonly ["all-paths", "clustering-coefficient"];
77
+ /** A built-in algorithm name the element reserves but does not run, and will remove. */
78
+ export type DeprecatedAlgorithm = (typeof DEPRECATED_ALGORITHMS)[number];
60
79
  /**
61
80
  * An algorithm key. The built-in names keep autocomplete alive; the string arm accepts a
62
81
  * plugin's name.
@@ -446,13 +465,23 @@ export interface ScaleDescriptor {
446
465
  domainKind: "numeric" | "categorical" | "boolean";
447
466
  options: readonly OptionDescriptor[];
448
467
  }
449
- /** One named style document, offered as a whole look. */
468
+ /**
469
+ * One named style document, offered as a whole look.
470
+ *
471
+ * Nothing produces one yet: it is returned only by the deprecated `CatalogApi.themes()`, and goes
472
+ * with it at the next major release unless that is implemented first (issue #331).
473
+ */
450
474
  export interface ThemeDescriptor {
451
475
  name: string;
452
476
  plainName: string;
453
477
  document: StyleDocument;
454
478
  }
455
- /** One function the expression grammar accepts. */
479
+ /**
480
+ * One function the expression grammar accepts.
481
+ *
482
+ * Nothing produces one yet: it is returned only by the deprecated `CatalogApi.functions()`, and
483
+ * goes with it at the next major release unless that is implemented first (issue #332).
484
+ */
456
485
  export interface FunctionDescriptor {
457
486
  name: string;
458
487
  /** The smallest and largest argument count accepted. */
@@ -524,7 +553,12 @@ export type Scope = "visible" | "graph" | "selection" | "largest-component" | {
524
553
  } | {
525
554
  nodes: readonly NodeId[];
526
555
  };
527
- /** The catalogue: everything the element can offer, as data. */
556
+ /**
557
+ * The catalogue: everything the element can offer, as data.
558
+ *
559
+ * `session.catalog` implements every method here except the six named in
560
+ * {@link DeprecatedCatalogMethod}, which nothing implements yet.
561
+ */
528
562
  export interface CatalogApi {
529
563
  algorithms(): readonly AlgorithmDescriptor[];
530
564
  layouts(): readonly LayoutDescriptor[];
@@ -533,24 +567,61 @@ export interface CatalogApi {
533
567
  cameras(): readonly CameraDescriptor[];
534
568
  logSinks(): readonly LogSinkDescriptor[];
535
569
  scales(): readonly ScaleDescriptor[];
570
+ /**
571
+ * @deprecated Not implemented. Removed at the next major release unless it is implemented
572
+ * first (issue #331).
573
+ */
536
574
  themes(): readonly ThemeDescriptor[];
575
+ /**
576
+ * @deprecated Not implemented. Removed at the next major release unless it is implemented
577
+ * first (issue #332).
578
+ */
537
579
  functions(): readonly FunctionDescriptor[];
580
+ /**
581
+ * @deprecated Not implemented. Removed at the next major release unless it is implemented
582
+ * first (issue #333).
583
+ */
538
584
  timeAttributes(): readonly AttributeDescriptor[];
539
585
  metrics(): readonly MetricAvailability[];
540
- /** The metrics that can run on this graph. A runtime query, not a static list. */
586
+ /**
587
+ * The metrics that can run on this graph. A runtime query, not a static list.
588
+ * @deprecated Not implemented; `metrics()` carries `available` and `reason` for the same
589
+ * question. Removed at the next major release unless it is implemented first (issue #334).
590
+ */
541
591
  applicable(): readonly MetricAvailability[];
592
+ /**
593
+ * @deprecated Not implemented. Removed at the next major release unless it is implemented
594
+ * first (issue #335).
595
+ */
542
596
  validate(query: Query, o?: {
543
597
  kind?: "selector" | "filter" | "formula";
544
598
  }): QueryValidation;
545
- /** The options for one algorithm or layout, with data-dependent bounds resolved. */
599
+ /**
600
+ * The options for one algorithm or layout, with data-dependent bounds resolved.
601
+ * @deprecated Not implemented; `algorithms()` and `layouts()` carry the static option
602
+ * descriptors. Removed at the next major release unless it is implemented first (issue #336).
603
+ */
546
604
  optionsFor(key: AlgorithmKey | LayoutId, scope?: Scope): Promise<readonly OptionDescriptor[]>;
547
605
  }
606
+ /**
607
+ * The {@link CatalogApi} methods nothing implements yet, which `session.catalog` leaves out.
608
+ *
609
+ * Implementing one means deleting its name here: `SessionCatalogApi` is derived from this list,
610
+ * so the two cannot drift apart.
611
+ */
612
+ export type DeprecatedCatalogMethod = "themes" | "functions" | "timeAttributes" | "applicable" | "validate" | "optionsFor";
548
613
  /**
549
614
  * Tell whether a value is one of the option types.
550
615
  * @param value - The value to test.
551
616
  * @returns True when the value is a member of OPTION_TYPES.
552
617
  */
553
618
  export declare function isOptionType(value: unknown): value is OptionType;
619
+ /**
620
+ * Tell whether an algorithm key names a built-in the element reserves but does not run.
621
+ * @param key - The algorithm key.
622
+ * @returns True when the key is a member of DEPRECATED_ALGORITHMS.
623
+ */
624
+ export declare function isDeprecatedAlgorithm(key: string): key is DeprecatedAlgorithm;
554
625
  /**
555
626
  * Tell whether a value is one of the cost classes.
556
627
  * @param value - The value to test.
@@ -1,4 +1,39 @@
1
1
  import { z } from "zod/v4";
2
+ /**
3
+ * Every arrow the edge renderer can draw at the head or tail of an edge, in schema order.
4
+ * Read `EdgeArrowTypes.options` for the list, e.g. to build a picker.
5
+ */
6
+ export declare const EdgeArrowTypes: z.ZodEnum<{
7
+ none: "none";
8
+ dot: "dot";
9
+ normal: "normal";
10
+ inverted: "inverted";
11
+ "sphere-dot": "sphere-dot";
12
+ "open-dot": "open-dot";
13
+ tee: "tee";
14
+ "open-normal": "open-normal";
15
+ diamond: "diamond";
16
+ "open-diamond": "open-diamond";
17
+ crow: "crow";
18
+ box: "box";
19
+ "half-open": "half-open";
20
+ vee: "vee";
21
+ }>;
22
+ /**
23
+ * Every line pattern the edge renderer can draw, in schema order.
24
+ * Read `EdgeLineTypes.options` for the list, e.g. to build a picker.
25
+ */
26
+ export declare const EdgeLineTypes: z.ZodEnum<{
27
+ solid: "solid";
28
+ dot: "dot";
29
+ diamond: "diamond";
30
+ box: "box";
31
+ star: "star";
32
+ dash: "dash";
33
+ "dash-dot": "dash-dot";
34
+ sinewave: "sinewave";
35
+ zigzag: "zigzag";
36
+ }>;
2
37
  /**
3
38
  * Everything a style layer can say about how one edge is drawn.
4
39
  *
@@ -1,7 +1,7 @@
1
1
  export type { AdHocData, ImageData } from "./common";
2
2
  export { colorToHex } from "./common";
3
3
  export type { EdgeStyleConfig } from "./EdgeStyle";
4
- export { defaultEdgeStyle, EdgeStyle } from "./EdgeStyle";
4
+ export { defaultEdgeStyle, EdgeArrowTypes, EdgeLineTypes, EdgeStyle } from "./EdgeStyle";
5
5
  export type { FetchEdgesFn, FetchNodesFn, GraphBehaviorConfig } from "./GraphBehavior";
6
6
  export type { NodeIdType } from "./GraphBehavior";
7
7
  export { GraphBehaviorOpts } from "./GraphBehavior";
@@ -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 {};
@@ -185,6 +185,20 @@ export type GraphtyErrorCode =
185
185
  * import plan or the data.
186
186
  */
187
187
  | "E_ID_MISSING"
188
+ /**
189
+ * A load read its source to the end and found nothing in it: no node records and no edge
190
+ * records. It is reported as a failure rather than as a success with zero counts, and a
191
+ * load asked to `replace` keeps the graph it would have replaced. `details` carry the
192
+ * format. The caller checks the file, or the format it was read as.
193
+ */
194
+ | "E_EMPTY_LOAD"
195
+ /**
196
+ * A load was overtaken: a REPLACING load was called after it, or `clearData` ran, so its data
197
+ * would have replaced or mixed into the newer dataset. It stops without touching the graph.
198
+ * `details` carry the format. Not a fault in the source; the caller ignores it, or loads
199
+ * again.
200
+ */
201
+ | "E_SUPERSEDED"
188
202
  /**
189
203
  * The graph exceeds a hard structural limit of an index or of the accelerator, and no scope
190
204
  * 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