@weasel-js/diagram 1.10.1 → 1.11.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.
@@ -0,0 +1,417 @@
1
+ import { D as DiagramData, a as DiagramSceneOptions, N as NodeStyle, b as DataEdge, E as EdgeStyle, c as DataNode, d as DiagramRouter, e as DiagramSpec } from './fromData-GKqRgPFs.js';
2
+ import { a as Row, M as MeasureRowText } from './body-2lC7IiIA.js';
3
+ import * as react from 'react';
4
+ import { Paint } from '@weasel-js/core';
5
+ import '@weasel-js/core/math';
6
+ import '@weasel-js/geom';
7
+
8
+ /** An effects pipeline as plain data. It says what is wired to what and
9
+ * nothing about how any of it is drawn. */
10
+ interface EffectPipeline {
11
+ stages: readonly EffectStage[];
12
+ wires: readonly EffectWire[];
13
+ groups?: readonly EffectGroup[];
14
+ /** What the value types mean. A type no entry names is plain data. */
15
+ types?: Readonly<Record<string, EffectType>>;
16
+ }
17
+ /** One step of a pipeline: what it reads and writes, and what its box shows. */
18
+ interface EffectStage {
19
+ id: string;
20
+ title: string;
21
+ /** What sort of stage this is, for a look to read. The shipped looks know
22
+ * 'stage' (default), 'decision', 'source' and 'sink', and draw any other
23
+ * value as 'stage'. */
24
+ kind?: string;
25
+ inputs?: readonly EffectPort[];
26
+ outputs?: readonly EffectPort[];
27
+ /** Settings worth showing, in order. */
28
+ params?: readonly {
29
+ label: string;
30
+ value: string;
31
+ }[];
32
+ /** For a decision that splits on a number: the input it compares, and the
33
+ * cut points in ascending order. N cuts need N + 1 outputs, the lowest
34
+ * band first. */
35
+ split?: {
36
+ input: string;
37
+ at: readonly number[];
38
+ };
39
+ /** The stage is in the pipeline and switched off. */
40
+ bypassed?: boolean;
41
+ /** Anything else a look wants. No shipped look reads it. */
42
+ data?: Readonly<Record<string, unknown>>;
43
+ }
44
+ /** One input or output of a stage, carrying a value of one type. */
45
+ interface EffectPort {
46
+ /** Unique among the stage's inputs and outputs together. */
47
+ id: string;
48
+ /** Default the id. */
49
+ label?: string;
50
+ type: string;
51
+ }
52
+ /** A connection from one stage's output to another stage's input. */
53
+ interface EffectWire {
54
+ from: {
55
+ stage: string;
56
+ port: string;
57
+ };
58
+ to: {
59
+ stage: string;
60
+ port: string;
61
+ };
62
+ /** Drawn on the wire. */
63
+ label?: string;
64
+ }
65
+ /** A box drawn around some stages, and around other groups. */
66
+ interface EffectGroup {
67
+ id: string;
68
+ label?: string;
69
+ /** Stage ids and group ids. */
70
+ members: readonly string[];
71
+ }
72
+ /** One run of a pipeline: what happened, beside the pipeline rather than in
73
+ * it, so it can change every frame while the pipeline and its layout stay
74
+ * put. A stage the run has no entry for is one it never reached. */
75
+ interface EffectRun {
76
+ stages: Readonly<Record<string, EffectStageRun>>;
77
+ }
78
+ /** What one stage did in a run. */
79
+ interface EffectStageRun {
80
+ /** How long it took, in milliseconds. */
81
+ cost?: number;
82
+ /** For a decision: the output it chose. */
83
+ taken?: string;
84
+ /** What each output carried, by port id, as text to show. */
85
+ values?: Readonly<Record<string, string>>;
86
+ /** What each output carried, by port id, as a picture, drawn in the slot a
87
+ * look keeps for it (`showPreviews`). A bitmap rather than a canvas
88
+ * because its pixels cannot change: hand back the same one and nothing is
89
+ * uploaded again; draw new pixels into a new one. */
90
+ previews?: Readonly<Record<string, ImageBitmap>>;
91
+ }
92
+ /** What a value type means, as `EffectPipeline.types` records it. */
93
+ interface EffectType {
94
+ /** A control value: a condition, a gate, a modulation source. Looks draw
95
+ * its wires apart from data wires. */
96
+ control?: boolean;
97
+ }
98
+
99
+ /** One thing wrong with a pipeline, and where. */
100
+ interface EffectProblem {
101
+ kind: 'missing-stage' | 'missing-port' | 'wrong-direction' | 'type-mismatch' | 'duplicate-stage' | 'duplicate-port' | 'duplicate-group' | 'missing-member' | 'bad-split';
102
+ message: string;
103
+ stage?: string;
104
+ port?: string;
105
+ /** Index into `pipeline.wires`. */
106
+ wire?: number;
107
+ group?: string;
108
+ }
109
+ /** Everything wrong with `pipeline`. Never throws. */
110
+ declare function checkPipeline(pipeline: EffectPipeline): EffectProblem[];
111
+
112
+ /** What every look shares: how a type is colored, how a stage and a wire are
113
+ * styled, and the lookups a look does over a pipeline. */
114
+
115
+ /** The color of a value type, for a port or a wire. Answers `undefined`, a
116
+ * port with no type, with a neutral color. */
117
+ type TypeColor = (type: string | undefined) => string;
118
+ /** What a look hands back: `diagramScene`'s two arguments, and its colors. */
119
+ interface EffectLookResult {
120
+ data: DiagramData;
121
+ scene: DiagramSceneOptions;
122
+ color: TypeColor;
123
+ /** Edges standing in for a decision's exits where the look draws no
124
+ * decision, keyed by edge id: which stage chose, and by which output. A
125
+ * run reads that stage's `taken` for them. */
126
+ exits?: ReadonlyMap<string, {
127
+ stage: string;
128
+ port: string;
129
+ }>;
130
+ }
131
+ /** One way of drawing a pipeline. Unparameterized, a look whose options are
132
+ * not known: any look fits it, and it is called with none. */
133
+ type EffectLook<TOptions = never> = (pipeline: EffectPipeline, options?: TOptions) => EffectLookResult;
134
+ /** The color `wireStyle` draws a wire in when `checkPipeline` reported it. */
135
+ declare const PROBLEM_COLOR = "#ff5d5d";
136
+ /** A color per type: the one given, or the next in the palette in the order
137
+ * types first appear on the pipeline's ports. */
138
+ declare function typeColors(pipeline: EffectPipeline, given?: Readonly<Record<string, string>>): TypeColor;
139
+ /** Whether `type` is one the pipeline's `types` mark as `control`. */
140
+ declare function isControl(pipeline: EffectPipeline, type: string | undefined): boolean;
141
+ /** The node style the shipped looks give a stage: dashed and dim when it is bypassed. */
142
+ declare function stageStyle(stage: EffectStage): NodeStyle;
143
+ /** The edge style the shipped looks give a wire: `color`, dashed for a
144
+ * control wire, and `PROBLEM_COLOR` in place of `color` for a flagged one. */
145
+ declare function wireStyle(color: string, control: boolean, problem: boolean): EdgeStyle;
146
+ /** Stages with the repeats dropped, first one kept. `diagramScene` throws on
147
+ * a repeated id, so a look builds its nodes from these. */
148
+ declare function uniqueStages(pipeline: EffectPipeline): EffectStage[];
149
+ /** Groups with the repeats dropped, first one kept, and none that has the id
150
+ * of a stage: `diagramScene` throws on an id that names two things. */
151
+ declare function uniqueGroups(pipeline: EffectPipeline): EffectGroup[];
152
+ /** The port called `id` among a stage's inputs and outputs, inputs first. */
153
+ declare function portOn(stage: EffectStage | undefined, id: string): EffectPort | undefined;
154
+ /** A stage's `kind` as the shipped looks read it: any value they do not know is `'stage'`. */
155
+ declare function kindOf(stage: EffectStage): 'stage' | 'decision' | 'source' | 'sink';
156
+ /** A wire with both ends present, and what a look needs to draw it. */
157
+ interface DrawableWire {
158
+ wire: EffectWire;
159
+ /** Index into `pipeline.wires`. */
160
+ index: number;
161
+ /** The value type of the port the wire leaves. */
162
+ type: string | undefined;
163
+ /** `checkPipeline` reported it. */
164
+ problem: boolean;
165
+ fromStage: EffectStage;
166
+ toStage: EffectStage;
167
+ }
168
+ /** The wires a look can draw: each one whose two stages and two ports exist,
169
+ * in the pipeline's order. A wire `checkPipeline` reported and that still has
170
+ * both ends is kept, with `problem` set. */
171
+ declare function drawableWires(pipeline: EffectPipeline): DrawableWire[];
172
+ /** What a value row shows before a run fills it in. */
173
+ declare const NO_VALUE = "\u2013";
174
+ /** The row id of the value row for an output, under its stage's body. */
175
+ declare const valueRowId: (port: string) => string;
176
+ /** The row id of the preview slot for an output, under its stage's body. */
177
+ declare const previewRowId: (port: string) => string;
178
+ /** `RunRowOptions.previewSize`'s default: a 48-unit square. */
179
+ declare const PREVIEW_SIZE = 48;
180
+ /** The rows a look keeps on each stage for what an `EffectRun` shows there.
181
+ * Kept from the start, so a run fills them in without the chart laying out
182
+ * again. A decision's symbol keeps neither. */
183
+ interface RunRowOptions {
184
+ /** A row per output for its value. Default false. */
185
+ showValues?: boolean;
186
+ /** A slot per output for its preview, after its value row. Default false. */
187
+ showPreviews?: boolean;
188
+ /** The preview slot's size: a square's side, or a width and height. A
189
+ * preview is stretched to fill it. Default `PREVIEW_SIZE`. */
190
+ previewSize?: number | {
191
+ width: number;
192
+ height: number;
193
+ };
194
+ }
195
+ /** The body rows of an ordinary stage: its title, a row of its ports when
196
+ * `withPorts` (inputs left, outputs right), then for each output its value
197
+ * row when `showValues` and its preview slot when `showPreviews`, then its
198
+ * params when `showParams`. */
199
+ declare function stageRows(stage: EffectStage, opts: {
200
+ showParams: boolean;
201
+ withPorts: boolean;
202
+ } & RunRowOptions): Row[];
203
+ /** What a wire is called: its own label, or for a wire leaving a decision the
204
+ * exit's label, which defaults to the exit's id. Any other wire has no name. */
205
+ declare function exitLabel(d: DrawableWire): string | undefined;
206
+ /** One edge per drawable wire, from port to port, named by `exitLabel` and
207
+ * styled by `wireStyle` in its type's color. */
208
+ declare function wireEdges(pipeline: EffectPipeline, color: TypeColor): {
209
+ edge: DataEdge;
210
+ style: EdgeStyle;
211
+ }[];
212
+
213
+ /** What every branch symbol is built from: its types, where its ports go, and
214
+ * the diamond each one falls back to. */
215
+
216
+ /** What a branch symbol draws: a data node without its id or style, which the look adds. */
217
+ type BranchNode = Pick<DataNode, 'outline' | 'lines' | 'rows' | 'ports' | 'marks' | 'width' | 'height' | 'padding'>;
218
+ /** How a look wants a branch symbol drawn. */
219
+ interface BranchOptions {
220
+ /** The edge control inputs enter by: the side the stages driving them sit
221
+ * on. Default `'top'`. */
222
+ controlSide?: 'top' | 'bottom';
223
+ /** The style the look draws the stage's node in: lines, dots and ticks
224
+ * take its `text` color. Default `stageStyle(stage)`. */
225
+ style?: NodeStyle;
226
+ /** The colors of a `bar`'s bands and a `crossover`'s curves, lowest
227
+ * first, repeating. Default a palette of four, or for a bypassed stage
228
+ * `style.stroke` for every band. */
229
+ tints?: readonly string[];
230
+ }
231
+ /** Draws one decision stage, with a port for each of its inputs and outputs. */
232
+ type BranchSymbol = (stage: EffectStage, pipeline: EffectPipeline, options?: BranchOptions) => BranchNode;
233
+
234
+ /** Which symbol a decision draws as: one by name, or `'auto'` for a bar when
235
+ * the stage has a sound `split` and a diamond otherwise. */
236
+ type BranchChoice = 'auto' | 'diamond' | 'bar' | 'demux' | 'switch' | 'hexagon' | 'step' | 'comparator' | 'crossover' | 'fork';
237
+ /** Each branch symbol by name. One called on a stage it cannot draw draws
238
+ * the `diamond` instead: a `bar`, `step` or `crossover` with no sound split,
239
+ * or a `switch` or `comparator` without exactly two exits. */
240
+ declare const BRANCH_SYMBOLS: Readonly<Record<Exclude<BranchChoice, 'auto'>, BranchSymbol>>;
241
+ /** The symbol `choice` comes to for `stage`: `'auto'` a bar for a sound
242
+ * split, and any symbol that cannot draw the stage the diamond. */
243
+ declare function symbolNameFor(stage: EffectStage, choice?: BranchChoice): Exclude<BranchChoice, 'auto'>;
244
+ /** The node a decision stage draws as, by the symbol `choice` comes to. */
245
+ declare function branchNode(stage: EffectStage, pipeline: EffectPipeline, choice?: BranchChoice, options?: BranchOptions): BranchNode;
246
+
247
+ /** Options for the `compact` look. */
248
+ interface CompactOptions {
249
+ /** Default `'bezier'`. */
250
+ router?: DiagramRouter;
251
+ /** Default 16. */
252
+ nodeGap?: number;
253
+ /** Default 48. */
254
+ rankGap?: number;
255
+ /** A color per value type, over the palette's own. */
256
+ colors?: Readonly<Record<string, string>>;
257
+ /** Default `'hexagon'`, the one symbol that keeps a decision one row tall. */
258
+ branch?: BranchChoice;
259
+ }
260
+ /** Between a compact stage's outline and its title. */
261
+ declare const COMPACT_PADDING = 4;
262
+ /** The compact look: each stage one line, its title alone, and no ports
263
+ * drawn; the wires between two stages one line between them. For a
264
+ * pipeline too big to read as a node graph. */
265
+ declare const compact: EffectLook<CompactOptions>;
266
+
267
+ /** Props for `EffectChart`. */
268
+ interface EffectChartProps<TOptions = never> {
269
+ /** Compared by its JSON, so it may be rebuilt on every render: the chart
270
+ * lays out again only when that changes. A value JSON drops or flattens
271
+ * in a stage's `data` (a function, a `Map`) is not seen changing. */
272
+ pipeline: EffectPipeline;
273
+ /** One run of the pipeline, drawn over it: stages it never reached and
274
+ * branches it did not take faded, each stage's cost above its corner, and
275
+ * each output's value and preview in the rows a look keeps for them
276
+ * (`showValues`, `showPreviews`). It may change every frame: the chart
277
+ * neither lays out again nor refits, and repaints only what changed. A
278
+ * preview the next run no longer shows has its texture freed then. */
279
+ run?: EffectRun;
280
+ /** How the pipeline is drawn. Default `nodeGraph`. */
281
+ look?: EffectLook<TOptions>;
282
+ /** The look's options. Keep the object's identity steady between renders,
283
+ * or the chart lays out again on each one. */
284
+ options?: TOptions;
285
+ /** CSS pixels. Omit both to fill the parent, which then needs a size of
286
+ * its own. The chart refits when its size changes, until the user pans or
287
+ * zooms. */
288
+ width?: number;
289
+ height?: number;
290
+ /** The smallest scale the chart opens at. A chart that does not fit whole
291
+ * at it opens at it anyway, anchored at its start, and the rest is a pan
292
+ * away. Default `EFFECT_MIN_SCALE`. */
293
+ minScale?: number;
294
+ /** What the canvas paints behind the chart. Unset, it is transparent; the
295
+ * shipped looks are drawn for a dark ground. */
296
+ background?: Paint;
297
+ /** A stage id, or null for none. */
298
+ selected?: string | null;
299
+ /** Hears each pick: a stage's id, or `null` for anything else. Only a
300
+ * stage can be picked: a click on a group box or a lane lands on the
301
+ * canvas behind it. The canvas keeps its own highlight on the stage picked;
302
+ * only a change to `selected` moves it. */
303
+ onSelect?: (stage: string | null) => void;
304
+ /** What `checkPipeline` found. Called once on mount, and again each time
305
+ * the pipeline's content changes. */
306
+ onProblems?: (problems: readonly EffectProblem[]) => void;
307
+ /** A class for the canvas element. */
308
+ className?: string;
309
+ }
310
+ /** `EffectChart`'s default `minScale`: the shipped looks' 12px titles at 6px, the smallest still legible. */
311
+ declare const EFFECT_MIN_SCALE = 0.5;
312
+ /** A chart of an effects pipeline: pan, zoom, and pick a stage. Text paints
313
+ * only in a registered font family, so call `registerCanvasFont('sans-serif')`
314
+ * once before mounting one. */
315
+ declare function EffectChart<TOptions = never>({ pipeline: given, run, look, options, width, height, minScale, background, selected, onSelect, onProblems, className, }: EffectChartProps<TOptions>): react.JSX.Element;
316
+
317
+ /** Options for the `lanes` look. */
318
+ interface LanesOptions extends RunRowOptions {
319
+ /** The value types whose lanes come first, top down. The rest follow in
320
+ * the order their types first appear on the pipeline's ports. */
321
+ lanes?: readonly string[];
322
+ /** The least height of a lane. A lane grows past it until what stands in
323
+ * it fits. Default 48. */
324
+ laneHeight?: number;
325
+ /** Between one column of stages and the next. Default 40. */
326
+ rankGap?: number;
327
+ /** Default `'bezier'`. */
328
+ router?: DiagramRouter;
329
+ /** A color per value type, over the palette's own. */
330
+ colors?: Readonly<Record<string, string>>;
331
+ /** Whether a stage lists its `params`. Default true. */
332
+ showParams?: boolean;
333
+ /** Default `'auto'`. */
334
+ branch?: BranchChoice;
335
+ /** Measures text, as `diagramScene` takes it, for sizing stages before
336
+ * the lanes are cut to fit them. It is handed on in the look's `scene`. */
337
+ measure?: MeasureRowText;
338
+ }
339
+ /** How far a stage stands inside the first and last lane it touches, at
340
+ * least: more beside a lane edge that wires run along on several tracks. */
341
+ declare const LANE_INSET = 6;
342
+ /** The node id of the lane for a value type. */
343
+ declare const laneId: (type: string) => string;
344
+ /** The lanes look: a horizontal lane per value type, and each stage standing
345
+ * across the lanes of the types it reads and writes, as tall as they are,
346
+ * its ports in their own lanes. A decision keeps its symbol's size, centered
347
+ * across its lanes. Columns run left to right in the order the signal flows.
348
+ * A wire runs around the stages between its ends along the lane edges, each
349
+ * sharing one on a track of its own. */
350
+ declare const lanes: EffectLook<LanesOptions>;
351
+
352
+ /** Options for the `rack` look. */
353
+ interface RackOptions extends RunRowOptions {
354
+ /** The stage ids on the line, in order. Default the longest path over data wires. */
355
+ chain?: readonly string[];
356
+ /** Where what feeds the chain from the side sits. Default `'below'`. */
357
+ side?: 'below' | 'above';
358
+ nodeGap?: number;
359
+ rankGap?: number;
360
+ /** A color per value type, over the palette's own. */
361
+ colors?: Readonly<Record<string, string>>;
362
+ /** Whether a stage lists its `params`. Default true. A decision's symbol
363
+ * does not show params either way. */
364
+ showParams?: boolean;
365
+ /** Default `'auto'`. */
366
+ branch?: BranchChoice;
367
+ /** Draw a decision that only skips ahead as an arc over what it skips. Default true. */
368
+ collapseSkips?: boolean;
369
+ }
370
+ /** The rack look: the main signal on one straight line with its stages in
371
+ * order, and whatever feeds a stage from the side hung beside it. */
372
+ declare const rack: EffectLook<RackOptions>;
373
+
374
+ /** Options for the `nodeGraph` look. */
375
+ interface NodeGraphOptions extends RunRowOptions {
376
+ /** Default `'bezier'`. */
377
+ router?: DiagramRouter;
378
+ nodeGap?: number;
379
+ rankGap?: number;
380
+ /** A color per value type, over the palette's own. */
381
+ colors?: Readonly<Record<string, string>>;
382
+ /** Whether a stage lists its `params`. Default true. A decision's symbol
383
+ * does not show params either way. */
384
+ showParams?: boolean;
385
+ /** Default `'auto'`. */
386
+ branch?: BranchChoice;
387
+ }
388
+ /** The node-graph look: every port a named row on its stage, a wire from port
389
+ * to port in the color of what it carries, flowing left to right. */
390
+ declare const nodeGraph: EffectLook<NodeGraphOptions>;
391
+
392
+ /** The looks that ship, by name. */
393
+ declare const EFFECT_LOOKS: Readonly<{
394
+ nodeGraph: EffectLook<NodeGraphOptions>;
395
+ rack: EffectLook<RackOptions>;
396
+ lanes: EffectLook<LanesOptions>;
397
+ compact: EffectLook<CompactOptions>;
398
+ }>;
399
+
400
+ /** Which stages a pipeline's main signal runs through, and which decisions on
401
+ * that run only choose between going on and skipping ahead. */
402
+
403
+ /** Stage ids of the longest path over data wires, sources first. */
404
+ declare function mainChain(pipeline: EffectPipeline): string[];
405
+
406
+ /**
407
+ * `specs` as `run` leaves them: a stage the run never reached faded, with its
408
+ * wires; a decision's wires to the outputs it did not take faded; each value
409
+ * row a look kept filled in; a `switch` thrown to the output its decision
410
+ * took; and each stage's cost written above its corner.
411
+ * No run, no change.
412
+ */
413
+ declare function paintRun(pipeline: EffectPipeline, specs: readonly DiagramSpec[], run: EffectRun | undefined, exits?: EffectLookResult['exits']): DiagramSpec[];
414
+ /** A cost in milliseconds, to three figures. */
415
+ declare function costText(ms: number): string;
416
+
417
+ export { BRANCH_SYMBOLS, type BranchChoice, type BranchNode, type BranchOptions, type BranchSymbol, COMPACT_PADDING, type CompactOptions, type DrawableWire, EFFECT_LOOKS, EFFECT_MIN_SCALE, EffectChart, type EffectChartProps, type EffectGroup, type EffectLook, type EffectLookResult, type EffectPipeline, type EffectPort, type EffectProblem, type EffectRun, type EffectStage, type EffectStageRun, type EffectType, type EffectWire, LANE_INSET, type LanesOptions, NO_VALUE, type NodeGraphOptions, PREVIEW_SIZE, PROBLEM_COLOR, type RackOptions, type RunRowOptions, type TypeColor, branchNode, checkPipeline, compact, costText, drawableWires, exitLabel, isControl, kindOf, laneId, lanes, mainChain, nodeGraph, paintRun, portOn, previewRowId, rack, stageRows, stageStyle, symbolNameFor, typeColors, uniqueGroups, uniqueStages, valueRowId, wireEdges, wireStyle };