@mettascript/grapher 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +135 -0
- package/dist/index.d.ts +815 -0
- package/dist/index.js +4014 -0
- package/dist/node.d.ts +37 -0
- package/dist/node.js +1779 -0
- package/package.json +73 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,815 @@
|
|
|
1
|
+
import { Atom, MeTTa } from '@mettascript/hyperon';
|
|
2
|
+
|
|
3
|
+
/** A node's role in the s-expression:
|
|
4
|
+
* - `symbol`: a named atom. With children it is `(name child...)`; without, a bare symbol/variable/value.
|
|
5
|
+
* - `list`: a headless expression `(child...)`.
|
|
6
|
+
* - `dot`: a build-time passthrough (a single child composes to that child). */
|
|
7
|
+
type NodeKind = "symbol" | "list" | "dot";
|
|
8
|
+
/** One node: its identity, its text, its role, and its position on the canvas. */
|
|
9
|
+
interface GraphNode {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
kind: NodeKind;
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
}
|
|
16
|
+
/** A cycle-guarded DAG of {@link GraphNode}s with parent/child edges. */
|
|
17
|
+
declare class Graph {
|
|
18
|
+
readonly nodes: Map<string, GraphNode>;
|
|
19
|
+
private readonly childIds;
|
|
20
|
+
private readonly parentIds;
|
|
21
|
+
/** Add a node. An explicit `id` is preserved (for loading); otherwise a fresh one is minted. Defaults:
|
|
22
|
+
* kind `symbol`, position `(0, 0)`. */
|
|
23
|
+
add(spec: {
|
|
24
|
+
name: string;
|
|
25
|
+
kind?: NodeKind;
|
|
26
|
+
x?: number;
|
|
27
|
+
y?: number;
|
|
28
|
+
id?: string;
|
|
29
|
+
}): GraphNode;
|
|
30
|
+
/** Remove a node and every edge touching it. */
|
|
31
|
+
remove(id: string): void;
|
|
32
|
+
/** Move a node to a new position. */
|
|
33
|
+
move(id: string, x: number, y: number): void;
|
|
34
|
+
/** This node's child ids, in insertion order. */
|
|
35
|
+
childrenOf(id: string): string[];
|
|
36
|
+
/** This node's parent ids, in insertion order. */
|
|
37
|
+
parentsOf(id: string): string[];
|
|
38
|
+
/** Whether `parent -> child` would be a legal edge: not a self-loop, a duplicate, an unknown node, or a
|
|
39
|
+
* cycle (the parent already sitting below the child). Lets the editor reject a drag before committing it. */
|
|
40
|
+
canConnect(parentId: string, childId: string): boolean;
|
|
41
|
+
/** Connect `parent` to `child`. Returns false and does nothing when the edge would be illegal (see
|
|
42
|
+
* {@link canConnect}). */
|
|
43
|
+
connect(parentId: string, childId: string): boolean;
|
|
44
|
+
/** Remove the `parent -> child` edge if present. */
|
|
45
|
+
disconnect(parentId: string, childId: string): void;
|
|
46
|
+
/** Children of `id` in screen order: by x, ties (within {@link X_EPSILON}) broken by y. This is how
|
|
47
|
+
* argument order is read off the canvas. */
|
|
48
|
+
sortedChildren(id: string): GraphNode[];
|
|
49
|
+
/** The roots (parentless nodes) reachable by walking up from `id`. A parentless node is its own head. */
|
|
50
|
+
findHeads(id: string): GraphNode[];
|
|
51
|
+
/** Every root in the graph (nodes with no parents). */
|
|
52
|
+
heads(): GraphNode[];
|
|
53
|
+
/** A deep copy: same node ids, positions, and edges. */
|
|
54
|
+
clone(): Graph;
|
|
55
|
+
/** Can `from` reach `to` by following child edges downward? */
|
|
56
|
+
private reaches;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** A pan offset and a scale. Screen = world * scale + pan. */
|
|
60
|
+
interface Viewport {
|
|
61
|
+
panX: number;
|
|
62
|
+
panY: number;
|
|
63
|
+
scale: number;
|
|
64
|
+
}
|
|
65
|
+
/** The identity viewport (no pan, unit scale). */
|
|
66
|
+
declare function initialViewport(): Viewport;
|
|
67
|
+
/** Screen point to world point. */
|
|
68
|
+
declare function toWorld(v: Viewport, sx: number, sy: number): {
|
|
69
|
+
x: number;
|
|
70
|
+
y: number;
|
|
71
|
+
};
|
|
72
|
+
/** World point to screen point. */
|
|
73
|
+
declare function toScreen(v: Viewport, wx: number, wy: number): {
|
|
74
|
+
x: number;
|
|
75
|
+
y: number;
|
|
76
|
+
};
|
|
77
|
+
/** Pan by a screen-space delta. */
|
|
78
|
+
declare function pan(v: Viewport, dx: number, dy: number): Viewport;
|
|
79
|
+
/** Scale by `factor` while keeping the world point under screen `(sx, sy)` fixed (zoom toward cursor). */
|
|
80
|
+
declare function zoomAt(v: Viewport, sx: number, sy: number, factor: number): Viewport;
|
|
81
|
+
|
|
82
|
+
/** A per-node evaluation label to show beneath it. */
|
|
83
|
+
interface NodeLabel {
|
|
84
|
+
text: string;
|
|
85
|
+
error: boolean;
|
|
86
|
+
}
|
|
87
|
+
/** A per-node overlay from a MeTTa `&grapher` directive: a fill color, a highlight ring, a label, and a size
|
|
88
|
+
* scale (1 = default). */
|
|
89
|
+
interface NodeViz {
|
|
90
|
+
color?: string;
|
|
91
|
+
highlight?: boolean;
|
|
92
|
+
label?: string;
|
|
93
|
+
sizeScale?: number;
|
|
94
|
+
}
|
|
95
|
+
/** Everything the renderer needs for one frame. */
|
|
96
|
+
interface RenderState {
|
|
97
|
+
graph: Graph;
|
|
98
|
+
viewport: Viewport;
|
|
99
|
+
selection: ReadonlySet<string>;
|
|
100
|
+
labels: ReadonlyMap<string, NodeLabel>;
|
|
101
|
+
primaryId: string | null;
|
|
102
|
+
viz: ReadonlyMap<string, NodeViz>;
|
|
103
|
+
}
|
|
104
|
+
/** Renders a graph into an <svg> and keeps a handle to the viewport group for pan and zoom. */
|
|
105
|
+
declare class Renderer {
|
|
106
|
+
readonly svg: SVGSVGElement;
|
|
107
|
+
private readonly viewportG;
|
|
108
|
+
private readonly haloG;
|
|
109
|
+
private readonly edgesG;
|
|
110
|
+
private readonly mergeG;
|
|
111
|
+
private readonly nodesG;
|
|
112
|
+
private tracePrev;
|
|
113
|
+
private traceRaf;
|
|
114
|
+
private traceDuration;
|
|
115
|
+
private bg;
|
|
116
|
+
constructor(container: HTMLElement);
|
|
117
|
+
/** Set the canvas background. The redex glow re-reads it, so its contrast stays right under any theme. */
|
|
118
|
+
setBackground(bg: string): void;
|
|
119
|
+
/** Set how long a step's morph takes (ms), so playback speed slows the animation, not just the pauses. */
|
|
120
|
+
setTraceDuration(ms: number): void;
|
|
121
|
+
/** Redraw the whole frame. */
|
|
122
|
+
render(state: RenderState): void;
|
|
123
|
+
/** Forget the last playthrough frame, so the next one starts without gliding from a stale step. */
|
|
124
|
+
clearTrace(): void;
|
|
125
|
+
/** Show one reduction step. With `animate` and a previous step, shared subterms arc from their old place
|
|
126
|
+
* to their new one, the parts that appear or vanish fade, and the viewport eases, the way a math
|
|
127
|
+
* animation morphs one expression into the next. Otherwise it paints at once. */
|
|
128
|
+
showTrace(state: RenderState, animate: boolean): void;
|
|
129
|
+
/** Paint an interpolated frame between two steps. The interpolation itself is pure ({@link
|
|
130
|
+
* interpolateTrace}); this just draws the result. */
|
|
131
|
+
private paintTrace;
|
|
132
|
+
/** Faint dashed links between the occurrences of each variable within a rule. */
|
|
133
|
+
private varNet;
|
|
134
|
+
private edges;
|
|
135
|
+
private nodeGroups;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** The state and operations the controller drives. The host (the editor) owns everything persistent. */
|
|
139
|
+
interface ControllerHost {
|
|
140
|
+
svg: SVGSVGElement;
|
|
141
|
+
container: HTMLElement;
|
|
142
|
+
graph: Graph;
|
|
143
|
+
viewport: Viewport;
|
|
144
|
+
selection: Set<string>;
|
|
145
|
+
primaryId: string | null;
|
|
146
|
+
/** Left-drag on empty canvas pans instead of rubber-band selecting. Host configuration, fixed for the
|
|
147
|
+
* host's lifetime, unlike {@link isTracing} which changes as a playthrough runs. */
|
|
148
|
+
readonly panOnLeftDrag: boolean;
|
|
149
|
+
render(): void;
|
|
150
|
+
changed(): void;
|
|
151
|
+
evaluate(nodeId: string): void;
|
|
152
|
+
completions(prefix: string): string[];
|
|
153
|
+
isTracing(): boolean;
|
|
154
|
+
}
|
|
155
|
+
/** Attaches to the host's svg on construction; call {@link destroy} to detach. */
|
|
156
|
+
declare class Controller {
|
|
157
|
+
private readonly host;
|
|
158
|
+
private mode;
|
|
159
|
+
private lastScreen;
|
|
160
|
+
private connectFrom;
|
|
161
|
+
private rubberStart;
|
|
162
|
+
private spaceHeld;
|
|
163
|
+
private clip;
|
|
164
|
+
private readonly overlay;
|
|
165
|
+
private input;
|
|
166
|
+
private menu;
|
|
167
|
+
private createAt;
|
|
168
|
+
private highlight;
|
|
169
|
+
private readonly onDown;
|
|
170
|
+
private readonly onMove;
|
|
171
|
+
private readonly onUp;
|
|
172
|
+
private readonly onWheel;
|
|
173
|
+
private readonly onDblClick;
|
|
174
|
+
private readonly onKeyDown;
|
|
175
|
+
private readonly onKeyUp;
|
|
176
|
+
private readonly onContext;
|
|
177
|
+
constructor(host: ControllerHost);
|
|
178
|
+
/** Detach every listener and remove transient UI. */
|
|
179
|
+
destroy(): void;
|
|
180
|
+
private screenOf;
|
|
181
|
+
private worldOf;
|
|
182
|
+
private nodeIdAt;
|
|
183
|
+
private pointerDown;
|
|
184
|
+
private pointerMove;
|
|
185
|
+
private pointerUp;
|
|
186
|
+
private wheel;
|
|
187
|
+
private dblClick;
|
|
188
|
+
private selectOnly;
|
|
189
|
+
private toggle;
|
|
190
|
+
private clearSelection;
|
|
191
|
+
private selectInRubber;
|
|
192
|
+
private drawRubber;
|
|
193
|
+
private drawConnectLine;
|
|
194
|
+
private toScreen;
|
|
195
|
+
private keyDown;
|
|
196
|
+
private keyUp;
|
|
197
|
+
private copy;
|
|
198
|
+
private paste;
|
|
199
|
+
private openInput;
|
|
200
|
+
private inputKey;
|
|
201
|
+
private commit;
|
|
202
|
+
private updateMenu;
|
|
203
|
+
private renderMenu;
|
|
204
|
+
private closeInput;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** A serialized graph: every node with its position, and every `[parent, child]` edge in order. */
|
|
208
|
+
interface GraphJson {
|
|
209
|
+
nodes: GraphNode[];
|
|
210
|
+
edges: [string, string][];
|
|
211
|
+
}
|
|
212
|
+
/** Snapshot a graph to JSON. */
|
|
213
|
+
declare function toJson(graph: Graph): GraphJson;
|
|
214
|
+
/** Rebuild a graph from JSON, preserving ids, positions, and edge order. */
|
|
215
|
+
declare function fromJson(json: GraphJson): Graph;
|
|
216
|
+
/** Render a graph as MeTTa source, one head per line. */
|
|
217
|
+
declare function toSource(graph: Graph): string;
|
|
218
|
+
/** Parse MeTTa source into a laid-out graph. */
|
|
219
|
+
declare function fromSource(src: string): Graph;
|
|
220
|
+
|
|
221
|
+
/** One self-contained SVG animation frame and its display time. */
|
|
222
|
+
interface SvgFrame {
|
|
223
|
+
svg: string;
|
|
224
|
+
delay: number;
|
|
225
|
+
}
|
|
226
|
+
/** SVG frames with one fixed output size and background. */
|
|
227
|
+
interface SvgAnimation {
|
|
228
|
+
frames: SvgFrame[];
|
|
229
|
+
width: number;
|
|
230
|
+
height: number;
|
|
231
|
+
background: string;
|
|
232
|
+
}
|
|
233
|
+
/** Convert one SVG frame to width * height * 4 RGBA bytes. */
|
|
234
|
+
type SvgRasterizer = (svg: string, width: number, height: number, background: string) => Promise<Uint8Array | Uint8ClampedArray>;
|
|
235
|
+
/** Encode SVG frames with a caller-supplied rasterizer and gifenc-compatible encoder. */
|
|
236
|
+
declare function encodeSvgAnimation(animation: SvgAnimation, rasterize: SvgRasterizer, lib: GifEncoderLib, maxColors?: number): Promise<Uint8Array>;
|
|
237
|
+
|
|
238
|
+
/** The colors of the block view. */
|
|
239
|
+
interface BlockPalette {
|
|
240
|
+
canvas: string;
|
|
241
|
+
bkgColor: string;
|
|
242
|
+
backgroundBlockColor: string;
|
|
243
|
+
outlineBlockColor: string;
|
|
244
|
+
formColor: string;
|
|
245
|
+
identifierColor: string;
|
|
246
|
+
literalColor: string;
|
|
247
|
+
stringColor: string;
|
|
248
|
+
operatorColor: string;
|
|
249
|
+
spacerefColor: string;
|
|
250
|
+
atColor: string;
|
|
251
|
+
holeFill: string;
|
|
252
|
+
holeSide: string;
|
|
253
|
+
holeText: string;
|
|
254
|
+
selectedColor: string;
|
|
255
|
+
selectedAtomColor: string;
|
|
256
|
+
}
|
|
257
|
+
/** Colors and sizes for one render, all in pixels. */
|
|
258
|
+
interface BlockSettings extends BlockPalette {
|
|
259
|
+
fontSize: number;
|
|
260
|
+
/** Advance width of one monospace character; measured by the renderer. */
|
|
261
|
+
unitWidth: number;
|
|
262
|
+
/** Row height; a glyph is centered within it. */
|
|
263
|
+
unitHeight: number;
|
|
264
|
+
/** Block corner radius. */
|
|
265
|
+
radius: number;
|
|
266
|
+
/** Atom and hole backing radius (smaller than the block radius). */
|
|
267
|
+
radiusAdj: number;
|
|
268
|
+
/** Below this many characters of children, a block stays on one line even if it is a stacking form. */
|
|
269
|
+
cutoff: number;
|
|
270
|
+
}
|
|
271
|
+
/** The site's own syntax palette (GitHub dark), so a block program matches the code blocks around it:
|
|
272
|
+
* variables and space-refs orange, numbers blue, strings light blue, control operators red, at-atoms
|
|
273
|
+
* purple, everything else the neutral light text. Nesting is shown by two dark surfaces and a lighter
|
|
274
|
+
* outline, on the same dark canvas as the node graph. */
|
|
275
|
+
declare const SITE_PALETTE: BlockPalette;
|
|
276
|
+
/** A plain teal scheme. */
|
|
277
|
+
declare const TEAL_PALETTE: BlockPalette;
|
|
278
|
+
/** The character-count cutoff below which a stacking form stays on one line. */
|
|
279
|
+
declare const CUTOFF = 14;
|
|
280
|
+
/** Build settings from a font size, the measured monospace advance, and a palette (the site's by
|
|
281
|
+
* default). */
|
|
282
|
+
declare function makeSettings(fontSize: number, unitWidth: number, palette?: BlockPalette): BlockSettings;
|
|
283
|
+
|
|
284
|
+
/** One vertex of a pulled-point polygon: the point, plus the incoming (l) and outgoing (r) Bezier pulls
|
|
285
|
+
* and angles (degrees). */
|
|
286
|
+
interface PulledPoint {
|
|
287
|
+
lpull: number;
|
|
288
|
+
langle: number;
|
|
289
|
+
x: number;
|
|
290
|
+
y: number;
|
|
291
|
+
rpull: number;
|
|
292
|
+
rangle: number;
|
|
293
|
+
}
|
|
294
|
+
/** A row of a backing profile: `x` is the edge (right edge for the right profile, left edge for the left)
|
|
295
|
+
* and `h` is the row height. */
|
|
296
|
+
interface ProfileRow {
|
|
297
|
+
x: number;
|
|
298
|
+
h: number;
|
|
299
|
+
}
|
|
300
|
+
/** Build an SVG path from a closed loop of pulled points: one cubic Bezier per edge, wrapping the last
|
|
301
|
+
* point back to the first. */
|
|
302
|
+
declare function pulledPointsToPath(points: readonly PulledPoint[]): string;
|
|
303
|
+
/** A rounded rectangle path. */
|
|
304
|
+
declare function roundedRectPath(width: number, height: number, r: number): string;
|
|
305
|
+
/** A rounded backing path from its right and left row profiles. */
|
|
306
|
+
declare function roundedBackingPath(rightProfile: readonly ProfileRow[], leftProfile: readonly ProfileRow[], r: number, headerException: boolean): string;
|
|
307
|
+
|
|
308
|
+
/** A leaf glyph. */
|
|
309
|
+
interface AtomBox {
|
|
310
|
+
kind: "atom";
|
|
311
|
+
path: number[];
|
|
312
|
+
x: number;
|
|
313
|
+
y: number;
|
|
314
|
+
w: number;
|
|
315
|
+
h: number;
|
|
316
|
+
depth: number;
|
|
317
|
+
text: string;
|
|
318
|
+
color: string;
|
|
319
|
+
}
|
|
320
|
+
/** A variable, drawn as a hole with its name inside. */
|
|
321
|
+
interface HoleBox {
|
|
322
|
+
kind: "hole";
|
|
323
|
+
path: number[];
|
|
324
|
+
x: number;
|
|
325
|
+
y: number;
|
|
326
|
+
w: number;
|
|
327
|
+
h: number;
|
|
328
|
+
depth: number;
|
|
329
|
+
text: string;
|
|
330
|
+
}
|
|
331
|
+
/** A block: a form drawn as a backing with its head glyph and child boxes inside. */
|
|
332
|
+
interface ExprBox {
|
|
333
|
+
kind: "expr";
|
|
334
|
+
path: number[];
|
|
335
|
+
x: number;
|
|
336
|
+
y: number;
|
|
337
|
+
w: number;
|
|
338
|
+
h: number;
|
|
339
|
+
depth: number;
|
|
340
|
+
orient: "h" | "v";
|
|
341
|
+
fill: string;
|
|
342
|
+
outline: string;
|
|
343
|
+
headerException: boolean;
|
|
344
|
+
children: BlockBox[];
|
|
345
|
+
rightProfile: ProfileRow[];
|
|
346
|
+
leftProfile: ProfileRow[];
|
|
347
|
+
}
|
|
348
|
+
type BlockBox = AtomBox | HoleBox | ExprBox;
|
|
349
|
+
/** Lay out one atom as a block tree rooted at the origin. */
|
|
350
|
+
declare function layoutAtom(atom: Atom, s: BlockSettings, path?: number[]): BlockBox;
|
|
351
|
+
/** Lay out a whole program: one block per head, stacked down the canvas with a gap between them. Each
|
|
352
|
+
* head keeps its index as its root path so a reduction can be spliced back into the right head. */
|
|
353
|
+
declare function placeProgram(atoms: readonly Atom[], s: BlockSettings): BlockBox[];
|
|
354
|
+
|
|
355
|
+
/** The slice of the `gifenc` module this needs. Pass `await import("gifenc")` (or `import * as`) here. */
|
|
356
|
+
interface GifEncoderLib {
|
|
357
|
+
GIFEncoder: () => {
|
|
358
|
+
writeFrame: (index: Uint8Array, width: number, height: number, opts: {
|
|
359
|
+
palette: number[][];
|
|
360
|
+
delay: number;
|
|
361
|
+
}) => void;
|
|
362
|
+
finish: () => void;
|
|
363
|
+
bytes: () => Uint8Array;
|
|
364
|
+
};
|
|
365
|
+
quantize: (rgba: Uint8Array | Uint8ClampedArray, maxColors: number) => number[][];
|
|
366
|
+
applyPalette: (rgba: Uint8Array | Uint8ClampedArray, palette: number[][]) => Uint8Array;
|
|
367
|
+
}
|
|
368
|
+
/** How to render the GIF. */
|
|
369
|
+
interface GifOptions {
|
|
370
|
+
/** Output width in pixels (height follows the aspect ratio). Default 720. */
|
|
371
|
+
width?: number;
|
|
372
|
+
/** Morph frames per reduction step. Default `morphMs / stepMs`, reduced to keep under `maxFrames`. */
|
|
373
|
+
framesPerStep?: number;
|
|
374
|
+
/** Cap on the total number of frames. Default 180. */
|
|
375
|
+
maxFrames?: number;
|
|
376
|
+
/** Milliseconds to hold each settled state. Default 260. */
|
|
377
|
+
holdMs?: number;
|
|
378
|
+
/** Milliseconds per morph frame. Default 40. */
|
|
379
|
+
stepMs?: number;
|
|
380
|
+
/** Milliseconds one step's morph spans, the live view's trace duration. Sets the default frame count
|
|
381
|
+
* per step so the export glides exactly like the screen; an explicit `framesPerStep` wins. The editor
|
|
382
|
+
* export methods fill this in with their current trace duration. Default 550 (`DEFAULT_TRACE_MS`). */
|
|
383
|
+
morphMs?: number;
|
|
384
|
+
/** Canvas background color. Used by the graph GIF, which has no block palette to take it from. */
|
|
385
|
+
background?: string;
|
|
386
|
+
}
|
|
387
|
+
/** Encode a sequence of reduction states into an animated GIF, morphing between them. Each state is a
|
|
388
|
+
* frontier (one or more terms), so a nondeterministic step shows every branch. */
|
|
389
|
+
declare function reductionGif(states: readonly Atom[][], s: BlockSettings, lib: GifEncoderLib, opts?: GifOptions): Promise<Blob>;
|
|
390
|
+
|
|
391
|
+
/** A per-node visual overlay set by MeTTa directives in the `&grapher` space. */
|
|
392
|
+
interface VizOverlay {
|
|
393
|
+
color?: string;
|
|
394
|
+
highlight?: boolean;
|
|
395
|
+
label?: string;
|
|
396
|
+
sizeScale?: number;
|
|
397
|
+
}
|
|
398
|
+
/** Options for {@link MeTTaGrapher}: bring your own engine (to share a space) and an initial program. */
|
|
399
|
+
interface GrapherOptions {
|
|
400
|
+
metta?: MeTTa;
|
|
401
|
+
source?: string;
|
|
402
|
+
/** Left-drag on empty canvas pans instead of rubber-band selecting. For a host that gives the canvas its
|
|
403
|
+
* own panel rather than embedding it in a scrolling article, where panning is the gesture a reader
|
|
404
|
+
* reaches for first. Shift-drag still rubber-bands, so box-select stays available. Off by default. */
|
|
405
|
+
panOnLeftDrag?: boolean;
|
|
406
|
+
}
|
|
407
|
+
/** A visual MeTTa editor mounted in a DOM element. */
|
|
408
|
+
declare class MeTTaGrapher implements ControllerHost {
|
|
409
|
+
readonly container: HTMLElement;
|
|
410
|
+
readonly metta: MeTTa;
|
|
411
|
+
/** Whether a left-drag on empty canvas pans (part of {@link ControllerHost}). */
|
|
412
|
+
readonly panOnLeftDrag: boolean;
|
|
413
|
+
graph: Graph;
|
|
414
|
+
viewport: Viewport;
|
|
415
|
+
readonly selection: Set<string>;
|
|
416
|
+
primaryId: string | null;
|
|
417
|
+
readonly labels: Map<string, NodeLabel>;
|
|
418
|
+
/** Per-node overlays (color, highlight, label) driven by MeTTa directives in the `&grapher` space. */
|
|
419
|
+
readonly viz: Map<string, VizOverlay>;
|
|
420
|
+
private readonly vizFocus;
|
|
421
|
+
private vizBound;
|
|
422
|
+
/** The `&grapher` directives from the last loaded source, kept so `toSource` can round-trip them under a
|
|
423
|
+
* comment even though they are not drawn as nodes. */
|
|
424
|
+
private vizDirectives;
|
|
425
|
+
private readonly renderer;
|
|
426
|
+
private readonly controller;
|
|
427
|
+
private readonly changeCbs;
|
|
428
|
+
private readonly sharedSpace;
|
|
429
|
+
private program;
|
|
430
|
+
private programDirty;
|
|
431
|
+
private trace;
|
|
432
|
+
private traceIndex;
|
|
433
|
+
private traceGraph;
|
|
434
|
+
/** Which view is showing: the node graph, or the nested-block ("block") view. */
|
|
435
|
+
viewMode: "graph" | "block";
|
|
436
|
+
private readonly block;
|
|
437
|
+
/** The rendered SVG element (part of {@link ControllerHost}). */
|
|
438
|
+
get svg(): SVGSVGElement;
|
|
439
|
+
constructor(container: HTMLElement, opts?: GrapherOptions);
|
|
440
|
+
/** The space to evaluate against. A provided engine is used as-is (a shared, persistent space);
|
|
441
|
+
* otherwise the whole canvas is loaded into a fresh space so its rules and facts are active, rebuilt
|
|
442
|
+
* lazily when the graph has changed. */
|
|
443
|
+
private evalSpace;
|
|
444
|
+
/** Redraw from the current state. During a playthrough the reduction graph is shown, without the
|
|
445
|
+
* editing selection or evaluation labels. */
|
|
446
|
+
render(): void;
|
|
447
|
+
/** The render state for a playthrough step: the reduction graph, without editing chrome. */
|
|
448
|
+
private traceState;
|
|
449
|
+
/** Notify onChange subscribers that the graph changed. */
|
|
450
|
+
changed(): void;
|
|
451
|
+
/** Completion candidates for the node-creation input, including the program's own defined symbols. */
|
|
452
|
+
completions(prefix: string): string[];
|
|
453
|
+
/** Evaluate every head the node belongs to and label each with its result. */
|
|
454
|
+
evaluate(nodeId: string): void;
|
|
455
|
+
/** Evaluate every head in the graph. */
|
|
456
|
+
evaluateAll(): void;
|
|
457
|
+
/** Read the `&grapher` space's directives and turn them into per-node overlays and a focus set. */
|
|
458
|
+
private applyViz;
|
|
459
|
+
private mergeViz;
|
|
460
|
+
/** Apply one `(shade-by FUNC)` / `(size-by FUNC)` mapper: value each node by evaluating `(FUNC node)`, then
|
|
461
|
+
* normalize the values across the graph and colour or size the nodes that produced a number. */
|
|
462
|
+
private applyMapper;
|
|
463
|
+
/** The nodes a directive target names: by node name, else by the atom the node composes to. Nodes that
|
|
464
|
+
* are part of a `&grapher` directive expression are skipped, so `(color (fact 5) red)` colors the query
|
|
465
|
+
* node and not the `(fact 5)` written inside the directive itself. */
|
|
466
|
+
private matchNodes;
|
|
467
|
+
/** Every node inside a head that operates on `&grapher` (`(add-atom &grapher …)` and friends): the
|
|
468
|
+
* directives' own plumbing, which should not be matched or colored. */
|
|
469
|
+
private directiveNodeIds;
|
|
470
|
+
/** Frame the focused nodes (graph view), if any directive asked to focus. */
|
|
471
|
+
private focusViz;
|
|
472
|
+
/** Evaluate one head and store its result label, unless the head is inert: a definition `(= ...)` or any
|
|
473
|
+
* atom that reduces to itself (a fact, a type declaration). Only genuine queries get a label. */
|
|
474
|
+
private labelHead;
|
|
475
|
+
/** Load a graph from JSON. */
|
|
476
|
+
load(json: GraphJson): void;
|
|
477
|
+
/** Load a graph by parsing MeTTa source. A top-level `(style ...)` block, and any explicit `(add-atom
|
|
478
|
+
* &grapher ...)`, are the stylesheet, not content: their directives are run into the isolated `&grapher`
|
|
479
|
+
* space, kept out of the drawn graph, and their overlays painted onto the content. */
|
|
480
|
+
loadSource(src: string): void;
|
|
481
|
+
/** Load a program from atoms (for example built with the eDSL), laid out as tidy trees. */
|
|
482
|
+
loadAtoms(atoms: readonly Atom[]): void;
|
|
483
|
+
/** Recolor the block view with a different palette. */
|
|
484
|
+
setBlockPalette(palette: BlockPalette): void;
|
|
485
|
+
/** Snapshot the graph to JSON. */
|
|
486
|
+
save(): GraphJson;
|
|
487
|
+
/** Render the graph as MeTTa source. */
|
|
488
|
+
toSource(): string;
|
|
489
|
+
/** Compose the graph's heads into atoms. */
|
|
490
|
+
atoms(): Atom[];
|
|
491
|
+
/** Re-run the tidy tree layout, frame the result, and redraw. */
|
|
492
|
+
tidy(): void;
|
|
493
|
+
/** Zoom around the canvas center by `factor` (above 1 zooms in, below 1 zooms out). Works in both views. */
|
|
494
|
+
zoomBy(factor: number): void;
|
|
495
|
+
/** Pan the view by a screen-space delta (for on-screen pan controls). Works in both views. */
|
|
496
|
+
panBy(dx: number, dy: number): void;
|
|
497
|
+
/** Frame the whole program: reset the block view's zoom/pan, or fit the graph. */
|
|
498
|
+
fitView(padding?: number): void;
|
|
499
|
+
/** The viewport that frames `graph` in the container, or null when it has no nodes. */
|
|
500
|
+
private fitViewportFor;
|
|
501
|
+
/** Start a step-by-step reduction playthrough of a head (the given node, or the current query target).
|
|
502
|
+
* While tracing, the canvas shows each reduction state; step with {@link traceForward} /
|
|
503
|
+
* {@link traceBack} and leave with {@link stopTrace}. */
|
|
504
|
+
playTrace(nodeId?: string): void;
|
|
505
|
+
/** The live morph span, mirrored here so the GIF exporters pace their frames off what the screen plays. */
|
|
506
|
+
private traceMs;
|
|
507
|
+
/** How long each step's morph takes (ms). Lower it to speed the animation up, raise it to slow it down so
|
|
508
|
+
* the reduction is easy to follow. The GIF exporters default to the same span. */
|
|
509
|
+
setTraceDuration(ms: number): void;
|
|
510
|
+
/** Advance the playthrough by one reduction. */
|
|
511
|
+
traceForward(): void;
|
|
512
|
+
/** Step the playthrough back one reduction. */
|
|
513
|
+
traceBack(): void;
|
|
514
|
+
/** Jump the playthrough back to the first state, to replay it from the start. */
|
|
515
|
+
traceRestart(): void;
|
|
516
|
+
/** Leave the playthrough and return to the editable graph (or interactive blocks). */
|
|
517
|
+
stopTrace(): void;
|
|
518
|
+
/** Whether a playthrough is active (part of {@link ControllerHost}, which pauses editing while true). */
|
|
519
|
+
isTracing(): boolean;
|
|
520
|
+
/** The current playthrough position (0-based step and total states), or null when not tracing. */
|
|
521
|
+
traceInfo(): {
|
|
522
|
+
index: number;
|
|
523
|
+
total: number;
|
|
524
|
+
} | null;
|
|
525
|
+
/** A snapshot of the whole view state for the host UI. The editor is the single source of truth: the
|
|
526
|
+
* host reads this (and subscribes with {@link onViewChange}) instead of tracking which view is showing
|
|
527
|
+
* or whether a playthrough is active on its own, so the two can never disagree. */
|
|
528
|
+
uiState(): {
|
|
529
|
+
viewMode: "graph" | "block";
|
|
530
|
+
tracing: {
|
|
531
|
+
index: number;
|
|
532
|
+
total: number;
|
|
533
|
+
} | null;
|
|
534
|
+
blockCanBack: boolean;
|
|
535
|
+
};
|
|
536
|
+
private showTraceStep;
|
|
537
|
+
/** Switch between the node-graph view and the nested-block view. */
|
|
538
|
+
setViewMode(mode: "graph" | "block"): void;
|
|
539
|
+
/** Reduce the block view's selected term one step in place. */
|
|
540
|
+
blockReduce(): boolean;
|
|
541
|
+
/** Step the block view back to before its last in-place reduction. */
|
|
542
|
+
blockBack(): boolean;
|
|
543
|
+
/** Whether the block view can step back. */
|
|
544
|
+
blockCanStepBack(): boolean;
|
|
545
|
+
/** The block view's program as source, reflecting its edits and reductions. */
|
|
546
|
+
blockSource(): string;
|
|
547
|
+
/** The reduction states to animate for a GIF: the active playthrough's if one is running, else those
|
|
548
|
+
* computed for the last query. Null when there is nothing (no target, or fewer than two states). */
|
|
549
|
+
private traceStates;
|
|
550
|
+
/** Encode the current query's reduction as an animated GIF of the block view, using a caller-supplied
|
|
551
|
+
* encoder (gifenc) so the package carries no GIF dependency. The morph pacing defaults to the live
|
|
552
|
+
* trace duration, so the GIF plays what the screen plays. Returns null when there is no reduction. */
|
|
553
|
+
exportReductionGif(lib: GifEncoderLib, opts?: GifOptions): Promise<Blob | null>;
|
|
554
|
+
/** Encode the current reduction as a GIF of the node-graph view alone (companion to the block GIF; stack
|
|
555
|
+
* the two to show both). Paced like the live view. Returns null when there is nothing to animate. */
|
|
556
|
+
exportGraphReductionGif(lib: GifEncoderLib, opts?: GifOptions): Promise<Blob | null>;
|
|
557
|
+
/** Export the current reduction as one GIF that plays it in the graph and the block views side by side.
|
|
558
|
+
* Paced like the live view. Returns null when there is nothing to animate. */
|
|
559
|
+
exportSideBySideGif(lib: GifEncoderLib, opts?: GifOptions): Promise<Blob | null>;
|
|
560
|
+
private readonly blockCbs;
|
|
561
|
+
/** Subscribe to block-view changes (an edit or reduction); returns an unsubscribe function. */
|
|
562
|
+
onBlockChange(cb: () => void): () => void;
|
|
563
|
+
private notifyBlock;
|
|
564
|
+
private readonly viewCbs;
|
|
565
|
+
/** Subscribe to view-state changes: a view switch or any playthrough transition. The host reads
|
|
566
|
+
* {@link uiState} in the callback. Returns an unsubscribe function. */
|
|
567
|
+
onViewChange(cb: () => void): () => void;
|
|
568
|
+
private notifyView;
|
|
569
|
+
/** The head to trace: the selected node's head, else the last query head (not a `=`/`:` definition). */
|
|
570
|
+
private traceTarget;
|
|
571
|
+
/** Subscribe to graph changes; returns an unsubscribe function. */
|
|
572
|
+
onChange(cb: (graph: Graph) => void): () => void;
|
|
573
|
+
/** Detach listeners and remove the SVG. */
|
|
574
|
+
destroy(): void;
|
|
575
|
+
private afterLoad;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/** The space the editor watches for directives. */
|
|
579
|
+
declare const VIZ_SPACE = "&grapher";
|
|
580
|
+
/** A parsed directive read from the grapher space. */
|
|
581
|
+
interface VizDirective {
|
|
582
|
+
kind: "color" | "highlight" | "focus" | "label" | "size" | "shade";
|
|
583
|
+
/** The term (or symbol) the directive points at. */
|
|
584
|
+
target: Atom;
|
|
585
|
+
/** A color for `color`, or the text for `label`. */
|
|
586
|
+
arg?: Atom;
|
|
587
|
+
/** The number for `size` (a relative scale) and `shade` (a value mapped to a heat color). */
|
|
588
|
+
value?: number;
|
|
589
|
+
}
|
|
590
|
+
/** A data-driven style rule from `(shade-by FUNC)` or `(size-by FUNC)`: colour or size every node by
|
|
591
|
+
* evaluating `(FUNC node)` and normalizing the results across the graph, the way a Cytoscape stylesheet maps
|
|
592
|
+
* a data field to a visual property. */
|
|
593
|
+
interface VizMapper {
|
|
594
|
+
property: "shade" | "size";
|
|
595
|
+
/** The function applied to each node, e.g. `energy` in `(shade-by energy)`. */
|
|
596
|
+
func: Atom;
|
|
597
|
+
}
|
|
598
|
+
/** Everything the editor reads from `&grapher`: the per-node directives, the data-driven mappers, and the
|
|
599
|
+
* global settings that target nothing (the canvas background). */
|
|
600
|
+
interface VizResult {
|
|
601
|
+
directives: VizDirective[];
|
|
602
|
+
/** Data-driven mappers from `(shade-by FUNC)` / `(size-by FUNC)`, applied to every node. */
|
|
603
|
+
mappers: VizMapper[];
|
|
604
|
+
/** The canvas background from `(background COLOR)`, or null to keep the default. */
|
|
605
|
+
background: string | null;
|
|
606
|
+
}
|
|
607
|
+
/** Bind the isolated `&grapher` space in `space` (as a fresh, empty space). Call once per space: binding
|
|
608
|
+
* it again would replace it with a new empty one, dropping any directives already added. */
|
|
609
|
+
declare function bindVizSpace(space: MeTTa): void;
|
|
610
|
+
/** Read what is currently in `&grapher`, each atom verbatim (unevaluated): the per-node directives and the
|
|
611
|
+
* global background. Empty when the space is unbound or empty. */
|
|
612
|
+
declare function readViz(space: MeTTa): VizResult;
|
|
613
|
+
/** A CSS color from a name (`red`, `blue`, …) or a hex string; falls back to yellow. */
|
|
614
|
+
declare function colorOf(atom: Atom): string;
|
|
615
|
+
/** The text of a label atom: a string without its quotes, or the atom's rendering. */
|
|
616
|
+
declare function textOf(atom: Atom): string;
|
|
617
|
+
|
|
618
|
+
/** A built-in palette name, or a custom palette. */
|
|
619
|
+
type PaletteChoice = "site" | "teal" | BlockPalette;
|
|
620
|
+
/** A fluent handle over a mounted {@link MeTTaGrapher}. Building steps return the handle; `source`, `gif`,
|
|
621
|
+
* and `destroy` end the chain. The full instance is on `.grapher`. */
|
|
622
|
+
interface Grapher {
|
|
623
|
+
readonly grapher: MeTTaGrapher;
|
|
624
|
+
/** Replace the program from MeTTa source. */
|
|
625
|
+
load(source: string): Grapher;
|
|
626
|
+
/** Replace the program from atoms (for example built with the eDSL). */
|
|
627
|
+
atoms(atoms: readonly Atom[]): Grapher;
|
|
628
|
+
/** Show the node graph. */
|
|
629
|
+
graph(): Grapher;
|
|
630
|
+
/** Show the nested blocks. */
|
|
631
|
+
blocks(): Grapher;
|
|
632
|
+
/** Recolor the blocks (a built-in name or a custom palette). */
|
|
633
|
+
palette(palette: PaletteChoice): Grapher;
|
|
634
|
+
/** Lay the program out and frame it. */
|
|
635
|
+
fit(): Grapher;
|
|
636
|
+
/** Evaluate every query and label the result. */
|
|
637
|
+
evaluate(): Grapher;
|
|
638
|
+
/** Initialize the last query's reduction trace at its first state. */
|
|
639
|
+
play(): Grapher;
|
|
640
|
+
/** The current program as source, reflecting edits and reductions. */
|
|
641
|
+
source(): string;
|
|
642
|
+
/** Encode the reduction as an animated GIF, using a caller-supplied encoder (gifenc). */
|
|
643
|
+
gif(encoder: GifEncoderLib, opts?: GifOptions): Promise<Blob | null>;
|
|
644
|
+
/** Detach listeners and remove the editor. */
|
|
645
|
+
destroy(): void;
|
|
646
|
+
}
|
|
647
|
+
/** Mount the visualizer on an element (or a CSS selector) and return a fluent handle. */
|
|
648
|
+
declare function grapher(target: string | HTMLElement, opts?: GrapherOptions): Grapher;
|
|
649
|
+
|
|
650
|
+
/** Compose the atom rooted at one node, or null if the node is unknown or contributes nothing. */
|
|
651
|
+
declare function composeAtom(graph: Graph, nodeId: string): Atom | null;
|
|
652
|
+
/** Compose one atom per head (a parentless node), children in screen order. Dot nodes that contribute
|
|
653
|
+
* nothing are dropped. */
|
|
654
|
+
declare function graphToAtoms(graph: Graph): Atom[];
|
|
655
|
+
/** Build nodes and edges from atoms, then lay them out as tidy trees. Adds to `graph` if given. */
|
|
656
|
+
declare function atomToGraph(atoms: Atom[], graph?: Graph): Graph;
|
|
657
|
+
|
|
658
|
+
/** Parse MeTTa source into its top-level atoms. */
|
|
659
|
+
declare function parseProgram(src: string): Atom[];
|
|
660
|
+
/** Parse a single-token source string into one atom, or `undefined` if it is not exactly one atom. */
|
|
661
|
+
declare function parseLeaf(token: string): Atom | undefined;
|
|
662
|
+
|
|
663
|
+
/** Assign `x` and `y` to every node so the graph reads as tidy top-down trees. Mutates the graph. */
|
|
664
|
+
declare function layout(graph: Graph, opts?: {
|
|
665
|
+
originX?: number;
|
|
666
|
+
originY?: number;
|
|
667
|
+
scaleOf?: (node: GraphNode) => number;
|
|
668
|
+
}): void;
|
|
669
|
+
|
|
670
|
+
/** Load the whole graph into a space so its own rules and facts are active when a head is evaluated. Adds
|
|
671
|
+
* every head atom to `metta`'s space and returns it; a fresh engine is created when none is given. This is
|
|
672
|
+
* what makes evaluating a query like `(fact 5)` reduce through a `(= (fact $n) ...)` rule drawn on the
|
|
673
|
+
* same canvas. */
|
|
674
|
+
declare function loadProgram(graph: Graph, metta?: MeTTa): MeTTa;
|
|
675
|
+
/** The outcome of evaluating a head: the result atoms, a short label for display, and whether any result
|
|
676
|
+
* is an error (or evaluation threw). */
|
|
677
|
+
interface EvalResult {
|
|
678
|
+
atoms: Atom[];
|
|
679
|
+
label: string;
|
|
680
|
+
error: boolean;
|
|
681
|
+
}
|
|
682
|
+
/** Evaluate the head at `headId`, catching a thrown error as a failed result. */
|
|
683
|
+
declare function evaluateHead(graph: Graph, headId: string, metta: MeTTa): EvalResult;
|
|
684
|
+
/** Like {@link evaluateHead}, awaiting async grounded operations reached during evaluation. */
|
|
685
|
+
declare function evaluateHeadAsync(graph: Graph, headId: string, metta: MeTTa): Promise<EvalResult>;
|
|
686
|
+
|
|
687
|
+
type LazyCache = Map<string, Set<number>>;
|
|
688
|
+
/** One reduction step of the whole expression: reduce the leftmost eager argument that can reduce (fanning
|
|
689
|
+
* out if that argument is nondeterministic), else reduce the whole atom. Returns every successor, or null
|
|
690
|
+
* at a normal form. */
|
|
691
|
+
declare function reduceStep(atom: Atom, metta: MeTTa, cache?: LazyCache): Atom[] | null;
|
|
692
|
+
/** The full sequence of frontiers from `atom` to its normal form(s). The first frontier is `[atom]`; each
|
|
693
|
+
* next frontier reduces every still-reducing term one step, so nondeterministic branches all advance
|
|
694
|
+
* together and every result is shown. Capped at `maxSteps` deep and {@link MAX_WIDTH} wide. */
|
|
695
|
+
declare function reduceTrace(atom: Atom, metta: MeTTa, maxSteps?: number): Atom[][];
|
|
696
|
+
|
|
697
|
+
/** Pairs of node ids to connect: for each variable name within a head, a chain through its occurrences in
|
|
698
|
+
* screen order. Names appearing once are omitted. */
|
|
699
|
+
declare function variableLinks(graph: Graph): Array<[string, string]>;
|
|
700
|
+
|
|
701
|
+
/** Ranked completion candidates for `prefix`, drawn from the space and the stdlib. Empty prefix yields
|
|
702
|
+
* nothing. Ties break toward shorter, then alphabetical, names. */
|
|
703
|
+
declare function completionsFor(prefix: string, metta: MeTTa, limit?: number): string[];
|
|
704
|
+
|
|
705
|
+
/** A token category, matching the highlighter's classes, plus `control` for the branching forms so the
|
|
706
|
+
* graph can shape and color them like a flowchart decision, and `boolean` for the constants True/False. */
|
|
707
|
+
type NodeRole = "variable" | "number" | "string" | "boolean" | "operator" | "control" | "spaceref" | "at" | "paren" | "symbol";
|
|
708
|
+
/** The fill and text color of a node. */
|
|
709
|
+
interface NodeColor {
|
|
710
|
+
fill: string;
|
|
711
|
+
text: string;
|
|
712
|
+
}
|
|
713
|
+
/** Classify a symbol name into a highlighter token category. */
|
|
714
|
+
declare function roleOf(name: string): NodeRole;
|
|
715
|
+
/** The color of a node. List nodes are the paren green; dot nodes a neutral; symbol nodes are colored by
|
|
716
|
+
* {@link roleOf}. */
|
|
717
|
+
declare function colorFor(node: GraphNode): NodeColor;
|
|
718
|
+
|
|
719
|
+
/** Node box height in world units. */
|
|
720
|
+
declare const NODE_H = 22;
|
|
721
|
+
/** The text drawn inside a node: `( )` for a list, a dot for a passthrough, otherwise the name rendered as
|
|
722
|
+
* its math glyph (`*` as ×, `->` as →, …). */
|
|
723
|
+
declare function displayText(node: GraphNode): string;
|
|
724
|
+
/** A node's box width, from its display text. */
|
|
725
|
+
declare function nodeWidth(node: GraphNode): number;
|
|
726
|
+
|
|
727
|
+
/** A block view mounted in a container, sharing the engine with the rest of the editor. */
|
|
728
|
+
declare class BlockView {
|
|
729
|
+
private readonly renderer;
|
|
730
|
+
private readonly getSpace;
|
|
731
|
+
private palette;
|
|
732
|
+
private settings;
|
|
733
|
+
private atoms;
|
|
734
|
+
private boxes;
|
|
735
|
+
private selectedPath;
|
|
736
|
+
private editing;
|
|
737
|
+
private readonlyMode;
|
|
738
|
+
private readonly history;
|
|
739
|
+
private readonly onChange;
|
|
740
|
+
constructor(container: HTMLElement, getSpace: () => MeTTa, onChange?: () => void);
|
|
741
|
+
private ensureSettings;
|
|
742
|
+
/** Recolor the view with a different palette. */
|
|
743
|
+
setPalette(palette: BlockPalette): void;
|
|
744
|
+
/** Load a program to edit and reduce interactively. */
|
|
745
|
+
setAtoms(atoms: readonly Atom[]): void;
|
|
746
|
+
/** Zoom the view in (factor > 1) or out (factor < 1). */
|
|
747
|
+
zoomBy(factor: number): void;
|
|
748
|
+
/** Pan the view by a screen-space delta. */
|
|
749
|
+
panBy(dx: number, dy: number): void;
|
|
750
|
+
/** Reset zoom/pan so the whole program is framed again. */
|
|
751
|
+
fitView(): void;
|
|
752
|
+
/** Frame the given atoms without interaction (used for a step-through playthrough). */
|
|
753
|
+
showReadonly(atoms: readonly Atom[]): void;
|
|
754
|
+
render(animate?: boolean): void;
|
|
755
|
+
/** The current program as source, reflecting any edits and reductions. */
|
|
756
|
+
sourceText(): string;
|
|
757
|
+
/** Encode a sequence of reduction states as an animated GIF, using a caller-supplied encoder (gifenc),
|
|
758
|
+
* so the package needs no GIF dependency of its own. */
|
|
759
|
+
exportGif(states: readonly Atom[][], lib: GifEncoderLib, opts?: GifOptions): Promise<Blob>;
|
|
760
|
+
/** Encode a reduction as one GIF that plays it in both the graph and the block views side by side. Shares
|
|
761
|
+
* the block layout settings so the two panels agree on the canvas color and fonts. */
|
|
762
|
+
exportSideBySideGif(states: readonly Atom[][], lib: GifEncoderLib, opts?: GifOptions): Promise<Blob>;
|
|
763
|
+
show(): void;
|
|
764
|
+
hide(): void;
|
|
765
|
+
destroy(): void;
|
|
766
|
+
private pathFromEvent;
|
|
767
|
+
/** The leaf text at `path`, or null when the term is a form (not editable as text). */
|
|
768
|
+
private leafText;
|
|
769
|
+
private lastPath;
|
|
770
|
+
private lastClickTime;
|
|
771
|
+
private readonly onPointerDown;
|
|
772
|
+
/** Begin editing the selected leaf. When `replace` is set the buffer starts empty (typing replaces the
|
|
773
|
+
* term); otherwise it starts from the current text (typing extends it). */
|
|
774
|
+
private startEdit;
|
|
775
|
+
/** Commit the edit: re-parse the buffer into an atom and splice it back into the program. */
|
|
776
|
+
private commitEdit;
|
|
777
|
+
private cancelEdit;
|
|
778
|
+
/** Reduce the selected term one step in place. Returns whether anything changed. */
|
|
779
|
+
reduceSelected(): boolean;
|
|
780
|
+
/** Step back to the program before the last reduction or edit. */
|
|
781
|
+
back(): boolean;
|
|
782
|
+
canStepBack(): boolean;
|
|
783
|
+
private readonly onKeyDown;
|
|
784
|
+
private onEditKey;
|
|
785
|
+
/** Every box path in preorder (a term before its children). */
|
|
786
|
+
private preorder;
|
|
787
|
+
/** Move the cursor: right and left step through the tree in preorder, down enters the first child, up
|
|
788
|
+
* returns to the parent. */
|
|
789
|
+
private navigate;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/** Encode a reduction (its list of states, each a frontier of atoms) into one GIF showing the graph and the
|
|
793
|
+
* block views side by side, morphing between states together. `s` supplies the block layout and the shared
|
|
794
|
+
* canvas color. Returns an `image/gif` Blob. */
|
|
795
|
+
declare function sideBySideReductionGif(states: readonly Atom[][], s: BlockSettings, lib: GifEncoderLib, opts?: GifOptions): Promise<Blob>;
|
|
796
|
+
/** The graph and block views in one SVG animation, suitable for browser or Node rasterization. */
|
|
797
|
+
declare function sideBySideReductionSvgs(states: readonly Atom[][], opts?: GifOptions, s?: BlockSettings): SvgAnimation;
|
|
798
|
+
/** One rendered graph frame: a self-contained SVG string and how long to hold it (ms). */
|
|
799
|
+
type GraphFrame = SvgFrame;
|
|
800
|
+
/** The node-graph view of a reduction as a sequence of SVG frames over a fixed-size, action-following
|
|
801
|
+
* viewport. Pure (no DOM), so it runs in Node as well as the browser: {@link graphReductionGif} rasterizes
|
|
802
|
+
* these with browser Canvas, while the Node entry uses Sharp. */
|
|
803
|
+
declare function graphReductionSvgs(states: readonly Atom[][], opts?: GifOptions): SvgAnimation;
|
|
804
|
+
/** Encode a reduction as a GIF of the node-graph view alone, morphing between states. Companion to {@link
|
|
805
|
+
* reductionGif} (the block view); stack the two to show a reduction both ways. Rasterizes the frames from
|
|
806
|
+
* {@link graphReductionSvgs} with a canvas. */
|
|
807
|
+
declare function graphReductionGif(states: readonly Atom[][], lib: GifEncoderLib, opts?: GifOptions): Promise<Blob>;
|
|
808
|
+
/** The nested-block view of a reduction as a sequence of SVG frames over a fixed view box (the union of every
|
|
809
|
+
* state's bounds). Pure (no DOM), the block-view companion to {@link graphReductionSvgs}: place the two next
|
|
810
|
+
* to each other to show a reduction both ways. Rasterize with a canvas ({@link reductionGif}) or an external
|
|
811
|
+
* tool. Uses default block settings (site palette, monospace unit width); pass `background` to override the
|
|
812
|
+
* canvas color. */
|
|
813
|
+
declare function blockReductionSvgs(states: readonly Atom[][], opts?: GifOptions): SvgAnimation;
|
|
814
|
+
|
|
815
|
+
export { type BlockBox, type BlockPalette, type BlockSettings, BlockView, CUTOFF, Controller, type ControllerHost, type EvalResult, type GifEncoderLib, type GifOptions, Graph, type GraphFrame, type GraphJson, type GraphNode, type Grapher, type GrapherOptions, MeTTaGrapher, NODE_H, type NodeColor, type NodeKind, type NodeLabel, type NodeRole, type PaletteChoice, type ProfileRow, type PulledPoint, type RenderState, Renderer, SITE_PALETTE, type SvgAnimation, type SvgFrame, type SvgRasterizer, TEAL_PALETTE, VIZ_SPACE, type Viewport, type VizDirective, type VizOverlay, type VizResult, atomToGraph, bindVizSpace, blockReductionSvgs, colorFor, colorOf, completionsFor, composeAtom, displayText, encodeSvgAnimation, evaluateHead, evaluateHeadAsync, fromJson, fromSource, graphReductionGif, graphReductionSvgs, graphToAtoms, grapher, initialViewport, layout, layoutAtom, loadProgram, makeSettings, nodeWidth, pan, parseLeaf, parseProgram, placeProgram, pulledPointsToPath, readViz, reduceStep, reduceTrace, reductionGif, roleOf, roundedBackingPath, roundedRectPath, sideBySideReductionGif, sideBySideReductionSvgs, textOf, toJson, toScreen, toSource, toWorld, variableLinks, zoomAt };
|