@graphty/graphty-element 2.3.0 → 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.
- package/AGENTS.md +4 -3
- package/dist/ai.js +115 -222
- package/dist/catalog.js +46 -44
- package/dist/chunks/{AiManager-Bd_r1Hei.js → AiManager-BD9XK30e.js} +793 -654
- package/dist/chunks/{DataSource-bt0DhBjG.js → DataSource-B8vf2uhW.js} +3 -3
- package/dist/chunks/{GraphSession-iNyKm7Ds.js → GraphSession-dcwOjGJh.js} +3028 -2918
- package/dist/chunks/{GraphStyle-D0PXnZKu.js → GraphStyle-Cwr55SAE.js} +5 -2
- package/dist/chunks/{GraphtyError-BwcnblTH.js → GraphtyError-B93WRH3e.js} +8 -6
- package/dist/chunks/{GraphtyLogger-5KEttFUo.js → GraphtyLogger-CqOVV13Y.js} +2 -2
- package/dist/chunks/{NodeStyle-DKj7HjMJ.js → NodeStyle-CtmA7dXi.js} +16 -14
- package/dist/chunks/{VoiceInputAdapter-DszYl6Ha.js → VoiceInputAdapter-D0tHHi9G.js} +1 -1
- package/dist/chunks/{XRPivotCameraController-XtxbbZ-D.js → XRPivotCameraController-DTfhvhHz.js} +2 -2
- package/dist/chunks/algorithms-BF0X6RPw.js +3627 -0
- package/dist/chunks/{capability-check-BqIEXcun.js → capability-check-BJzlK4oL.js} +1 -1
- package/dist/chunks/{detect-DM29BEaB.js → detect-vJxK7n0D.js} +2 -2
- package/dist/chunks/{format-detection-BEdmtvsy.js → format-detection-C80TLQ2e.js} +1 -1
- package/dist/chunks/{index-CD0_RJv-.js → index-2xkq7wyD.js} +11482 -10971
- package/dist/chunks/optionsFromZod-BuTOFgVM.js +2572 -0
- package/dist/chunks/paletteRegistry-A63C71Gn.js +1155 -0
- package/dist/chunks/{registry-CSba5QGJ.js → registry-jB46Gmeb.js} +1 -1
- package/dist/chunks/scales-B2d-7Bf0.js +3220 -0
- package/dist/chunks/{types-B7bX5c0K.js → types-C_c53VgR.js} +31 -26
- package/dist/commands.d.ts +4 -0
- package/dist/custom-elements.json +1 -1
- package/dist/extend.js +45 -45
- package/dist/graphty-catalog.json +245 -12
- package/dist/graphty.bundle.js +40762 -39403
- package/dist/graphty.js +33 -33
- package/dist/logging.js +2 -2
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +42 -40
- package/dist/session.d.ts +1 -1
- package/dist/session.js +29 -30
- package/dist/src/Graph.d.ts +112 -10
- package/dist/src/acceleration/AccelerationController.d.ts +14 -3
- package/dist/src/acceleration/types.d.ts +78 -0
- package/dist/src/algorithms/KCoreAlgorithm.d.ts +26 -0
- package/dist/src/algorithms/LinkPredictionAlgorithm.d.ts +41 -0
- package/dist/src/camera/builtins.d.ts +14 -1
- package/dist/src/camera/types.d.ts +7 -0
- package/dist/src/cameras/CameraManager.d.ts +13 -0
- package/dist/src/cameras/OrbitCameraController.d.ts +9 -0
- package/dist/src/catalog/algorithms.d.ts +5 -5
- package/dist/src/catalog/index.d.ts +2 -2
- package/dist/src/catalog/layouts.d.ts +7 -6
- package/dist/src/catalog/types.d.ts +87 -6
- package/dist/src/config/EdgeStyle.d.ts +35 -0
- package/dist/src/config/GraphStyle.d.ts +5 -1
- package/dist/src/config/StyleTemplate.d.ts +2 -2
- package/dist/src/config/index.d.ts +1 -1
- package/dist/src/data/GEXFDataSource.d.ts +23 -0
- package/dist/src/errors/codes.d.ts +14 -0
- package/dist/src/events.d.ts +30 -0
- package/dist/src/graphty-element.d.ts +77 -32
- package/dist/src/layout/GridLayoutEngine.d.ts +37 -0
- package/dist/src/layout/LayoutEngine.d.ts +7 -7
- package/dist/src/layout/NGraphLayoutEngine.d.ts +2 -0
- package/dist/src/layout/RadialLayoutEngine.d.ts +37 -0
- package/dist/src/layout/SimulationLayoutEngine.d.ts +12 -0
- package/dist/src/managers/DataManager.d.ts +69 -2
- package/dist/src/managers/EventManager.d.ts +10 -4
- package/dist/src/managers/GraphContext.d.ts +2 -1
- package/dist/src/managers/LayoutManager.d.ts +30 -3
- package/dist/src/managers/StylePainter.d.ts +9 -0
- package/dist/src/managers/UpdateManager.d.ts +5 -0
- package/dist/src/meshes/MeshCache.d.ts +18 -0
- package/dist/src/meshes/NodeEffects.d.ts +16 -11
- package/dist/src/meshes/NodeMesh.d.ts +2 -2
- package/dist/src/meshes/RichTextParser.d.ts +26 -0
- package/dist/src/meshes/RichTextRenderer.d.ts +0 -1
- package/dist/src/session/cost/estimate.d.ts +1 -1
- package/dist/src/session/layout.d.ts +3 -3
- package/dist/src/session/results/index.d.ts +1 -1
- package/dist/src/session/results/statistics.d.ts +8 -1
- package/dist/src/session/results/types.d.ts +33 -0
- package/dist/src/session/runs/RunsApi.d.ts +1 -1
- package/dist/src/session/selection/targets.d.ts +4 -1
- package/dist/src/session/styles/StylesApi.d.ts +6 -0
- package/dist/src/session/styles/intern.d.ts +26 -5
- package/dist/src/session/styles/predicate.d.ts +26 -1
- package/dist/src/session/styles/repaint.d.ts +13 -1
- package/dist/src/session/styles/selector.d.ts +13 -1
- package/dist/src/session/styles/sources.d.ts +9 -0
- package/dist/src/session/types.d.ts +6 -6
- package/dist/webgpu.js +2 -2
- package/package.json +6 -6
- package/dist/chunks/Algorithm-RQ629NLb.js +0 -494
- package/dist/chunks/cameras-ii4vngYY.js +0 -435
- package/dist/chunks/paletteRegistry-DnWHQsAD.js +0 -3166
- package/dist/chunks/scales-DyuwlJKI.js +0 -6087
|
@@ -42,6 +42,13 @@ export declare class LayoutManager implements Manager {
|
|
|
42
42
|
private styles;
|
|
43
43
|
layoutEngine?: LayoutEngine;
|
|
44
44
|
private _running;
|
|
45
|
+
/**
|
|
46
|
+
* Set while a CONSUMER has paused the layout, through {@link LayoutManager.setPaused}. Nothing
|
|
47
|
+
* inside the element clears it: a load, a freeze, an accelerator attaching, a new layout or a
|
|
48
|
+
* drag may rebuild or place nodes, but their `running = true` is refused until the consumer
|
|
49
|
+
* resumes.
|
|
50
|
+
*/
|
|
51
|
+
private _paused;
|
|
45
52
|
/**
|
|
46
53
|
* Set when a layout was built over a graph with nothing in it, and the pre-steps it is
|
|
47
54
|
* configured with have therefore not been spent. See
|
|
@@ -68,8 +75,19 @@ export declare class LayoutManager implements Manager {
|
|
|
68
75
|
* again and the next frame moves nodes. Going true -> false only stops `step()` being
|
|
69
76
|
* called; batches already in flight land in the position array by themselves, nothing is
|
|
70
77
|
* disposed and nothing is released.
|
|
78
|
+
*
|
|
79
|
+
* While the consumer has paused the layout (see {@link LayoutManager.setPaused}) a `true` is
|
|
80
|
+
* ignored, so the element's own restarts cannot undo the pause.
|
|
71
81
|
*/
|
|
72
82
|
set running(value: boolean);
|
|
83
|
+
/**
|
|
84
|
+
* Pause or resume the layout on a consumer's behalf.
|
|
85
|
+
*
|
|
86
|
+
* A pause holds until the consumer resumes it: internal restarts are refused while it is set.
|
|
87
|
+
* Resuming runs the layout, and reheats a simulation that had settled.
|
|
88
|
+
* @param paused - True to pause, false to resume.
|
|
89
|
+
*/
|
|
90
|
+
setPaused(paused: boolean): void;
|
|
73
91
|
private graphContext;
|
|
74
92
|
/**
|
|
75
93
|
* The graph's acceleration controller, once a context has arrived. A manager built without a
|
|
@@ -134,7 +152,7 @@ export declare class LayoutManager implements Manager {
|
|
|
134
152
|
/**
|
|
135
153
|
* Internal method for setting layout - bypasses queue
|
|
136
154
|
* Used by operations that are already queued to prevent nested queueing
|
|
137
|
-
* @param
|
|
155
|
+
* @param layout - A registered engine name, or a catalogue layout id
|
|
138
156
|
* @param opts - Layout-specific options
|
|
139
157
|
*/
|
|
140
158
|
private _setLayoutInternal;
|
|
@@ -246,10 +264,18 @@ export declare class LayoutManager implements Manager {
|
|
|
246
264
|
*/
|
|
247
265
|
getNodePosition(node: Node): [number, number, number] | undefined;
|
|
248
266
|
/**
|
|
249
|
-
*
|
|
250
|
-
*
|
|
267
|
+
* Whether the layout engine has converged: the positions are final.
|
|
268
|
+
*
|
|
269
|
+
* A layout that was stopped part-way is NOT settled; it is {@link LayoutManager.isPaused}. A
|
|
270
|
+
* reader that only needs "positions are not moving right now" asks `!running || isSettled`.
|
|
271
|
+
* @returns True when the engine has converged, or when there is no engine.
|
|
251
272
|
*/
|
|
252
273
|
get isSettled(): boolean;
|
|
274
|
+
/**
|
|
275
|
+
* Whether the layout was stopped before it converged, so its positions are not final.
|
|
276
|
+
* @returns True when the layout is not running and has not settled.
|
|
277
|
+
*/
|
|
278
|
+
get isPaused(): boolean;
|
|
253
279
|
/**
|
|
254
280
|
* Get nodes from layout engine
|
|
255
281
|
* @returns Iterable of nodes managed by the layout engine
|
|
@@ -295,6 +321,7 @@ export declare class LayoutManager implements Manager {
|
|
|
295
321
|
layoutType: string | undefined;
|
|
296
322
|
isRunning: boolean;
|
|
297
323
|
isSettled: boolean;
|
|
324
|
+
isPaused: boolean;
|
|
298
325
|
nodeCount: number;
|
|
299
326
|
edgeCount: number;
|
|
300
327
|
};
|
|
@@ -114,6 +114,15 @@ export declare class StylePainter {
|
|
|
114
114
|
* @returns True when a pass has painted something the renderer has not applied.
|
|
115
115
|
*/
|
|
116
116
|
get hasPending(): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Whether a style pass is still on its way: asked for, and not yet announced.
|
|
119
|
+
*
|
|
120
|
+
* Different from {@link StylePainter.hasPending}, which is paint that has ARRIVED and not been
|
|
121
|
+
* drawn. This is paint that has not arrived yet, and what it will change -- a colour, a size,
|
|
122
|
+
* the box the camera frames -- is not known until it does.
|
|
123
|
+
* @returns True while the bound pass is painting or queued to paint.
|
|
124
|
+
*/
|
|
125
|
+
get isPainting(): boolean;
|
|
117
126
|
/**
|
|
118
127
|
* Take the nodes waiting to be drawn.
|
|
119
128
|
* @returns Their dense indices. The set is emptied.
|
|
@@ -419,6 +419,11 @@ export declare class UpdateManager implements Manager {
|
|
|
419
419
|
* @returns True when this frame will re-frame the camera, given a box to frame.
|
|
420
420
|
*/
|
|
421
421
|
private willZoomToFit;
|
|
422
|
+
/**
|
|
423
|
+
* Whether a style pass has been asked for and has not announced what it painted yet.
|
|
424
|
+
* @returns True while the session's style stack is painting.
|
|
425
|
+
*/
|
|
426
|
+
private styleIsPainting;
|
|
422
427
|
/**
|
|
423
428
|
* Frame the camera on a box {@link UpdateManager.willZoomToFit} has already approved.
|
|
424
429
|
* @param box - The box to frame, or undefined when there is nothing to frame.
|
|
@@ -26,6 +26,24 @@ export declare class MeshCache {
|
|
|
26
26
|
* Clear all cached meshes and reset statistics
|
|
27
27
|
*/
|
|
28
28
|
clear(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Dispose and forget every cached mesh that nothing is drawn from any more.
|
|
31
|
+
*
|
|
32
|
+
* Every source mesh is handed out only as instances, so one with no instances is a look no
|
|
33
|
+
* element has: a size a layer used to paint, a halo nobody is selected for. Without this the
|
|
34
|
+
* cache holds one mesh per look ever drawn, which grows with every edit to a size or a shape
|
|
35
|
+
* until the next dataset boundary. A name that is asked for again is simply built again.
|
|
36
|
+
*/
|
|
37
|
+
prune(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Dispose a source mesh and the material it was built with.
|
|
40
|
+
*
|
|
41
|
+
* Every creator handed to get() builds a fresh material for its mesh, so the material dies
|
|
42
|
+
* with it; `mesh.dispose()` alone would leave it in `scene.materials` for good. Textures are
|
|
43
|
+
* kept: node gradient textures are shared across materials per scene.
|
|
44
|
+
* @param mesh - The cached source mesh
|
|
45
|
+
*/
|
|
46
|
+
private static disposeSource;
|
|
29
47
|
/**
|
|
30
48
|
* Get the number of cached meshes
|
|
31
49
|
* @returns Count of cached meshes
|
|
@@ -83,13 +83,16 @@ export declare class NodeEffects {
|
|
|
83
83
|
* must not pay for it, so the only call site is the `effect.glow` branch of
|
|
84
84
|
* {@link NodeEffects.applyGlowEffect}; the removal branch deliberately does NOT create one.
|
|
85
85
|
*
|
|
86
|
+
* DISPOSED AGAIN WHEN NOTHING GLOWS, by {@link NodeEffects.syncGlowStrengths}. The inclusion
|
|
87
|
+
* list alone never says so: `node.glow` is a mesh channel, so a node that stops glowing moves
|
|
88
|
+
* to another source mesh and the old glowing source stays listed with no instances. The next
|
|
89
|
+
* glow recreates the layer through this method.
|
|
90
|
+
*
|
|
86
91
|
* `excludeByDefault: true` is a safety catch, not a tuning knob. Babylon's inclusion list
|
|
87
92
|
* means "only these" when it is non-empty and "no opinion" -- i.e. EVERY mesh in the scene --
|
|
88
|
-
* when it is empty (ThinGlowLayer.hasMesh).
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* failure to be worth one option: with this set, `_internalShouldRender` returns false while
|
|
92
|
-
* the list is empty, so an emptied layer renders nothing at all.
|
|
93
|
+
* when it is empty (ThinGlowLayer.hasMesh). With this set, `_internalShouldRender` returns
|
|
94
|
+
* false while the list is empty, so an emptied layer renders nothing rather than blooming
|
|
95
|
+
* the whole graph.
|
|
93
96
|
* @param scene - The Babylon.js scene
|
|
94
97
|
* @returns The glow layer for the scene
|
|
95
98
|
*/
|
|
@@ -142,6 +145,10 @@ export declare class NodeEffects {
|
|
|
142
145
|
* back to 0.1) leaves a mesh with no instances behind; counted, it would hold the layer at 100
|
|
143
146
|
* and round the live glow away in the 8-bit map. It keeps its entry, because a node that goes
|
|
144
147
|
* back to that strength reuses the cached mesh. A disposed mesh is dropped.
|
|
148
|
+
*
|
|
149
|
+
* When no glowing source mesh draws a node any more, the layer is disposed: it is a
|
|
150
|
+
* full-screen post-process that would otherwise render nothing every frame for the life of
|
|
151
|
+
* the scene. Every node mesh is an instance, so a source with no instances draws nothing.
|
|
145
152
|
* @param glowLayer - The scene's glow layer
|
|
146
153
|
* @param scene - The Babylon.js scene
|
|
147
154
|
*/
|
|
@@ -155,8 +162,8 @@ export declare class NodeEffects {
|
|
|
155
162
|
* with one outline configuration -- and resolving to it here would take the outline away from
|
|
156
163
|
* every sibling still on screen. That is the same reasoning `Node.dispose` records for glow,
|
|
157
164
|
* and it has the same consequence: for an instanced node this removes nothing, the source is
|
|
158
|
-
* freed when `MeshCache`
|
|
159
|
-
* Babylon's uniqueIds are monotonic per scene and never reused.
|
|
165
|
+
* freed when `MeshCache` prunes or clears it, and the layer's leftover uniqueId is inert
|
|
166
|
+
* because Babylon's uniqueIds are monotonic per scene and never reused.
|
|
160
167
|
* @param mesh - The mesh to remove from highlighting
|
|
161
168
|
*/
|
|
162
169
|
static removeFromHighlight(mesh: AbstractMesh): void;
|
|
@@ -178,10 +185,8 @@ export declare class NodeEffects {
|
|
|
178
185
|
* The colour map is keyed by mesh uniqueId, so it MUST die with the layer: leaving it behind
|
|
179
186
|
* would let a later mesh that happens to reuse a uniqueId inherit a dead style's glow colour.
|
|
180
187
|
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* than rebuilt. It exists so that whoever tears a scene down has one call for each layer this
|
|
184
|
-
* class can create, instead of discovering the glow layer only by leaking it.
|
|
188
|
+
* Called by {@link NodeEffects.syncGlowStrengths} once no node glows; the next glow
|
|
189
|
+
* recreates the layer lazily.
|
|
185
190
|
* @param scene - The Babylon.js scene
|
|
186
191
|
*/
|
|
187
192
|
static disposeGlowLayer(scene: Scene): void;
|
|
@@ -120,8 +120,8 @@ export declare class NodeMesh {
|
|
|
120
120
|
* provenance is invisible here, but unbounded allocation is not.
|
|
121
121
|
*
|
|
122
122
|
* The cache is a WeakMap keyed by scene, so the entries die with the scene and never leak
|
|
123
|
-
* across scenes or across tests. `MeshCache
|
|
124
|
-
*
|
|
123
|
+
* across scenes or across tests. `MeshCache` disposes a source mesh's material but never its
|
|
124
|
+
* textures, so a cached texture stays valid across a 2D/3D switch.
|
|
125
125
|
* @param gradient - The normalised gradient to paint
|
|
126
126
|
* @param scene - Babylon.js scene that will own the texture
|
|
127
127
|
* @returns The shared texture, or undefined if one cannot or should not be allocated
|
|
@@ -35,3 +35,29 @@ export declare class RichTextParser {
|
|
|
35
35
|
totalHeight: number;
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Measures one line of segments from the font's own metrics.
|
|
40
|
+
*
|
|
41
|
+
* The line's ink height is the tallest ascent plus the deepest descent over its segments, each
|
|
42
|
+
* the larger of the font box (`fontBoundingBoxAscent` / `fontBoundingBoxDescent`) and the actual
|
|
43
|
+
* glyph box, plus the outline on both sides. The line box is that height times `lineHeight`, and
|
|
44
|
+
* the extra leading is split evenly above and below, as CSS does. The label's panel height and
|
|
45
|
+
* the renderer's line advance both come from here, so they cannot disagree.
|
|
46
|
+
* @param ctx - Canvas rendering context for measurement
|
|
47
|
+
* @param lineSegments - The segments of one line
|
|
48
|
+
* @param options - Layout options
|
|
49
|
+
* @param options.lineHeight - Line height multiplier
|
|
50
|
+
* @param options.textOutline - Whether text outline is enabled
|
|
51
|
+
* @param options.textOutlineWidth - Width of text outline
|
|
52
|
+
* @returns The line's advance width, its line box height, and the distance from the top of the
|
|
53
|
+
* line box to the alphabetic baseline
|
|
54
|
+
*/
|
|
55
|
+
export declare function measureLine(ctx: CanvasRenderingContext2D, lineSegments: TextSegment[], options: {
|
|
56
|
+
lineHeight: number;
|
|
57
|
+
textOutline: boolean;
|
|
58
|
+
textOutlineWidth: number;
|
|
59
|
+
}): {
|
|
60
|
+
width: number;
|
|
61
|
+
lineBox: number;
|
|
62
|
+
baseline: number;
|
|
63
|
+
};
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* Nothing here reaches Babylon.js, Lit or the DOM: an estimate is arithmetic over plain data,
|
|
28
28
|
* published from the Node-safe `./session` entry point.
|
|
29
29
|
*/
|
|
30
|
-
import type
|
|
30
|
+
import { type AlgorithmDescriptor, type AlgorithmKey, type CostClass, type Scope } from "../../catalog/types";
|
|
31
31
|
import { GraphtyError } from "../../errors/GraphtyError";
|
|
32
32
|
import type { GraphStatistics } from "../types";
|
|
33
33
|
/**
|
|
@@ -29,8 +29,8 @@ export interface LayoutRecommendation {
|
|
|
29
29
|
* The arrangement, exactly as `catalog.layouts()` publishes it.
|
|
30
30
|
*
|
|
31
31
|
* `layout.id` is the public arrangement name -- `"force"`, `"circular"` -- and `layout.engine`
|
|
32
|
-
* is the registered engine
|
|
33
|
-
*
|
|
32
|
+
* is the registered engine that runs it by default. `setLayout` takes either, so a consumer
|
|
33
|
+
* acts on the id: `element.setLayout(recommendation.layout.id)`.
|
|
34
34
|
*/
|
|
35
35
|
readonly layout: LayoutDescriptor;
|
|
36
36
|
/** Why this arrangement suits this graph, in a sentence a consumer can show a reader. */
|
|
@@ -80,7 +80,7 @@ export interface LayoutRecommendationOptions {
|
|
|
80
80
|
* });
|
|
81
81
|
*
|
|
82
82
|
* if (advice !== undefined) {
|
|
83
|
-
* await element.setLayout(advice.layout.
|
|
83
|
+
* await element.setLayout(advice.layout.id);
|
|
84
84
|
* }
|
|
85
85
|
* ```
|
|
86
86
|
*/
|
|
@@ -13,4 +13,4 @@
|
|
|
13
13
|
export { defaultReading } from "./reading";
|
|
14
14
|
export { createResultsApi, type ResultsRunEntry } from "./ResultsApi";
|
|
15
15
|
export { createRunResult, type ResultElementValues } from "./RunResult";
|
|
16
|
-
export { checkShapeContract, type Histogram, type HistogramBin, type HistogramBinning, type HistogramOptions, type Normalization, type NumericColumnView, type RankingEntry, type ReadingOptions, RESULT_FIELD_NAMES, RESULT_PATH_RUN_PLACEHOLDER, RESULT_ROOT, RESULT_SHAPE_CONTRACTS, resultPath, type ResultsApi, type ResultSummary, type RunRef, type RunResult, type SummaryEntry, type SummaryGroup, } from "./types";
|
|
16
|
+
export { checkShapeContract, type Histogram, type HistogramBin, type HistogramBinning, type HistogramOptions, type Normalization, type NumericColumnView, type RankingEntry, type ReadingOptions, RESULT_FIELD_NAMES, RESULT_PATH_RUN_PLACEHOLDER, RESULT_ROOT, RESULT_SHAPE_CONTRACTS, resultPath, type ResultsApi, type ResultSummary, type RunRef, type RunResult, type SummaryEntry, type SummaryGroup, type TopRanking, } from "./types";
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* published from the Node-safe `./session` entry point.
|
|
26
26
|
*/
|
|
27
27
|
import type { NodeId } from "../../catalog/types";
|
|
28
|
-
import type { Histogram, HistogramOptions, Normalization, NumericColumnView, RankingEntry } from "./types";
|
|
28
|
+
import type { Histogram, HistogramOptions, Normalization, NumericColumnView, RankingEntry, TopRanking } from "./types";
|
|
29
29
|
/**
|
|
30
30
|
* How many bins a histogram is cut into when the caller does not say.
|
|
31
31
|
*
|
|
@@ -182,6 +182,13 @@ export interface RankableEntry {
|
|
|
182
182
|
* @returns The ranking, best first. Entries with no finite value are left out.
|
|
183
183
|
*/
|
|
184
184
|
export declare function rankEntries(entries: readonly RankableEntry[]): readonly RankingEntry[];
|
|
185
|
+
/**
|
|
186
|
+
* The top `n` of a ranking, cut only between tie groups. See {@link TopRanking} for the policy.
|
|
187
|
+
* @param ranking - The ranking, best first, with tied entries sharing a rank.
|
|
188
|
+
* @param n - The most entries the top may hold, a whole number.
|
|
189
|
+
* @returns The entries taken, and the group that did not fit when one did not.
|
|
190
|
+
*/
|
|
191
|
+
export declare function topOfRanking(ranking: readonly RankingEntry[], n: number): TopRanking;
|
|
185
192
|
/** How one histogram is cut, including the one thing the caller never has to say. */
|
|
186
193
|
interface HistogramRequest extends HistogramOptions {
|
|
187
194
|
/**
|
|
@@ -479,6 +479,30 @@ export interface RankingEntry {
|
|
|
479
479
|
/** The share of measured elements it ranks at or above, from 0 to 1. */
|
|
480
480
|
readonly percentile: number;
|
|
481
481
|
}
|
|
482
|
+
/**
|
|
483
|
+
* The top of a ranking, cut only between tie groups.
|
|
484
|
+
*
|
|
485
|
+
* THE TIE POLICY: a group of elements that share a value is taken whole or not at all, and it is
|
|
486
|
+
* taken only when the whole group fits inside the limit. With ranks that share a place (1, 2, 2,
|
|
487
|
+
* 4), a group of size `s` at rank `r` is in exactly when `r + s - 1 <= n`. So the top never holds
|
|
488
|
+
* more than `n` elements and never splits a tie by an arbitrary order -- and it can hold FEWER
|
|
489
|
+
* than `n`, or none at all on a graph whose top value is shared by more than `n` elements.
|
|
490
|
+
* {@link TopRanking.leftOut} and {@link TopRanking.reason} say when that happened.
|
|
491
|
+
*/
|
|
492
|
+
export interface TopRanking {
|
|
493
|
+
/** The elements taken, best first: whole tie groups only, never more than the limit. */
|
|
494
|
+
readonly entries: readonly RankingEntry[];
|
|
495
|
+
/**
|
|
496
|
+
* The tie group that stopped the top short: the first group that did not fit, with its
|
|
497
|
+
* value and its size. Null when nothing was left out on account of a tie.
|
|
498
|
+
*/
|
|
499
|
+
readonly leftOut: {
|
|
500
|
+
readonly value: number;
|
|
501
|
+
readonly count: number;
|
|
502
|
+
} | null;
|
|
503
|
+
/** Why fewer elements were taken than the limit allowed, in a sentence; null when none were left out. */
|
|
504
|
+
readonly reason: string | null;
|
|
505
|
+
}
|
|
482
506
|
/** One bar of a histogram. */
|
|
483
507
|
export interface HistogramBin {
|
|
484
508
|
/** The lowest value the bin holds, inclusive. */
|
|
@@ -646,6 +670,15 @@ export interface RunResult {
|
|
|
646
670
|
* @returns The entries, best first.
|
|
647
671
|
*/
|
|
648
672
|
ranking(field: string, limit?: number): readonly RankingEntry[];
|
|
673
|
+
/**
|
|
674
|
+
* The top `n` elements on one field, cut only between tie groups. See {@link TopRanking}
|
|
675
|
+
* for the tie policy. A `{ match: "top" }` style selector and a `{ top }` selection target
|
|
676
|
+
* both read this, so the two can never disagree about which elements are the top `n`.
|
|
677
|
+
* @param field - The field to rank on.
|
|
678
|
+
* @param n - The most elements the top may hold.
|
|
679
|
+
* @returns The elements taken, and the tie group left out when there was one.
|
|
680
|
+
*/
|
|
681
|
+
top(field: string, n: number): TopRanking;
|
|
649
682
|
/**
|
|
650
683
|
* The distribution of one numeric field.
|
|
651
684
|
* @param field - The field to bin.
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* structural view of `OperationQueueManager` narrow enough that the session never imports the
|
|
19
19
|
* renderer's manager to talk to it.
|
|
20
20
|
*/
|
|
21
|
-
import type
|
|
21
|
+
import { type AlgorithmDescriptor, type LayerId, type RunId, type Scope } from "../../catalog/types";
|
|
22
22
|
import type { AutoApplyPolicy } from "../styles/autoApply";
|
|
23
23
|
import { type RunExecutor, type RunQueueContext } from "./Run";
|
|
24
24
|
import { type Caveats, type EngineVersions, type ResolvedScope, type RunChange, type RunsApi } from "./types";
|
|
@@ -104,7 +104,10 @@ export type SelectionTarget = ElementIdTarget | NeighborhoodTarget
|
|
|
104
104
|
| {
|
|
105
105
|
readonly scope: Scope;
|
|
106
106
|
}
|
|
107
|
-
/**
|
|
107
|
+
/**
|
|
108
|
+
* The highest-ranked elements of a finished run. A tie group is taken whole and only when it
|
|
109
|
+
* fits inside `n`, so this can select fewer than `n` elements, or none. See `TopRanking` in the results types.
|
|
110
|
+
*/
|
|
108
111
|
| {
|
|
109
112
|
readonly top: {
|
|
110
113
|
readonly run: RunRef;
|
|
@@ -493,6 +493,12 @@ export interface StylesSources {
|
|
|
493
493
|
* @param change - What changed, and how much was painted.
|
|
494
494
|
*/
|
|
495
495
|
readonly onChange?: (change: StyleChange) => void;
|
|
496
|
+
/**
|
|
497
|
+
* Aborted when the session holding the stack is disposed. Every edit still pending is
|
|
498
|
+
* cancelled with it, so a caller awaiting one gets an `AbortError` rather than waiting for
|
|
499
|
+
* ever, and an edit issued afterwards is cancelled before it starts.
|
|
500
|
+
*/
|
|
501
|
+
readonly disposed?: AbortSignal;
|
|
496
502
|
}
|
|
497
503
|
/**
|
|
498
504
|
* What a highlight paints when its caller names no style.
|
|
@@ -26,9 +26,17 @@
|
|
|
26
26
|
* does today. {@link channelRole} is where that split is written down, and
|
|
27
27
|
* {@link meshChannelsFor} is the list a repaint pushes.
|
|
28
28
|
*
|
|
29
|
-
* A KEY IS OPAQUE AND SESSION-LOCAL. It
|
|
30
|
-
*
|
|
31
|
-
*
|
|
29
|
+
* A KEY IS OPAQUE AND SESSION-LOCAL. It names one style for the life of the session and is
|
|
30
|
+
* meaningless outside it. Nothing may persist one, compare two from different sessions, or read
|
|
31
|
+
* anything back out of the number.
|
|
32
|
+
*
|
|
33
|
+
* A KEY IS RELEASED WHEN NOTHING IS DRAWN FROM IT, AND NEVER HANDED OUT AGAIN. The repaint counts
|
|
34
|
+
* the elements drawn from each key ({@link StyleInterner.retain}, {@link StyleInterner.release}),
|
|
35
|
+
* and a style no element holds is forgotten, so what the interner keeps follows the looks on
|
|
36
|
+
* screen rather than every edit ever made. The number is not recycled: a renderer names a cached
|
|
37
|
+
* source mesh after it, and a recycled key would hand one look's mesh to another. The storage
|
|
38
|
+
* behind a key IS recycled, which is what keeps a session that edits a size a thousand times
|
|
39
|
+
* the size of the picture it draws.
|
|
32
40
|
*
|
|
33
41
|
* Nothing here reaches Babylon.js, Lit or the DOM.
|
|
34
42
|
*/
|
|
@@ -76,7 +84,7 @@ export declare function meshChannelsFor(target: "node" | "edge"): readonly Chann
|
|
|
76
84
|
* into the interner.
|
|
77
85
|
*/
|
|
78
86
|
export interface StyleInterner<T> {
|
|
79
|
-
/** How many distinct styles
|
|
87
|
+
/** How many distinct styles are held: minted and not yet released. */
|
|
80
88
|
readonly size: number;
|
|
81
89
|
/** Start a new sequence, discarding anything pushed and not ended. */
|
|
82
90
|
begin(): void;
|
|
@@ -105,9 +113,22 @@ export interface StyleInterner<T> {
|
|
|
105
113
|
/**
|
|
106
114
|
* Finish the sequence and answer with the key the style it describes is known by.
|
|
107
115
|
* @param mint - Builds the style object, called ONLY when the sequence is new.
|
|
108
|
-
* @returns The key
|
|
116
|
+
* @returns The key, which no other style is ever given in this interner.
|
|
109
117
|
*/
|
|
110
118
|
end(mint: () => T): number;
|
|
119
|
+
/**
|
|
120
|
+
* Say that one more element is drawn from a key.
|
|
121
|
+
* @param key - The key, as {@link end} answered with.
|
|
122
|
+
*/
|
|
123
|
+
retain(key: number): void;
|
|
124
|
+
/**
|
|
125
|
+
* Say that one element fewer is drawn from a key, and forget its style when none is left.
|
|
126
|
+
*
|
|
127
|
+
* A style that has been minted and never retained is held until something retains and then
|
|
128
|
+
* releases it: minting is a lookup, and a lookup must not take a style away.
|
|
129
|
+
* @param key - The key, as {@link end} answered with.
|
|
130
|
+
*/
|
|
131
|
+
release(key: number): void;
|
|
111
132
|
/**
|
|
112
133
|
* The style one key stands for.
|
|
113
134
|
* @param key - The key, as {@link end} answered with.
|
|
@@ -115,6 +115,19 @@ export interface SelectorSource {
|
|
|
115
115
|
* @returns The indices, or undefined when the column cannot be enumerated.
|
|
116
116
|
*/
|
|
117
117
|
readonly measured?: (path: Path, target: SelectorTarget) => ArrayLike<number> | undefined;
|
|
118
|
+
/**
|
|
119
|
+
* The lowest value in the top `n` of one run column, cut only between tie groups (see
|
|
120
|
+
* `RunResult.top`), or undefined when nothing is taken or the column is not a ranked run
|
|
121
|
+
* field for this kind of element. Absent, a `{match:"top"}` selector is refused.
|
|
122
|
+
*
|
|
123
|
+
* Asked once per element, so it must answer from something already computed: a session
|
|
124
|
+
* reads it off the run's result, which keeps the answer per field and `n`.
|
|
125
|
+
* @param path - The column path, `results.<run>.<field>`.
|
|
126
|
+
* @param target - Whether the asking layer paints nodes or edges.
|
|
127
|
+
* @param n - The most elements the top may hold.
|
|
128
|
+
* @returns The cut, or undefined.
|
|
129
|
+
*/
|
|
130
|
+
readonly topCut?: (path: Path, target: SelectorTarget, n: number) => number | undefined;
|
|
118
131
|
}
|
|
119
132
|
/**
|
|
120
133
|
* One target's half of a {@link SelectorSource}, resolved once so the predicate never chooses.
|
|
@@ -160,7 +173,7 @@ export type ElementPredicate = (index: number) => boolean;
|
|
|
160
173
|
/** A selector, reduced to the test a repaint runs and the columns that test reads. */
|
|
161
174
|
export interface CompiledSelector {
|
|
162
175
|
/** Which selector kind this was compiled from. */
|
|
163
|
-
readonly match: "everything" | "expression" | "has" | "ids";
|
|
176
|
+
readonly match: "everything" | "expression" | "has" | "ids" | "top";
|
|
164
177
|
/** Which kind of element it speaks about. */
|
|
165
178
|
readonly target: SelectorTarget;
|
|
166
179
|
/**
|
|
@@ -231,6 +244,18 @@ export declare function hasPredicate(columns: ElementColumns, path: Path): Eleme
|
|
|
231
244
|
* @returns The test.
|
|
232
245
|
*/
|
|
233
246
|
export declare function idsPredicate(columns: ElementColumns, ids: ReadonlySet<EdgeId | NodeId>): ElementPredicate;
|
|
247
|
+
/**
|
|
248
|
+
* The predicate for `{match:"top"}`: the element's value is at or above the top's cut.
|
|
249
|
+
*
|
|
250
|
+
* The cut is asked for per element rather than settled here, because a run that finishes or
|
|
251
|
+
* re-runs after the layer was added publishes a new ranking, and a cut captured now would go on
|
|
252
|
+
* painting the old top.
|
|
253
|
+
* @param columns - Where to read values.
|
|
254
|
+
* @param path - The column path.
|
|
255
|
+
* @param cutOf - The lowest value in the top, or undefined when nothing is in it.
|
|
256
|
+
* @returns The test.
|
|
257
|
+
*/
|
|
258
|
+
export declare function topPredicate(columns: ElementColumns, path: Path, cutOf: () => number | undefined): ElementPredicate;
|
|
234
259
|
/**
|
|
235
260
|
* Parse and compile `{match:"expression"}`.
|
|
236
261
|
*
|
|
@@ -168,7 +168,8 @@ export interface ElementPaint {
|
|
|
168
168
|
*
|
|
169
169
|
* This is the number a structural hash exists to keep small: it must follow the distinct
|
|
170
170
|
* SHAPES and SIZES in the picture, never the element count, and a colour encoding must not
|
|
171
|
-
* move it.
|
|
171
|
+
* move it. A mesh no element is drawn from any more is not counted: its key is released and
|
|
172
|
+
* never handed out again.
|
|
172
173
|
* @param target - Nodes or edges.
|
|
173
174
|
* @returns The count, which is at least one.
|
|
174
175
|
*/
|
|
@@ -211,6 +212,17 @@ export interface ElementPaint {
|
|
|
211
212
|
* @returns A function that stops the notifications.
|
|
212
213
|
*/
|
|
213
214
|
onPainted(listener: () => void): () => void;
|
|
215
|
+
/**
|
|
216
|
+
* Whether a pass has been asked for and has not finished yet.
|
|
217
|
+
*
|
|
218
|
+
* A pass YIELDS TO THE EVENT LOOP and waits behind the pass in front of it, so between the
|
|
219
|
+
* edit that asks for it and the announcement that ends it there are frames -- as many as the
|
|
220
|
+
* machine is slow. Nothing is in {@link ElementPaint.lastPainted} for those frames, and a
|
|
221
|
+
* renderer that asked only whether paint was waiting to be drawn would call the picture
|
|
222
|
+
* finished, and frame the camera on it, while a node's new size was still on its way.
|
|
223
|
+
* @returns True from the moment a pass is requested until it has announced what it painted.
|
|
224
|
+
*/
|
|
225
|
+
painting(): boolean;
|
|
214
226
|
/**
|
|
215
227
|
* The layers the last pass could not paint, and why.
|
|
216
228
|
* @returns The problems, emptied at the start of every pass.
|
|
@@ -68,6 +68,17 @@ export type Selector =
|
|
|
68
68
|
readonly match: "ids";
|
|
69
69
|
readonly nodes?: readonly NodeId[];
|
|
70
70
|
readonly edges?: readonly EdgeId[];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The top `n` elements by one run field, `results.<run>.<field>`, cut only between tie
|
|
74
|
+
* groups: a group of equal values is painted whole, and only when all of it fits inside `n`.
|
|
75
|
+
* So a layer never paints more than `n` elements, and paints none on a graph whose highest
|
|
76
|
+
* value is shared by more than `n`. `RunResult.top` is the same cut with its reason.
|
|
77
|
+
*/
|
|
78
|
+
| {
|
|
79
|
+
readonly match: "top";
|
|
80
|
+
readonly path: Path;
|
|
81
|
+
readonly n: number;
|
|
71
82
|
};
|
|
72
83
|
/**
|
|
73
84
|
* Turn a selector into the predicate a repaint runs.
|
|
@@ -81,6 +92,7 @@ export type Selector =
|
|
|
81
92
|
* @returns The compiled selector: its test, and the columns that test reads.
|
|
82
93
|
* @throws A `GraphtyError` with code `E_BAD_SELECTOR` when the selector's shape or its
|
|
83
94
|
* expression is wrong, `E_SELECTOR_EMPTY` when a selector is empty, and `E_UNSUPPORTED`
|
|
84
|
-
* when an `ids` selector is offered to a session that cannot say which id sits at which row
|
|
95
|
+
* when an `ids` selector is offered to a session that cannot say which id sits at which row,
|
|
96
|
+
* or a `top` selector to one that cannot rank a run's column.
|
|
85
97
|
*/
|
|
86
98
|
export declare function compileSelector(selector: Selector, target: SelectorTarget, source: SelectorSource): CompiledSelector;
|
|
@@ -131,6 +131,15 @@ export interface SessionSelectorSource extends SelectorSource {
|
|
|
131
131
|
* @returns The indices, ascending, or undefined when the column cannot be enumerated.
|
|
132
132
|
*/
|
|
133
133
|
readonly measured: (path: Path, target: SelectorTarget) => ArrayLike<number> | undefined;
|
|
134
|
+
/**
|
|
135
|
+
* The lowest value in the top `n` of a run's column, from `RunResult.top`, which keeps it.
|
|
136
|
+
* @param path - The column path, `results.<run>.<field>`.
|
|
137
|
+
* @param target - Whether the asking layer paints nodes or edges.
|
|
138
|
+
* @param n - The most elements the top may hold.
|
|
139
|
+
* @returns The cut, or undefined when nothing is taken or the path names no numeric field of
|
|
140
|
+
* this kind of element.
|
|
141
|
+
*/
|
|
142
|
+
readonly topCut: (path: Path, target: SelectorTarget, n: number) => number | undefined;
|
|
134
143
|
}
|
|
135
144
|
/**
|
|
136
145
|
* The id of the node at one end of an edge, for the attribute keys that name an endpoint.
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import type { DerivedGraph, GraphSnapshot, NodeId } from "@graphty/graph-format";
|
|
16
16
|
import type { z } from "zod/v4";
|
|
17
17
|
import type { AccelerationCapabilities, AccelerationPolicy, AccelerationStatus, GraphAccelerator } from "../acceleration";
|
|
18
|
-
import type { AlgorithmKey, AttributeDescriptor, CatalogApi, EdgeId, RunId, Scope } from "../catalog/types";
|
|
18
|
+
import type { AlgorithmKey, AttributeDescriptor, CatalogApi, DeprecatedCatalogMethod, EdgeId, RunId, Scope } from "../catalog/types";
|
|
19
19
|
import type { DataConfig } from "../config/DataConfig";
|
|
20
20
|
import type { ElementPositions } from "../data/positions";
|
|
21
21
|
import type { ImportReport } from "../data/report";
|
|
@@ -347,12 +347,12 @@ export interface SessionDataApi {
|
|
|
347
347
|
* been run. A consumer wanting only the metrics that CAN run filters on `available`; both lists
|
|
348
348
|
* come off one call rather than two that could disagree.
|
|
349
349
|
*
|
|
350
|
-
* The rest of
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
350
|
+
* The rest of {@link CatalogApi} -- the methods named in `DeprecatedCatalogMethod` -- is absent
|
|
351
|
+
* rather than stubbed, and deprecated on `CatalogApi` itself. A consumer discovers that gap by
|
|
352
|
+
* autocomplete finding nothing, not by a call that throws. This type is derived from that list,
|
|
353
|
+
* so implementing one of them means deleting its name there and nothing here.
|
|
354
354
|
*/
|
|
355
|
-
export type SessionCatalogApi =
|
|
355
|
+
export type SessionCatalogApi = Omit<CatalogApi, DeprecatedCatalogMethod>;
|
|
356
356
|
/** The configuration a session carries. */
|
|
357
357
|
export interface SessionConfig {
|
|
358
358
|
/** The data configuration: id paths, weight paths, position scale, direction, id coercion. */
|
package/dist/webgpu.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EXACT_MAX_NODES as n, createAccelerator as p, verifyDevice as u } from "@graphty/webgpu-graph-algorithms";
|
|
2
2
|
import { probeBrowserWebGpu as l, requestGpuContext as d } from "@graphty/webgpu-graph-algorithms/browser";
|
|
3
|
-
import { r as h } from "./chunks/registry-
|
|
4
|
-
import { G as s } from "./chunks/GraphtyError-
|
|
3
|
+
import { r as h } from "./chunks/registry-jB46Gmeb.js";
|
|
4
|
+
import { G as s } from "./chunks/GraphtyError-B93WRH3e.js";
|
|
5
5
|
const a = "webgpu-graph-algorithms", w = /* @__PURE__ */ new Set(["kind", "ctx", "options", "dispose", "verify"]);
|
|
6
6
|
function b(o, e) {
|
|
7
7
|
for (const [r, t] of Object.entries(o))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphty/graphty-element",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "A Web Component library for 3D/2D graph visualization built with Lit and Babylon.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"customElements": "./dist/custom-elements.json",
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
"vitepress": "^1.6.3",
|
|
135
135
|
"vitest": "^3.2.4",
|
|
136
136
|
"@graphty/remote-logger": "^1.3.7",
|
|
137
|
-
"@graphty/webgpu-graph-algorithms": "^0.6.
|
|
137
|
+
"@graphty/webgpu-graph-algorithms": "^0.6.6"
|
|
138
138
|
},
|
|
139
139
|
"peerDependencies": {
|
|
140
140
|
"@ai-sdk/anthropic": "^2.0.50",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"ai": "^5.0.104",
|
|
147
147
|
"encrypt-storage": "^2.14.7",
|
|
148
148
|
"lit": "^3.0.0",
|
|
149
|
-
"@graphty/webgpu-graph-algorithms": "^0.6.
|
|
149
|
+
"@graphty/webgpu-graph-algorithms": "^0.6.6"
|
|
150
150
|
},
|
|
151
151
|
"peerDependenciesMeta": {
|
|
152
152
|
"@ai-sdk/anthropic": {
|
|
@@ -184,9 +184,9 @@
|
|
|
184
184
|
"papaparse": "^5.5.3",
|
|
185
185
|
"toposort": "^2.0.2",
|
|
186
186
|
"zod": "^3.25.28",
|
|
187
|
-
"@graphty/
|
|
188
|
-
"@graphty/
|
|
189
|
-
"@graphty/
|
|
187
|
+
"@graphty/layout": "^1.10.0",
|
|
188
|
+
"@graphty/algorithms": "^2.0.4",
|
|
189
|
+
"@graphty/graph-format": "^1.0.5"
|
|
190
190
|
},
|
|
191
191
|
"overrides": {
|
|
192
192
|
"storybook": "$storybook"
|