@weasel-js/diagram 1.11.1 → 1.12.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.
@@ -1,6 +1,6 @@
1
1
  import { DerivedDep, PoseDescriptor, NodeShapeEntry, MarkerRef, Page, PageLayoutOptions, AddNodeSpec, Stroke, RectPose } from '@weasel-js/core';
2
2
  import { Vec2 } from '@weasel-js/core/math';
3
- import { E as EdgeHop, S as StyleField, P as PortAnchor, D as DiagramGroup, R as RowTextStyle, a as Row, O as Outline, b as PortSpec, B as BodySpec, c as DiagramLabel, L as LayoutPorts, d as LayoutFn, e as LayoutOptions, M as MeasureRowText, f as DiagramNode } from './types-BbHunLXm.js';
3
+ import { E as EdgeHop, S as StyleField, P as PortAnchor, D as DiagramGroup, R as RowTextStyle, a as Row, O as Outline, b as PortSpec, B as BodySpec, c as DiagramLabel, L as LayoutPorts, d as LayoutFn, e as LayoutOptions, M as MeasureRowText, f as DiagramNode } from './types-M_ccNAlk.js';
4
4
 
5
5
  /**
6
6
  * Off-page markers as data: what a connector cut at the page gap holds, and
@@ -450,6 +450,8 @@ interface NodeStyle {
450
450
  strokeWidth?: number;
451
451
  dash?: number[];
452
452
  }
453
+ /** What a node is drawn with when nothing says otherwise. */
454
+ declare const DEFAULT_NODE_STYLE: NodeStyle;
453
455
  /** A node's or region's outline width when its style gives none. */
454
456
  declare const NODE_STROKE_WIDTH = 2;
455
457
  /** A lane's outline width, which its style does not change. */
@@ -539,15 +541,18 @@ interface DiagramSceneOptions<TLayer extends string = 'main'> {
539
541
  minWidth?: number;
540
542
  /** Where edge labels sit. Default `{ at: 'mid', offset: 9 }`. */
541
543
  labelPlacement?: DiagramLabel;
542
- nodeStyle?: (node: DataNode) => NodeStyle;
544
+ /** A node's look; `undefined` keeps the theme's, else {@link DEFAULT_NODE_STYLE}. */
545
+ nodeStyle?: (node: DataNode) => NodeStyle | undefined;
543
546
  /** Default 12. */
544
547
  groupPadding?: number;
545
- /** A group's box and label. `text` colors the label. */
546
- groupStyle?: (group: DataGroup) => NodeStyle;
547
- edgeStyle?: (edge: DataEdge) => EdgeStyle;
548
+ /** A group's box and label. `text` colors the label. `undefined` keeps the theme's
549
+ * container, else `DEFAULT_GROUP_STYLE`. */
550
+ groupStyle?: (group: DataGroup) => NodeStyle | undefined;
551
+ /** An edge's look; `undefined` keeps the theme's, else `DEFAULT_EDGE_STYLE`. */
552
+ edgeStyle?: (edge: DataEdge) => EdgeStyle | undefined;
548
553
  /** Styles nodes by their `style` role, and edges, groups and text by the theme, where the
549
554
  * functions above leave them; and its face is the default `font`. */
550
555
  theme?: DiagramTheme;
551
556
  }
552
557
 
553
- export { ANCHOR_DERIVE_POSE as A, type GroupPoseOptions as B, NODE_STROKE_WIDTH as C, type DiagramTheme as D, type EdgeStyle as E, type OffPageTag as F, GROUP_DERIVE_POSE as G, anchorDerivePose as H, boxAround as I, diagramAnchorOf as J, diagramEdgeOf as K, LANE_STROKE_WIDTH as L, diagramGroupOf as M, type NodeStyle as N, type OffPageSplit as O, diagramMarkOf as P, groupDerivePose as Q, layoutOwnsPort as R, layoutOwnsRoute as S, layoutWritesRoute as T, markShape as U, offPageTagId as V, offPageTagOf as W, registerMarkShape as X, rowTextStyle as Y, type DiagramData as a, type DiagramSceneOptions as b, type DataEdge as c, type DataNode as d, type DiagramRouter as e, type DiagramSpec as f, type EdgeEnd as g, type DiagramSceneData as h, type DiagramEdge as i, type DataContainer as j, DEFAULT_LANE_SIZE as k, DEFAULT_POOL_ACROSS as l, DIAGRAM_ANCHOR as m, DIAGRAM_GROUP as n, DIAGRAM_ROLES as o, DIAGRAM_THEME_KEY as p, type DataGroup as q, type DataLane as r, type DataMark as s, type DiagramAnchor as t, type DiagramDerivePose as u, type DiagramFont as v, type DiagramMark as w, type DiagramRole as x, type DiagramTextStyle as y, EDGE_STROKE_WIDTH as z };
558
+ export { ANCHOR_DERIVE_POSE as A, EDGE_STROKE_WIDTH as B, type GroupPoseOptions as C, type DiagramTheme as D, type EdgeStyle as E, NODE_STROKE_WIDTH as F, GROUP_DERIVE_POSE as G, type OffPageTag as H, anchorDerivePose as I, boxAround as J, diagramAnchorOf as K, LANE_STROKE_WIDTH as L, diagramEdgeOf as M, type NodeStyle as N, type OffPageSplit as O, diagramGroupOf as P, diagramMarkOf as Q, groupDerivePose as R, layoutOwnsPort as S, layoutOwnsRoute as T, layoutWritesRoute as U, markShape as V, offPageTagId as W, offPageTagOf as X, registerMarkShape as Y, rowTextStyle as Z, type DiagramData as a, type DiagramSceneOptions as b, type DataEdge as c, type DataNode as d, type DiagramRouter as e, type DiagramSpec as f, type EdgeEnd as g, type DiagramSceneData as h, type DiagramEdge as i, type DataContainer as j, DEFAULT_LANE_SIZE as k, DEFAULT_NODE_STYLE as l, DEFAULT_POOL_ACROSS as m, DIAGRAM_ANCHOR as n, DIAGRAM_GROUP as o, DIAGRAM_ROLES as p, DIAGRAM_THEME_KEY as q, type DataGroup as r, type DataLane as s, type DataMark as t, type DiagramAnchor as u, type DiagramDerivePose as v, type DiagramFont as w, type DiagramMark as x, type DiagramRole as y, type DiagramTextStyle as z };
@@ -131,7 +131,8 @@ interface LiveAudioRunnerHandle extends LiveAudioRunnerState {
131
131
  /**
132
132
  * A runner made on mount and remade when `engine`, `bus` or `nodes` change, following `pipeline`,
133
133
  * `sources` and `previews` through `useFollowAudioRunner`, and disposed on unmount. Before the first
134
- * mount the runner is null and the run holds the plan's errors. The engine is the caller's.
134
+ * mount the runner is null and the run holds the plan's errors. The engine is the caller's. `nodes`
135
+ * counts as changed only when a type is added, dropped or given a different node, so it can be built in render.
135
136
  */
136
137
  declare function useLiveAudioRunner(opts: UseLiveAudioRunnerOptions): LiveAudioRunnerHandle;
137
138
 
@@ -1,9 +1,9 @@
1
- import { formatParam, uniqueStages, runOrder, paramValues, PREVIEW_DENSITY, closeBitmaps, previewsOf, PREVIEW_SIZE } from './chunk-QKSWZEJH.js';
2
- import './chunk-43LDZ6L4.js';
3
- import './chunk-IM6DHWZO.js';
1
+ import { formatParam, uniqueStages, runOrder, paramValues, PREVIEW_DENSITY, closeBitmaps, previewsOf, PREVIEW_SIZE } from './chunk-5GIP2LA6.js';
2
+ import './chunk-2SYY4W3B.js';
3
+ import './chunk-R2XB6D32.js';
4
4
  import { createMixNode, createFileSourceNode, compressorNode, reverbNode, delayNode, filterNode, createPanNode, createGainNode, createNoiseNode, createOscillatorNode } from '@weasel-js/audio';
5
5
  import { useEffect, useSyncExternalStore, useMemo, useState } from 'react';
6
- import { useVisibleRaf, useLatest } from '@weasel-js/react';
6
+ import { useVisibleRaf, useStableByContent, useLatest } from '@weasel-js/react';
7
7
 
8
8
  var node = (settingIds, levels, make) => ({
9
9
  settings: (params) => Object.fromEntries(settingIds.filter((id) => params[id] !== void 0).map((id) => [id, params[id]])),
@@ -503,7 +503,8 @@ function useFollowAudioRunner(runner, opts) {
503
503
  return live ?? { run: planned, playing: false };
504
504
  }
505
505
  function useLiveAudioRunner(opts) {
506
- const { engine, bus, nodes } = opts;
506
+ const { engine, bus } = opts;
507
+ const nodes = useStableByContent(opts.nodes, sameNodes);
507
508
  const latest = useLatest(opts);
508
509
  const [runner, setRunner] = useState(null);
509
510
  useEffect(() => {
@@ -518,9 +519,14 @@ function useLiveAudioRunner(opts) {
518
519
  setRunner(made);
519
520
  return () => made.dispose();
520
521
  }, [engine, bus, nodes, latest]);
521
- const state = useFollowAudioRunner(runner, opts);
522
+ const state = useFollowAudioRunner(runner, { ...opts, ...nodes !== void 0 ? { nodes } : {} });
522
523
  return { ...state, runner };
523
524
  }
525
+ function sameNodes(a, b) {
526
+ if (a === void 0 || b === void 0) return a === b;
527
+ const keys = Object.keys(a);
528
+ return keys.length === Object.keys(b).length && keys.every((k) => Object.hasOwn(b, k) && a[k] === b[k]);
529
+ }
524
530
 
525
531
  export { AUDIO_STAGE_TYPES, EMPTY_PLAN, audioStageNodes, createLiveAudioRunner, diffPlans, drawScope, drawSpectrum, livePlan, useFollowAudioRunner, useLiveAudioRunner };
526
532
  //# sourceMappingURL=effect-audio.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/effect/audio/nodes.ts","../src/effect/audio/plan.ts","../src/effect/audio/patches.ts","../src/effect/audio/scope.ts","../src/effect/audio/livePreviews.ts","../src/effect/audio/liveRunner.ts","../src/effect/audio/stageTypes.ts","../src/effect/audio/useFollowAudioRunner.ts","../src/effect/audio/useLiveAudioRunner.ts"],"names":["levels","param","useEffect"],"mappings":"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","file":"effect-audio.js","sourcesContent":["import {\n compressorNode, createFileSourceNode, createGainNode, createMixNode, createNoiseNode, createOscillatorNode,\n createPanNode, delayNode, filterNode, reverbNode, type GraphNodeDef,\n} from '@weasel-js/audio';\n\n/** What a run supplies to its source stages. */\nexport interface AudioSources { audio?: AudioBuffer }\n\ntype Values = Readonly<Record<string, unknown>>;\n\n/** How one stage type becomes a graph node: its settings, its levels, and the node it builds. */\nexport interface AudioStageNode {\n /** The stage's discrete settings, from its param values and the run's sources. Throws to fail the stage. */\n settings(params: Values, sources: AudioSources): Values;\n /** The ids of its numeric params, each a `params` key of the def `build` returns. */\n levels: readonly string[];\n build(ctx: BaseAudioContext, settings: Values, levels: Readonly<Record<string, number>>): GraphNodeDef;\n}\n/** The graph node of each stage type, by `type`. */\nexport type AudioStageNodes = Readonly<Record<string, AudioStageNode>>;\n\n/** A node whose settings are the named param values; the factory takes them with the levels as one options bag. */\nconst node = (\n settingIds: readonly string[], levels: readonly string[],\n make: (ctx: BaseAudioContext, opts: never) => GraphNodeDef,\n): AudioStageNode => ({\n settings: (params) => Object.fromEntries(settingIds.filter((id) => params[id] !== undefined).map((id) => [id, params[id]])),\n levels,\n build: (ctx, settings, levels) => make(ctx, { ...settings, ...levels } as never),\n});\n\n/** The graph node each stage type builds; `audio.output` has none. */\nexport const audioStageNodes: AudioStageNodes = {\n 'audio.file': {\n settings: (_params, sources) => {\n if (!sources.audio) throw new Error('no source audio');\n return { buffer: sources.audio };\n },\n levels: [],\n build: (ctx, settings) => createFileSourceNode(ctx, { buffer: settings.buffer as AudioBuffer, loop: true }),\n },\n 'audio.oscillator': node(['wave'], ['frequency'], createOscillatorNode),\n 'audio.noise': node(['color'], [], createNoiseNode),\n 'audio.gain': node([], ['gain'], createGainNode),\n 'audio.pan': node([], ['pan'], createPanNode),\n 'audio.filter': node(['type'], ['frequency', 'Q'], filterNode),\n 'audio.delay': node([], ['time', 'feedback', 'mix'], delayNode),\n 'audio.reverb': node(['seconds'], ['mix'], reverbNode),\n 'audio.compressor': node([], ['threshold', 'ratio'], compressorNode),\n 'audio.mix': {\n settings: () => ({}),\n levels: ['a', 'b'],\n build: (ctx, _settings, levels) => {\n const def = createMixNode(ctx, { inputs: ['a', 'b'] });\n for (const id of ['a', 'b']) if (levels[id] !== undefined) def.params[id]!(levels[id], 0);\n return def;\n },\n },\n};\n","import type { GraphTarget } from '@weasel-js/audio';\nimport { uniqueStages } from '../draw';\nimport { runOrder } from '../runner/order';\nimport { paramValues } from '../runner/params';\nimport type { EffectPipeline, EffectStage } from '../types';\nimport type { AudioSources, AudioStageNodes } from './nodes';\n\n/** A node the plan builds: its stage type, its discrete settings and its numeric levels. */\nexport interface PlanNode {\n type: string;\n settings: Readonly<Record<string, unknown>>;\n levels: Readonly<Record<string, number>>;\n}\n/** A connection the plan makes, from a node to another node's port or to the graph's output. */\nexport interface PlanEdge { from: string; to: GraphTarget }\n\n/** The graph an audio pipeline should play: what to build, how it connects, and which stages it left out. */\nexport interface LivePlan {\n nodes: Readonly<Record<string, PlanNode>>;\n /** Sorted by `edgeKey`, so equal plans compare equal. */\n edges: readonly PlanEdge[];\n /** Why a stage is not in `nodes`, by stage id. A stage left out for want of input has none. */\n errors: Readonly<Record<string, string>>;\n}\n\n/** The plan of a graph holding nothing. */\nexport const EMPTY_PLAN: LivePlan = { nodes: {}, edges: [], errors: {} };\n\nconst OUTPUT_TYPE = 'audio.output';\n\n/** One string per edge, the same for equal edges. */\nexport const edgeKey = (e: PlanEdge): string =>\n JSON.stringify([e.from, 'output' in e.to ? null : [e.to.node, e.to.port]]);\n\nfunction levelsOf(levels: readonly string[], params: Readonly<Record<string, unknown>>): Record<string, number> {\n const out: Record<string, number> = {};\n for (const id of levels) {\n const v = params[id];\n if (typeof v === 'number') out[id] = v;\n }\n return out;\n}\n\n/** Compiles the audio stages of `pipeline`; stages of other types are ignored. */\nexport function livePlan(pipeline: EffectPipeline, nodes: AudioStageNodes, sources: AudioSources): LivePlan {\n const stages = new Map<string, EffectStage>();\n for (const s of uniqueStages(pipeline)) {\n if (s.type !== undefined && (Object.hasOwn(nodes, s.type) || s.type === OUTPUT_TYPE)) stages.set(s.id, s);\n }\n const { order, cyclic } = runOrder(pipeline);\n const planNodes: Record<string, PlanNode> = {};\n const errors: Record<string, string> = {};\n for (const id of cyclic) if (stages.has(id)) errors[id] = 'on a feedback loop';\n\n /** The planned nodes whose sound leaves each stage: itself, or what a bypassed stage carries on. */\n const origins = new Map<string, readonly string[]>();\n const edges = new Map<string, PlanEdge>();\n\n for (const id of order) {\n const stage = stages.get(id);\n if (stage === undefined) continue;\n const isOutput = stage.type === OUTPUT_TYPE;\n const bypassed = stage.bypassed === true && !isOutput;\n const firstAudio = (stage.inputs ?? []).find((i) => i.type === 'audio')?.id;\n const fed = pipeline.wires\n .filter((w) => w.to.stage === id && stages.has(w.from.stage) && (!bypassed || w.to.port === firstAudio))\n .flatMap((w) => (origins.get(w.from.stage) ?? []).map((from) => ({ from, port: w.to.port })));\n if ((stage.inputs?.length ?? 0) > 0 && fed.length === 0) continue;\n\n if (bypassed) {\n origins.set(id, [...new Set(fed.map((f) => f.from))]);\n continue;\n }\n if (!isOutput) {\n const entry = nodes[stage.type!]!;\n const params = paramValues(stage);\n try {\n planNodes[id] = { type: stage.type!, settings: entry.settings(params, sources), levels: levelsOf(entry.levels, params) };\n } catch (err) {\n errors[id] = err instanceof Error ? err.message : String(err);\n continue;\n }\n origins.set(id, [id]);\n }\n for (const f of fed) {\n const edge: PlanEdge = { from: f.from, to: isOutput ? { output: true } : { node: id, port: f.port } };\n edges.set(edgeKey(edge), edge);\n }\n }\n return {\n nodes: planNodes,\n edges: [...edges.values()].sort((a, b) => {\n const [ka, kb] = [edgeKey(a), edgeKey(b)];\n return ka < kb ? -1 : ka > kb ? 1 : 0;\n }),\n errors,\n };\n}\n","import type { GraphNodeDef, GraphPatch } from '@weasel-js/audio';\nimport { edgeKey, type LivePlan, type PlanEdge, type PlanNode } from './plan';\n\n/** Makes the def for a node that is added or replaced. */\nexport type BuildNode = (id: string, node: PlanNode) => GraphNodeDef;\n\nfunction sameSettings(a: PlanNode['settings'], b: PlanNode['settings']): boolean {\n const keys = Object.keys(a);\n return keys.length === Object.keys(b).length && keys.every((k) => k in b && Object.is(a[k], b[k]));\n}\n\nconst touches = (e: PlanEdge, ids: ReadonlySet<string>): boolean =>\n ids.has(e.from) || ('node' in e.to && ids.has(e.to.node));\n\n/** The patches that turn the graph `prev` describes into the one `next` describes. */\nexport function diffPlans(prev: LivePlan, next: LivePlan, build: BuildNode): GraphPatch[] {\n const prevIds = Object.keys(prev.nodes).sort();\n const nextIds = Object.keys(next.nodes).sort();\n const gone = new Set<string>(); // removed, or removed to change type: their old edges are dropped\n const fresh = new Set<string>(); // gone, or newly added: every edge touching them in `next` is connected\n const groups = {\n disconnect: [] as GraphPatch[],\n remove: [] as GraphPatch[],\n add: [] as GraphPatch[],\n replace: [] as GraphPatch[],\n set: [] as GraphPatch[],\n connect: [] as GraphPatch[],\n };\n\n for (const id of prevIds) {\n const now = next.nodes[id];\n if (now === undefined || now.type !== prev.nodes[id]!.type) {\n gone.add(id);\n fresh.add(id);\n groups.remove.push({ kind: 'remove', id });\n }\n }\n for (const id of nextIds) {\n const now = next.nodes[id]!;\n const was = prev.nodes[id];\n if (was === undefined || gone.has(id)) {\n fresh.add(id);\n groups.add.push({ kind: 'add', id, def: build(id, now) });\n } else if (!sameSettings(was.settings, now.settings)) {\n groups.replace.push({ kind: 'replace', id, def: build(id, now) });\n } else {\n for (const param of Object.keys(now.levels).sort()) {\n const value = now.levels[param]!;\n if (!Object.is(was.levels[param], value)) groups.set.push({ kind: 'set', id, param, value });\n }\n }\n }\n\n const nextKeys = new Set(next.edges.map(edgeKey));\n const prevKeys = new Set(prev.edges.map(edgeKey));\n for (const e of prev.edges) {\n if (!nextKeys.has(edgeKey(e)) && !touches(e, gone)) {\n groups.disconnect.push({ kind: 'disconnect', from: e.from, to: e.to });\n }\n }\n for (const e of next.edges) {\n if (!prevKeys.has(edgeKey(e)) || touches(e, fresh)) groups.connect.push({ kind: 'connect', from: e.from, to: e.to });\n }\n\n return [\n ...groups.disconnect,\n ...groups.remove,\n ...groups.add,\n ...groups.replace,\n ...groups.set,\n ...groups.connect,\n ];\n}\n","import type { AnalyserTap } from '@weasel-js/audio';\nimport { PREVIEW_DENSITY } from '../draw';\n\n/** What a stage's preview slot shows while its graph plays. */\nexport type AudioPreview = 'off' | 'scope' | 'spectrum';\n\n// Neutral enough to read on both the light and the dark theme; no image preview names a foreground to match.\nconst INK = '#8a8f98';\nconst BANDS = 32;\nconst LINE = 1.5;\n\ntype Size = { width: number; height: number };\n\nfunction canvasOf(size: Size) {\n const canvas = new OffscreenCanvas(\n Math.max(1, Math.round(size.width * PREVIEW_DENSITY)),\n Math.max(1, Math.round(size.height * PREVIEW_DENSITY)),\n );\n return { canvas, g: canvas.getContext('2d')!, w: canvas.width, h: canvas.height };\n}\n\n/** The waveform as a line across the bitmap, silence at mid-height. */\nexport function drawScope(tap: AnalyserTap, size: Size): ImageBitmap {\n const { canvas, g, w, h } = canvasOf(size);\n const wave = tap.waveform();\n g.strokeStyle = INK;\n g.lineWidth = LINE * PREVIEW_DENSITY;\n g.lineJoin = 'round';\n g.beginPath();\n for (let x = 0; x < w; x += 1) {\n const v = wave[Math.min(wave.length - 1, Math.floor((x / Math.max(1, w - 1)) * (wave.length - 1)))]! / 255;\n const y = h - v * h;\n if (x === 0) g.moveTo(x, y);\n else g.lineTo(x, y);\n }\n g.stroke();\n return canvas.transferToImageBitmap();\n}\n\n/** The spectrum as filled bars rising from the bottom, low frequencies on the left. */\nexport function drawSpectrum(tap: AnalyserTap, size: Size): ImageBitmap {\n const { canvas, g, w, h } = canvasOf(size);\n const bands = tap.bands(BANDS);\n const slot = w / BANDS;\n g.fillStyle = INK;\n for (let i = 0; i < BANDS; i += 1) {\n const bar = bands[i]! * h;\n g.fillRect(i * slot, h - bar, slot * 0.8, bar);\n }\n return canvas.transferToImageBitmap();\n}\n","import type { AnalyserTap, AudioGraph } from '@weasel-js/audio';\nimport { PREVIEW_SIZE } from '../draw';\nimport { closeBitmaps, previewsOf } from '../runner/previews';\nimport type { EffectRun, EffectStageRun } from '../types';\nimport { drawScope, drawSpectrum, type AudioPreview } from './scope';\n\n/** The analyser taps behind a live runner's previews, and the runs it has drawn them into. */\nexport interface LivePreviews {\n mode(): AudioPreview;\n setMode(mode: AudioPreview, graph: AudioGraph, ids: readonly string[]): void;\n /** After an edit: forgets taps of `removed` nodes (the graph disposed them) and taps any planned node without one. */\n follow(graph: AudioGraph, removed: readonly string[], planned: readonly string[]): void;\n /** Forgets every tap: they went with the graph they were on. */\n restart(): void;\n /** A run with the previews drawn from every tap, over `errors`; undefined when nothing is tapped. */\n draw(errors: Readonly<Record<string, string>>): EffectRun | undefined;\n /** Notes a run the runner published, so `drawn` can tell which came before it. */\n track(run: EffectRun): void;\n drawn(run: EffectRun | undefined): void;\n /** Closes every bitmap still held and disposes the taps. */\n dispose(): void;\n}\n\n/** A run holding only `errors`, by stage id. */\nexport const errorsRun = (errors: Readonly<Record<string, string>>): EffectRun =>\n ({ stages: Object.fromEntries(Object.entries(errors).map(([id, error]) => [id, { error }])) });\n\nexport function createLivePreviews(): LivePreviews {\n let mode: AudioPreview = 'off';\n let taps = new Map<string, AnalyserTap>();\n // Runs published and not yet known to be off screen, oldest first.\n let published: EffectRun[] = [];\n\n const tapAll = (graph: AudioGraph, ids: readonly string[]) => {\n for (const id of ids) if (!taps.has(id)) taps.set(id, graph.tap(id));\n };\n const disposeTaps = () => {\n for (const t of taps.values()) t.dispose();\n taps = new Map();\n };\n\n return {\n mode: () => mode,\n setMode(next, graph, ids) {\n mode = next;\n if (next === 'off') disposeTaps();\n else tapAll(graph, ids);\n },\n follow(graph, removed, planned) {\n if (mode === 'off') return;\n for (const id of removed) taps.delete(id);\n const live = new Set(planned);\n for (const id of [...taps.keys()]) if (!live.has(id)) taps.delete(id);\n tapAll(graph, planned);\n },\n restart() {\n taps = new Map();\n },\n draw(errors) {\n if (mode === 'off' || taps.size === 0) return undefined;\n const paint = mode === 'scope' ? drawScope : drawSpectrum;\n const stages: Record<string, EffectStageRun> = { ...errorsRun(errors).stages };\n for (const [id, tap] of taps) {\n stages[id] = { ...stages[id], previews: { out: paint(tap, { width: PREVIEW_SIZE, height: PREVIEW_SIZE }) } };\n }\n return { stages };\n },\n track(run) {\n published.push(run);\n },\n drawn(run) {\n const at = run === undefined ? published.length : published.indexOf(run);\n if (at <= 0) return;\n const keep = new Set(run === undefined ? [] : previewsOf(run));\n closeBitmaps(published.slice(0, at).flatMap(previewsOf).filter((b) => !keep.has(b)));\n published = published.slice(at);\n },\n dispose() {\n disposeTaps();\n closeBitmaps(published.flatMap(previewsOf));\n published = [];\n },\n };\n}\n","import type { AudioEngine, AudioGraph, GraphPatch } from '@weasel-js/audio';\nimport type { EffectPipeline, EffectRun } from '../types';\nimport { audioStageNodes, type AudioSources, type AudioStageNodes } from './nodes';\nimport { createLivePreviews, errorsRun } from './livePreviews';\nimport { diffPlans } from './patches';\nimport { EMPTY_PLAN, livePlan, type LivePlan } from './plan';\nimport type { AudioPreview } from './scope';\n\n/** What a live runner last published: its run, and whether it plays. */\nexport interface LiveAudioRunnerState { run: EffectRun | undefined; playing: boolean }\n\n/** What a live runner plays, and through which engine. */\nexport interface LiveAudioRunnerOptions {\n engine: AudioEngine;\n pipeline: EffectPipeline;\n nodes?: AudioStageNodes;\n sources?: AudioSources;\n /** The engine bus the graph plays through. */\n bus?: string;\n}\n\n/** Plays an audio pipeline through a patchable graph, editing the graph as the pipeline changes. */\nexport interface LiveAudioRunner {\n readonly state: LiveAudioRunnerState;\n /** The graph follows `pipeline` while it plays, or while it does not. */\n setPipeline(pipeline: EffectPipeline): void;\n /** A new buffer replaces each file node. */\n setSources(sources: AudioSources): void;\n /** Unlocks the engine, then starts the graph. */\n play(): Promise<void>;\n pause(): void;\n /** Which stages draw into their `out` preview: a scope, a spectrum, or none. Takes effect on the next `frame`. */\n setPreviews(mode: AudioPreview): void;\n /** Publishes a run with each tapped stage's preview drawn from its tap's current window. */\n frame(): void;\n /** Call after the render that shows `run`: the bitmaps of earlier runs are closed. */\n drawn(run: EffectRun | undefined): void;\n /** A fresh graph holding the current plan, not playing: files start again from 0. */\n reset(): void;\n subscribe(listener: () => void): () => void;\n /** Disposes the graph; the runner does nothing after. The engine is the caller's. */\n dispose(): void;\n}\n\nconst messageOf = (err: unknown): string => (err instanceof Error ? err.message : String(err));\n\nconst idsOf = (p: GraphPatch): string[] =>\n 'id' in p ? [p.id] : [p.from, ...('node' in p.to ? [p.to.node] : [])];\n\n/** The stage a failed structural patch names: the one whose id the error message quotes. */\nconst failingStage = (patches: readonly GraphPatch[], message: string): string | undefined =>\n patches.flatMap(idsOf).find((id) => message.includes(`\"${id}\"`));\n\nconst sameErrors = (a: Readonly<Record<string, string>>, b: Readonly<Record<string, string>>): boolean => {\n const keys = Object.keys(a);\n return keys.length === Object.keys(b).length && keys.every((k) => a[k] === b[k]);\n};\n\n/** Applies the param writes together; when that throws, one by one, to name the stage that failed. */\nfunction applySets(graph: AudioGraph, sets: readonly GraphPatch[], failures: Record<string, string>): void {\n if (sets.length === 0) return;\n try {\n graph.apply(sets);\n } catch (err) {\n console.warn(`@weasel-js/diagram: audio graph edit failed: ${messageOf(err)}`);\n for (const p of sets) {\n try {\n graph.apply([p]);\n } catch (one) {\n if (p.kind === 'set') failures[p.id] = messageOf(one);\n break;\n }\n }\n }\n}\n\n/** A runner over `opts.pipeline` holding a fresh graph on `opts.engine`, not playing. */\nexport function createLiveAudioRunner(opts: LiveAudioRunnerOptions): LiveAudioRunner {\n const { engine, bus } = opts;\n const nodes = opts.nodes ?? audioStageNodes;\n let pipeline = opts.pipeline;\n let sources: AudioSources = opts.sources ?? {};\n let graph: AudioGraph = engine.graph(bus);\n let plan: LivePlan = EMPTY_PLAN;\n let errors: Readonly<Record<string, string>> = {};\n let state: LiveAudioRunnerState = { run: { stages: {} }, playing: false };\n let disposed = false;\n const listeners = new Set<() => void>();\n const previews = createLivePreviews();\n\n const set = (next: Partial<LiveAudioRunnerState>) => {\n const merged = { ...state, ...next };\n if (merged.run === state.run && merged.playing === state.playing) return;\n if (merged.run !== state.run && merged.run !== undefined) previews.track(merged.run);\n state = merged;\n for (const l of [...listeners]) l();\n };\n const publishErrors = (next: Readonly<Record<string, string>>) => {\n if (sameErrors(errors, next)) return;\n errors = next;\n set({ run: errorsRun(next) });\n };\n\n /** Brings the graph from `from` to the plan `pipeline` and `sources` now give. Structure goes first\n * in its own apply: a throw there changed nothing, while a throw from the sets means structure landed. */\n const sync = (from: LivePlan) => {\n const next = livePlan(pipeline, nodes, sources);\n const merged: Record<string, string> = { ...next.errors };\n let adopted = next;\n let structural: GraphPatch[] = [];\n let removed: string[] = [];\n let sets: GraphPatch[] = [];\n try {\n const patches = diffPlans(from, next, (_id, n) => nodes[n.type]!.build(engine.context, n.settings, n.levels));\n structural = patches.filter((p) => p.kind !== 'set');\n sets = patches.filter((p) => p.kind === 'set');\n if (structural.length > 0) graph.apply(structural);\n removed = structural.flatMap((p) => (p.kind === 'remove' ? [p.id] : []));\n } catch (err) {\n const message = messageOf(err);\n const id = failingStage(structural, message);\n if (id !== undefined) merged[id] = message;\n console.warn(`@weasel-js/diagram: audio graph edit failed: ${message}`);\n adopted = from;\n sets = [];\n }\n applySets(graph, sets, merged);\n plan = adopted;\n previews.follow(graph, removed, Object.keys(adopted.nodes));\n publishErrors(merged);\n };\n\n sync(EMPTY_PLAN);\n\n return {\n get state() { return state; },\n setPipeline(next) {\n if (disposed) return;\n pipeline = next;\n sync(plan);\n },\n setSources(next) {\n if (disposed) return;\n sources = next;\n sync(plan);\n },\n async play() {\n if (disposed) return;\n await engine.unlock();\n if (disposed) return;\n graph.start();\n set({ playing: true });\n },\n pause() {\n if (disposed) return;\n graph.stop();\n set({ playing: false });\n },\n setPreviews(mode) {\n if (disposed) return;\n previews.setMode(mode, graph, Object.keys(plan.nodes));\n if (mode === 'off') set({ run: errorsRun(errors) });\n },\n frame() {\n if (disposed) return;\n const run = previews.draw(errors);\n if (run !== undefined) set({ run });\n },\n drawn: previews.drawn,\n reset() {\n if (disposed) return;\n graph.dispose();\n graph = engine.graph(bus);\n previews.restart();\n sync(EMPTY_PLAN);\n set({ playing: false });\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n previews.dispose();\n graph.dispose();\n },\n };\n}\n","import { formatParam, type EffectStageType } from '../stageTypes';\nimport type { EffectParam, EffectParamControl, EffectPort } from '../types';\n\nconst param = (id: string, control: EffectParamControl): EffectParam => ({ id, label: id, value: formatParam(control), control });\n\nconst amount = (value: number, min: number, max: number, step: number, unit?: string): EffectParamControl =>\n ({ kind: 'number', value, min, max, step, ...(unit !== undefined ? { unit } : {}) });\n\nconst choice = (value: string, ...options: string[]): EffectParamControl =>\n ({ kind: 'enum', value, options: options.map((o) => ({ value: o, label: o[0]!.toUpperCase() + o.slice(1) })) });\n\nconst port = (id: string): EffectPort => ({ id, type: 'audio' });\nconst IN = [port('in')];\nconst OUT = [port('out')];\n\n/** Stage types over audio, each with a graph node in `audioStageNodes` except\n * `audio.output`, which is the graph's own output. Every `type` is prefixed\n * because `IMAGE_STAGE_TYPES` already has an `oscillator`. */\nexport const AUDIO_STAGE_TYPES: readonly EffectStageType[] = [\n { type: 'audio.file', title: 'File', kind: 'source', outputs: OUT },\n {\n type: 'audio.oscillator', title: 'Oscillator', kind: 'source', outputs: OUT,\n params: [\n param('wave', choice('sine', 'sine', 'square', 'sawtooth', 'triangle')),\n param('frequency', amount(440, 20, 20000, 1, 'Hz')),\n ],\n },\n {\n type: 'audio.noise', title: 'Noise', kind: 'source', outputs: OUT,\n params: [param('color', choice('white', 'white', 'pink', 'brown'))],\n },\n { type: 'audio.gain', title: 'Gain', inputs: IN, outputs: OUT, params: [param('gain', amount(1, 0, 2, 0.01))] },\n { type: 'audio.pan', title: 'Pan', inputs: IN, outputs: OUT, params: [param('pan', amount(0, -1, 1, 0.01))] },\n {\n type: 'audio.filter', title: 'Filter', inputs: IN, outputs: OUT,\n params: [\n param('type', choice('lowpass', 'lowpass', 'highpass', 'bandpass')),\n param('frequency', amount(1000, 20, 20000, 1, 'Hz')),\n param('Q', amount(1, 0.1, 20, 0.1)),\n ],\n },\n {\n type: 'audio.delay', title: 'Delay', inputs: IN, outputs: OUT,\n params: [\n param('time', amount(300, 0, 2000, 10, 'ms')),\n param('feedback', amount(0.4, 0, 0.95, 0.01)),\n param('mix', amount(0.5, 0, 1, 0.01)),\n ],\n },\n {\n type: 'audio.reverb', title: 'Reverb', inputs: IN, outputs: OUT,\n params: [param('seconds', amount(2, 0.1, 10, 0.1, 's')), param('mix', amount(0.3, 0, 1, 0.01))],\n },\n {\n type: 'audio.compressor', title: 'Compressor', inputs: IN, outputs: OUT,\n params: [param('threshold', amount(-24, -60, 0, 1, 'dB')), param('ratio', amount(4, 1, 20, 0.5))],\n },\n {\n type: 'audio.mix', title: 'Mix', inputs: [port('a'), port('b')], outputs: OUT,\n params: [param('a', amount(1, 0, 2, 0.01)), param('b', amount(1, 0, 2, 0.01))],\n },\n { type: 'audio.output', title: 'Output', kind: 'sink', inputs: IN },\n];\n","import { useEffect, useMemo, useSyncExternalStore } from 'react';\nimport { useVisibleRaf, type VisibleRafOptions } from '@weasel-js/react';\nimport type { EffectPipeline } from '../types';\nimport type { LiveAudioRunner, LiveAudioRunnerState } from './liveRunner';\nimport { errorsRun } from './livePreviews';\nimport { audioStageNodes, type AudioSources, type AudioStageNodes } from './nodes';\nimport { livePlan } from './plan';\nimport type { AudioPreview } from './scope';\n\n/** What `useFollowAudioRunner` keeps a runner following, and how its preview loop is gated. */\nexport interface FollowAudioRunnerOptions extends Pick<VisibleRafOptions, 'target' | 'requestFrame' | 'cancelFrame'> {\n pipeline: EffectPipeline;\n sources?: AudioSources;\n previews: AudioPreview;\n /** The nodes the plan is read with while there is no runner. */\n nodes?: AudioStageNodes;\n}\n\nconst noSubscribe = () => () => {};\n\n/**\n * Keeps a caller-owned `runner` following `pipeline`, `sources` and `previews`, draws its previews every\n * visible frame while it plays, and closes the bitmaps of runs no render shows. While `runner` is null,\n * the run holds the plan's errors, so a stage that cannot play says why before any engine exists.\n */\nexport function useFollowAudioRunner(runner: LiveAudioRunner | null, opts: FollowAudioRunnerOptions): LiveAudioRunnerState {\n const { pipeline, sources, previews, nodes, target, requestFrame, cancelFrame } = opts;\n useEffect(() => { runner?.setPipeline(pipeline); }, [runner, pipeline]);\n useEffect(() => { if (sources !== undefined) runner?.setSources(sources); }, [runner, sources]);\n useEffect(() => { runner?.setPreviews(previews); }, [runner, previews]);\n const live = useSyncExternalStore(runner?.subscribe ?? noSubscribe, () => runner?.state ?? null);\n const planned = useMemo(\n () => (runner !== null ? undefined : errorsRun(livePlan(pipeline, nodes ?? audioStageNodes, sources ?? {}).errors)),\n [runner, pipeline, nodes, sources],\n );\n const playing = live?.playing ?? false;\n\n const loop = useVisibleRaf((_now, self) => {\n if (runner === null || !runner.state.playing || previews === 'off') return;\n runner.frame();\n self.request();\n }, {\n ...(target !== undefined ? { target } : {}),\n ...(requestFrame !== undefined ? { requestFrame } : {}),\n ...(cancelFrame !== undefined ? { cancelFrame } : {}),\n });\n useEffect(() => {\n if (playing && previews !== 'off') loop.request();\n else loop.cancel();\n }, [playing, previews, loop]);\n\n useEffect(() => { runner?.drawn(live?.run); }, [runner, live?.run]);\n return live ?? { run: planned, playing: false };\n}\n","import { useEffect, useState } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { createLiveAudioRunner, type LiveAudioRunner, type LiveAudioRunnerOptions, type LiveAudioRunnerState } from './liveRunner';\nimport { useFollowAudioRunner, type FollowAudioRunnerOptions } from './useFollowAudioRunner';\n\n/** Options for `useLiveAudioRunner`: the runner's, which it follows as they change, and how its preview loop is gated. */\nexport interface UseLiveAudioRunnerOptions\n extends LiveAudioRunnerOptions, Pick<FollowAudioRunnerOptions, 'previews' | 'target' | 'requestFrame' | 'cancelFrame'> {}\n\n/** What `useLiveAudioRunner` returns: the runner's state, and the runner to drive, null until it mounts. */\nexport interface LiveAudioRunnerHandle extends LiveAudioRunnerState {\n runner: LiveAudioRunner | null;\n}\n\n/**\n * A runner made on mount and remade when `engine`, `bus` or `nodes` change, following `pipeline`,\n * `sources` and `previews` through `useFollowAudioRunner`, and disposed on unmount. Before the first\n * mount the runner is null and the run holds the plan's errors. The engine is the caller's.\n */\nexport function useLiveAudioRunner(opts: UseLiveAudioRunnerOptions): LiveAudioRunnerHandle {\n const { engine, bus, nodes } = opts;\n const latest = useLatest(opts);\n const [runner, setRunner] = useState<LiveAudioRunner | null>(null);\n useEffect(() => {\n const { pipeline, sources } = latest.current;\n const made = createLiveAudioRunner({\n engine, pipeline,\n ...(nodes !== undefined ? { nodes } : {}),\n ...(sources !== undefined ? { sources } : {}),\n ...(bus !== undefined ? { bus } : {}),\n });\n // eslint-disable-next-line react-hooks/set-state-in-effect -- publishes the runner this effect creates\n setRunner(made);\n return () => made.dispose();\n }, [engine, bus, nodes, latest]);\n const state = useFollowAudioRunner(runner, opts);\n return { ...state, runner };\n}\n"]}
1
+ {"version":3,"sources":["../src/effect/audio/nodes.ts","../src/effect/audio/plan.ts","../src/effect/audio/patches.ts","../src/effect/audio/scope.ts","../src/effect/audio/livePreviews.ts","../src/effect/audio/liveRunner.ts","../src/effect/audio/stageTypes.ts","../src/effect/audio/useFollowAudioRunner.ts","../src/effect/audio/useLiveAudioRunner.ts"],"names":["levels","param","useEffect"],"mappings":"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","file":"effect-audio.js","sourcesContent":["import {\n compressorNode, createFileSourceNode, createGainNode, createMixNode, createNoiseNode, createOscillatorNode,\n createPanNode, delayNode, filterNode, reverbNode, type GraphNodeDef,\n} from '@weasel-js/audio';\n\n/** What a run supplies to its source stages. */\nexport interface AudioSources { audio?: AudioBuffer }\n\ntype Values = Readonly<Record<string, unknown>>;\n\n/** How one stage type becomes a graph node: its settings, its levels, and the node it builds. */\nexport interface AudioStageNode {\n /** The stage's discrete settings, from its param values and the run's sources. Throws to fail the stage. */\n settings(params: Values, sources: AudioSources): Values;\n /** The ids of its numeric params, each a `params` key of the def `build` returns. */\n levels: readonly string[];\n build(ctx: BaseAudioContext, settings: Values, levels: Readonly<Record<string, number>>): GraphNodeDef;\n}\n/** The graph node of each stage type, by `type`. */\nexport type AudioStageNodes = Readonly<Record<string, AudioStageNode>>;\n\n/** A node whose settings are the named param values; the factory takes them with the levels as one options bag. */\nconst node = (\n settingIds: readonly string[], levels: readonly string[],\n make: (ctx: BaseAudioContext, opts: never) => GraphNodeDef,\n): AudioStageNode => ({\n settings: (params) => Object.fromEntries(settingIds.filter((id) => params[id] !== undefined).map((id) => [id, params[id]])),\n levels,\n build: (ctx, settings, levels) => make(ctx, { ...settings, ...levels } as never),\n});\n\n/** The graph node each stage type builds; `audio.output` has none. */\nexport const audioStageNodes: AudioStageNodes = {\n 'audio.file': {\n settings: (_params, sources) => {\n if (!sources.audio) throw new Error('no source audio');\n return { buffer: sources.audio };\n },\n levels: [],\n build: (ctx, settings) => createFileSourceNode(ctx, { buffer: settings.buffer as AudioBuffer, loop: true }),\n },\n 'audio.oscillator': node(['wave'], ['frequency'], createOscillatorNode),\n 'audio.noise': node(['color'], [], createNoiseNode),\n 'audio.gain': node([], ['gain'], createGainNode),\n 'audio.pan': node([], ['pan'], createPanNode),\n 'audio.filter': node(['type'], ['frequency', 'Q'], filterNode),\n 'audio.delay': node([], ['time', 'feedback', 'mix'], delayNode),\n 'audio.reverb': node(['seconds'], ['mix'], reverbNode),\n 'audio.compressor': node([], ['threshold', 'ratio'], compressorNode),\n 'audio.mix': {\n settings: () => ({}),\n levels: ['a', 'b'],\n build: (ctx, _settings, levels) => {\n const def = createMixNode(ctx, { inputs: ['a', 'b'] });\n for (const id of ['a', 'b']) if (levels[id] !== undefined) def.params[id]!(levels[id], 0);\n return def;\n },\n },\n};\n","import type { GraphTarget } from '@weasel-js/audio';\nimport { uniqueStages } from '../draw';\nimport { runOrder } from '../runner/order';\nimport { paramValues } from '../runner/params';\nimport type { EffectPipeline, EffectStage } from '../types';\nimport type { AudioSources, AudioStageNodes } from './nodes';\n\n/** A node the plan builds: its stage type, its discrete settings and its numeric levels. */\nexport interface PlanNode {\n type: string;\n settings: Readonly<Record<string, unknown>>;\n levels: Readonly<Record<string, number>>;\n}\n/** A connection the plan makes, from a node to another node's port or to the graph's output. */\nexport interface PlanEdge { from: string; to: GraphTarget }\n\n/** The graph an audio pipeline should play: what to build, how it connects, and which stages it left out. */\nexport interface LivePlan {\n nodes: Readonly<Record<string, PlanNode>>;\n /** Sorted by `edgeKey`, so equal plans compare equal. */\n edges: readonly PlanEdge[];\n /** Why a stage is not in `nodes`, by stage id. A stage left out for want of input has none. */\n errors: Readonly<Record<string, string>>;\n}\n\n/** The plan of a graph holding nothing. */\nexport const EMPTY_PLAN: LivePlan = { nodes: {}, edges: [], errors: {} };\n\nconst OUTPUT_TYPE = 'audio.output';\n\n/** One string per edge, the same for equal edges. */\nexport const edgeKey = (e: PlanEdge): string =>\n JSON.stringify([e.from, 'output' in e.to ? null : [e.to.node, e.to.port]]);\n\nfunction levelsOf(levels: readonly string[], params: Readonly<Record<string, unknown>>): Record<string, number> {\n const out: Record<string, number> = {};\n for (const id of levels) {\n const v = params[id];\n if (typeof v === 'number') out[id] = v;\n }\n return out;\n}\n\n/** Compiles the audio stages of `pipeline`; stages of other types are ignored. */\nexport function livePlan(pipeline: EffectPipeline, nodes: AudioStageNodes, sources: AudioSources): LivePlan {\n const stages = new Map<string, EffectStage>();\n for (const s of uniqueStages(pipeline)) {\n if (s.type !== undefined && (Object.hasOwn(nodes, s.type) || s.type === OUTPUT_TYPE)) stages.set(s.id, s);\n }\n const { order, cyclic } = runOrder(pipeline);\n const planNodes: Record<string, PlanNode> = {};\n const errors: Record<string, string> = {};\n for (const id of cyclic) if (stages.has(id)) errors[id] = 'on a feedback loop';\n\n /** The planned nodes whose sound leaves each stage: itself, or what a bypassed stage carries on. */\n const origins = new Map<string, readonly string[]>();\n const edges = new Map<string, PlanEdge>();\n\n for (const id of order) {\n const stage = stages.get(id);\n if (stage === undefined) continue;\n const isOutput = stage.type === OUTPUT_TYPE;\n const bypassed = stage.bypassed === true && !isOutput;\n const firstAudio = (stage.inputs ?? []).find((i) => i.type === 'audio')?.id;\n const fed = pipeline.wires\n .filter((w) => w.to.stage === id && stages.has(w.from.stage) && (!bypassed || w.to.port === firstAudio))\n .flatMap((w) => (origins.get(w.from.stage) ?? []).map((from) => ({ from, port: w.to.port })));\n if ((stage.inputs?.length ?? 0) > 0 && fed.length === 0) continue;\n\n if (bypassed) {\n origins.set(id, [...new Set(fed.map((f) => f.from))]);\n continue;\n }\n if (!isOutput) {\n const entry = nodes[stage.type!]!;\n const params = paramValues(stage);\n try {\n planNodes[id] = { type: stage.type!, settings: entry.settings(params, sources), levels: levelsOf(entry.levels, params) };\n } catch (err) {\n errors[id] = err instanceof Error ? err.message : String(err);\n continue;\n }\n origins.set(id, [id]);\n }\n for (const f of fed) {\n const edge: PlanEdge = { from: f.from, to: isOutput ? { output: true } : { node: id, port: f.port } };\n edges.set(edgeKey(edge), edge);\n }\n }\n return {\n nodes: planNodes,\n edges: [...edges.values()].sort((a, b) => {\n const [ka, kb] = [edgeKey(a), edgeKey(b)];\n return ka < kb ? -1 : ka > kb ? 1 : 0;\n }),\n errors,\n };\n}\n","import type { GraphNodeDef, GraphPatch } from '@weasel-js/audio';\nimport { edgeKey, type LivePlan, type PlanEdge, type PlanNode } from './plan';\n\n/** Makes the def for a node that is added or replaced. */\nexport type BuildNode = (id: string, node: PlanNode) => GraphNodeDef;\n\nfunction sameSettings(a: PlanNode['settings'], b: PlanNode['settings']): boolean {\n const keys = Object.keys(a);\n return keys.length === Object.keys(b).length && keys.every((k) => k in b && Object.is(a[k], b[k]));\n}\n\nconst touches = (e: PlanEdge, ids: ReadonlySet<string>): boolean =>\n ids.has(e.from) || ('node' in e.to && ids.has(e.to.node));\n\n/** The patches that turn the graph `prev` describes into the one `next` describes. */\nexport function diffPlans(prev: LivePlan, next: LivePlan, build: BuildNode): GraphPatch[] {\n const prevIds = Object.keys(prev.nodes).sort();\n const nextIds = Object.keys(next.nodes).sort();\n const gone = new Set<string>(); // removed, or removed to change type: their old edges are dropped\n const fresh = new Set<string>(); // gone, or newly added: every edge touching them in `next` is connected\n const groups = {\n disconnect: [] as GraphPatch[],\n remove: [] as GraphPatch[],\n add: [] as GraphPatch[],\n replace: [] as GraphPatch[],\n set: [] as GraphPatch[],\n connect: [] as GraphPatch[],\n };\n\n for (const id of prevIds) {\n const now = next.nodes[id];\n if (now === undefined || now.type !== prev.nodes[id]!.type) {\n gone.add(id);\n fresh.add(id);\n groups.remove.push({ kind: 'remove', id });\n }\n }\n for (const id of nextIds) {\n const now = next.nodes[id]!;\n const was = prev.nodes[id];\n if (was === undefined || gone.has(id)) {\n fresh.add(id);\n groups.add.push({ kind: 'add', id, def: build(id, now) });\n } else if (!sameSettings(was.settings, now.settings)) {\n groups.replace.push({ kind: 'replace', id, def: build(id, now) });\n } else {\n for (const param of Object.keys(now.levels).sort()) {\n const value = now.levels[param]!;\n if (!Object.is(was.levels[param], value)) groups.set.push({ kind: 'set', id, param, value });\n }\n }\n }\n\n const nextKeys = new Set(next.edges.map(edgeKey));\n const prevKeys = new Set(prev.edges.map(edgeKey));\n for (const e of prev.edges) {\n if (!nextKeys.has(edgeKey(e)) && !touches(e, gone)) {\n groups.disconnect.push({ kind: 'disconnect', from: e.from, to: e.to });\n }\n }\n for (const e of next.edges) {\n if (!prevKeys.has(edgeKey(e)) || touches(e, fresh)) groups.connect.push({ kind: 'connect', from: e.from, to: e.to });\n }\n\n return [\n ...groups.disconnect,\n ...groups.remove,\n ...groups.add,\n ...groups.replace,\n ...groups.set,\n ...groups.connect,\n ];\n}\n","import type { AnalyserTap } from '@weasel-js/audio';\nimport { PREVIEW_DENSITY } from '../draw';\n\n/** What a stage's preview slot shows while its graph plays. */\nexport type AudioPreview = 'off' | 'scope' | 'spectrum';\n\n// Neutral enough to read on both the light and the dark theme; no image preview names a foreground to match.\nconst INK = '#8a8f98';\nconst BANDS = 32;\nconst LINE = 1.5;\n\ntype Size = { width: number; height: number };\n\nfunction canvasOf(size: Size) {\n const canvas = new OffscreenCanvas(\n Math.max(1, Math.round(size.width * PREVIEW_DENSITY)),\n Math.max(1, Math.round(size.height * PREVIEW_DENSITY)),\n );\n return { canvas, g: canvas.getContext('2d')!, w: canvas.width, h: canvas.height };\n}\n\n/** The waveform as a line across the bitmap, silence at mid-height. */\nexport function drawScope(tap: AnalyserTap, size: Size): ImageBitmap {\n const { canvas, g, w, h } = canvasOf(size);\n const wave = tap.waveform();\n g.strokeStyle = INK;\n g.lineWidth = LINE * PREVIEW_DENSITY;\n g.lineJoin = 'round';\n g.beginPath();\n for (let x = 0; x < w; x += 1) {\n const v = wave[Math.min(wave.length - 1, Math.floor((x / Math.max(1, w - 1)) * (wave.length - 1)))]! / 255;\n const y = h - v * h;\n if (x === 0) g.moveTo(x, y);\n else g.lineTo(x, y);\n }\n g.stroke();\n return canvas.transferToImageBitmap();\n}\n\n/** The spectrum as filled bars rising from the bottom, low frequencies on the left. */\nexport function drawSpectrum(tap: AnalyserTap, size: Size): ImageBitmap {\n const { canvas, g, w, h } = canvasOf(size);\n const bands = tap.bands(BANDS);\n const slot = w / BANDS;\n g.fillStyle = INK;\n for (let i = 0; i < BANDS; i += 1) {\n const bar = bands[i]! * h;\n g.fillRect(i * slot, h - bar, slot * 0.8, bar);\n }\n return canvas.transferToImageBitmap();\n}\n","import type { AnalyserTap, AudioGraph } from '@weasel-js/audio';\nimport { PREVIEW_SIZE } from '../draw';\nimport { closeBitmaps, previewsOf } from '../runner/previews';\nimport type { EffectRun, EffectStageRun } from '../types';\nimport { drawScope, drawSpectrum, type AudioPreview } from './scope';\n\n/** The analyser taps behind a live runner's previews, and the runs it has drawn them into. */\nexport interface LivePreviews {\n mode(): AudioPreview;\n setMode(mode: AudioPreview, graph: AudioGraph, ids: readonly string[]): void;\n /** After an edit: forgets taps of `removed` nodes (the graph disposed them) and taps any planned node without one. */\n follow(graph: AudioGraph, removed: readonly string[], planned: readonly string[]): void;\n /** Forgets every tap: they went with the graph they were on. */\n restart(): void;\n /** A run with the previews drawn from every tap, over `errors`; undefined when nothing is tapped. */\n draw(errors: Readonly<Record<string, string>>): EffectRun | undefined;\n /** Notes a run the runner published, so `drawn` can tell which came before it. */\n track(run: EffectRun): void;\n drawn(run: EffectRun | undefined): void;\n /** Closes every bitmap still held and disposes the taps. */\n dispose(): void;\n}\n\n/** A run holding only `errors`, by stage id. */\nexport const errorsRun = (errors: Readonly<Record<string, string>>): EffectRun =>\n ({ stages: Object.fromEntries(Object.entries(errors).map(([id, error]) => [id, { error }])) });\n\nexport function createLivePreviews(): LivePreviews {\n let mode: AudioPreview = 'off';\n let taps = new Map<string, AnalyserTap>();\n // Runs published and not yet known to be off screen, oldest first.\n let published: EffectRun[] = [];\n\n const tapAll = (graph: AudioGraph, ids: readonly string[]) => {\n for (const id of ids) if (!taps.has(id)) taps.set(id, graph.tap(id));\n };\n const disposeTaps = () => {\n for (const t of taps.values()) t.dispose();\n taps = new Map();\n };\n\n return {\n mode: () => mode,\n setMode(next, graph, ids) {\n mode = next;\n if (next === 'off') disposeTaps();\n else tapAll(graph, ids);\n },\n follow(graph, removed, planned) {\n if (mode === 'off') return;\n for (const id of removed) taps.delete(id);\n const live = new Set(planned);\n for (const id of [...taps.keys()]) if (!live.has(id)) taps.delete(id);\n tapAll(graph, planned);\n },\n restart() {\n taps = new Map();\n },\n draw(errors) {\n if (mode === 'off' || taps.size === 0) return undefined;\n const paint = mode === 'scope' ? drawScope : drawSpectrum;\n const stages: Record<string, EffectStageRun> = { ...errorsRun(errors).stages };\n for (const [id, tap] of taps) {\n stages[id] = { ...stages[id], previews: { out: paint(tap, { width: PREVIEW_SIZE, height: PREVIEW_SIZE }) } };\n }\n return { stages };\n },\n track(run) {\n published.push(run);\n },\n drawn(run) {\n const at = run === undefined ? published.length : published.indexOf(run);\n if (at <= 0) return;\n const keep = new Set(run === undefined ? [] : previewsOf(run));\n closeBitmaps(published.slice(0, at).flatMap(previewsOf).filter((b) => !keep.has(b)));\n published = published.slice(at);\n },\n dispose() {\n disposeTaps();\n closeBitmaps(published.flatMap(previewsOf));\n published = [];\n },\n };\n}\n","import type { AudioEngine, AudioGraph, GraphPatch } from '@weasel-js/audio';\nimport type { EffectPipeline, EffectRun } from '../types';\nimport { audioStageNodes, type AudioSources, type AudioStageNodes } from './nodes';\nimport { createLivePreviews, errorsRun } from './livePreviews';\nimport { diffPlans } from './patches';\nimport { EMPTY_PLAN, livePlan, type LivePlan } from './plan';\nimport type { AudioPreview } from './scope';\n\n/** What a live runner last published: its run, and whether it plays. */\nexport interface LiveAudioRunnerState { run: EffectRun | undefined; playing: boolean }\n\n/** What a live runner plays, and through which engine. */\nexport interface LiveAudioRunnerOptions {\n engine: AudioEngine;\n pipeline: EffectPipeline;\n nodes?: AudioStageNodes;\n sources?: AudioSources;\n /** The engine bus the graph plays through. */\n bus?: string;\n}\n\n/** Plays an audio pipeline through a patchable graph, editing the graph as the pipeline changes. */\nexport interface LiveAudioRunner {\n readonly state: LiveAudioRunnerState;\n /** The graph follows `pipeline` while it plays, or while it does not. */\n setPipeline(pipeline: EffectPipeline): void;\n /** A new buffer replaces each file node. */\n setSources(sources: AudioSources): void;\n /** Unlocks the engine, then starts the graph. */\n play(): Promise<void>;\n pause(): void;\n /** Which stages draw into their `out` preview: a scope, a spectrum, or none. Takes effect on the next `frame`. */\n setPreviews(mode: AudioPreview): void;\n /** Publishes a run with each tapped stage's preview drawn from its tap's current window. */\n frame(): void;\n /** Call after the render that shows `run`: the bitmaps of earlier runs are closed. */\n drawn(run: EffectRun | undefined): void;\n /** A fresh graph holding the current plan, not playing: files start again from 0. */\n reset(): void;\n subscribe(listener: () => void): () => void;\n /** Disposes the graph; the runner does nothing after. The engine is the caller's. */\n dispose(): void;\n}\n\nconst messageOf = (err: unknown): string => (err instanceof Error ? err.message : String(err));\n\nconst idsOf = (p: GraphPatch): string[] =>\n 'id' in p ? [p.id] : [p.from, ...('node' in p.to ? [p.to.node] : [])];\n\n/** The stage a failed structural patch names: the one whose id the error message quotes. */\nconst failingStage = (patches: readonly GraphPatch[], message: string): string | undefined =>\n patches.flatMap(idsOf).find((id) => message.includes(`\"${id}\"`));\n\nconst sameErrors = (a: Readonly<Record<string, string>>, b: Readonly<Record<string, string>>): boolean => {\n const keys = Object.keys(a);\n return keys.length === Object.keys(b).length && keys.every((k) => a[k] === b[k]);\n};\n\n/** Applies the param writes together; when that throws, one by one, to name the stage that failed. */\nfunction applySets(graph: AudioGraph, sets: readonly GraphPatch[], failures: Record<string, string>): void {\n if (sets.length === 0) return;\n try {\n graph.apply(sets);\n } catch (err) {\n console.warn(`@weasel-js/diagram: audio graph edit failed: ${messageOf(err)}`);\n for (const p of sets) {\n try {\n graph.apply([p]);\n } catch (one) {\n if (p.kind === 'set') failures[p.id] = messageOf(one);\n break;\n }\n }\n }\n}\n\n/** A runner over `opts.pipeline` holding a fresh graph on `opts.engine`, not playing. */\nexport function createLiveAudioRunner(opts: LiveAudioRunnerOptions): LiveAudioRunner {\n const { engine, bus } = opts;\n const nodes = opts.nodes ?? audioStageNodes;\n let pipeline = opts.pipeline;\n let sources: AudioSources = opts.sources ?? {};\n let graph: AudioGraph = engine.graph(bus);\n let plan: LivePlan = EMPTY_PLAN;\n let errors: Readonly<Record<string, string>> = {};\n let state: LiveAudioRunnerState = { run: { stages: {} }, playing: false };\n let disposed = false;\n const listeners = new Set<() => void>();\n const previews = createLivePreviews();\n\n const set = (next: Partial<LiveAudioRunnerState>) => {\n const merged = { ...state, ...next };\n if (merged.run === state.run && merged.playing === state.playing) return;\n if (merged.run !== state.run && merged.run !== undefined) previews.track(merged.run);\n state = merged;\n for (const l of [...listeners]) l();\n };\n const publishErrors = (next: Readonly<Record<string, string>>) => {\n if (sameErrors(errors, next)) return;\n errors = next;\n set({ run: errorsRun(next) });\n };\n\n /** Brings the graph from `from` to the plan `pipeline` and `sources` now give. Structure goes first\n * in its own apply: a throw there changed nothing, while a throw from the sets means structure landed. */\n const sync = (from: LivePlan) => {\n const next = livePlan(pipeline, nodes, sources);\n const merged: Record<string, string> = { ...next.errors };\n let adopted = next;\n let structural: GraphPatch[] = [];\n let removed: string[] = [];\n let sets: GraphPatch[] = [];\n try {\n const patches = diffPlans(from, next, (_id, n) => nodes[n.type]!.build(engine.context, n.settings, n.levels));\n structural = patches.filter((p) => p.kind !== 'set');\n sets = patches.filter((p) => p.kind === 'set');\n if (structural.length > 0) graph.apply(structural);\n removed = structural.flatMap((p) => (p.kind === 'remove' ? [p.id] : []));\n } catch (err) {\n const message = messageOf(err);\n const id = failingStage(structural, message);\n if (id !== undefined) merged[id] = message;\n console.warn(`@weasel-js/diagram: audio graph edit failed: ${message}`);\n adopted = from;\n sets = [];\n }\n applySets(graph, sets, merged);\n plan = adopted;\n previews.follow(graph, removed, Object.keys(adopted.nodes));\n publishErrors(merged);\n };\n\n sync(EMPTY_PLAN);\n\n return {\n get state() { return state; },\n setPipeline(next) {\n if (disposed) return;\n pipeline = next;\n sync(plan);\n },\n setSources(next) {\n if (disposed) return;\n sources = next;\n sync(plan);\n },\n async play() {\n if (disposed) return;\n await engine.unlock();\n if (disposed) return;\n graph.start();\n set({ playing: true });\n },\n pause() {\n if (disposed) return;\n graph.stop();\n set({ playing: false });\n },\n setPreviews(mode) {\n if (disposed) return;\n previews.setMode(mode, graph, Object.keys(plan.nodes));\n if (mode === 'off') set({ run: errorsRun(errors) });\n },\n frame() {\n if (disposed) return;\n const run = previews.draw(errors);\n if (run !== undefined) set({ run });\n },\n drawn: previews.drawn,\n reset() {\n if (disposed) return;\n graph.dispose();\n graph = engine.graph(bus);\n previews.restart();\n sync(EMPTY_PLAN);\n set({ playing: false });\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n previews.dispose();\n graph.dispose();\n },\n };\n}\n","import { formatParam, type EffectStageType } from '../stageTypes';\nimport type { EffectParam, EffectParamControl, EffectPort } from '../types';\n\nconst param = (id: string, control: EffectParamControl): EffectParam => ({ id, label: id, value: formatParam(control), control });\n\nconst amount = (value: number, min: number, max: number, step: number, unit?: string): EffectParamControl =>\n ({ kind: 'number', value, min, max, step, ...(unit !== undefined ? { unit } : {}) });\n\nconst choice = (value: string, ...options: string[]): EffectParamControl =>\n ({ kind: 'enum', value, options: options.map((o) => ({ value: o, label: o[0]!.toUpperCase() + o.slice(1) })) });\n\nconst port = (id: string): EffectPort => ({ id, type: 'audio' });\nconst IN = [port('in')];\nconst OUT = [port('out')];\n\n/** Stage types over audio, each with a graph node in `audioStageNodes` except\n * `audio.output`, which is the graph's own output. Every `type` is prefixed\n * because `IMAGE_STAGE_TYPES` already has an `oscillator`. */\nexport const AUDIO_STAGE_TYPES: readonly EffectStageType[] = [\n { type: 'audio.file', title: 'File', kind: 'source', outputs: OUT },\n {\n type: 'audio.oscillator', title: 'Oscillator', kind: 'source', outputs: OUT,\n params: [\n param('wave', choice('sine', 'sine', 'square', 'sawtooth', 'triangle')),\n param('frequency', amount(440, 20, 20000, 1, 'Hz')),\n ],\n },\n {\n type: 'audio.noise', title: 'Noise', kind: 'source', outputs: OUT,\n params: [param('color', choice('white', 'white', 'pink', 'brown'))],\n },\n { type: 'audio.gain', title: 'Gain', inputs: IN, outputs: OUT, params: [param('gain', amount(1, 0, 2, 0.01))] },\n { type: 'audio.pan', title: 'Pan', inputs: IN, outputs: OUT, params: [param('pan', amount(0, -1, 1, 0.01))] },\n {\n type: 'audio.filter', title: 'Filter', inputs: IN, outputs: OUT,\n params: [\n param('type', choice('lowpass', 'lowpass', 'highpass', 'bandpass')),\n param('frequency', amount(1000, 20, 20000, 1, 'Hz')),\n param('Q', amount(1, 0.1, 20, 0.1)),\n ],\n },\n {\n type: 'audio.delay', title: 'Delay', inputs: IN, outputs: OUT,\n params: [\n param('time', amount(300, 0, 2000, 10, 'ms')),\n param('feedback', amount(0.4, 0, 0.95, 0.01)),\n param('mix', amount(0.5, 0, 1, 0.01)),\n ],\n },\n {\n type: 'audio.reverb', title: 'Reverb', inputs: IN, outputs: OUT,\n params: [param('seconds', amount(2, 0.1, 10, 0.1, 's')), param('mix', amount(0.3, 0, 1, 0.01))],\n },\n {\n type: 'audio.compressor', title: 'Compressor', inputs: IN, outputs: OUT,\n params: [param('threshold', amount(-24, -60, 0, 1, 'dB')), param('ratio', amount(4, 1, 20, 0.5))],\n },\n {\n type: 'audio.mix', title: 'Mix', inputs: [port('a'), port('b')], outputs: OUT,\n params: [param('a', amount(1, 0, 2, 0.01)), param('b', amount(1, 0, 2, 0.01))],\n },\n { type: 'audio.output', title: 'Output', kind: 'sink', inputs: IN },\n];\n","import { useEffect, useMemo, useSyncExternalStore } from 'react';\nimport { useVisibleRaf, type VisibleRafOptions } from '@weasel-js/react';\nimport type { EffectPipeline } from '../types';\nimport type { LiveAudioRunner, LiveAudioRunnerState } from './liveRunner';\nimport { errorsRun } from './livePreviews';\nimport { audioStageNodes, type AudioSources, type AudioStageNodes } from './nodes';\nimport { livePlan } from './plan';\nimport type { AudioPreview } from './scope';\n\n/** What `useFollowAudioRunner` keeps a runner following, and how its preview loop is gated. */\nexport interface FollowAudioRunnerOptions extends Pick<VisibleRafOptions, 'target' | 'requestFrame' | 'cancelFrame'> {\n pipeline: EffectPipeline;\n sources?: AudioSources;\n previews: AudioPreview;\n /** The nodes the plan is read with while there is no runner. */\n nodes?: AudioStageNodes;\n}\n\nconst noSubscribe = () => () => {};\n\n/**\n * Keeps a caller-owned `runner` following `pipeline`, `sources` and `previews`, draws its previews every\n * visible frame while it plays, and closes the bitmaps of runs no render shows. While `runner` is null,\n * the run holds the plan's errors, so a stage that cannot play says why before any engine exists.\n */\nexport function useFollowAudioRunner(runner: LiveAudioRunner | null, opts: FollowAudioRunnerOptions): LiveAudioRunnerState {\n const { pipeline, sources, previews, nodes, target, requestFrame, cancelFrame } = opts;\n useEffect(() => { runner?.setPipeline(pipeline); }, [runner, pipeline]);\n useEffect(() => { if (sources !== undefined) runner?.setSources(sources); }, [runner, sources]);\n useEffect(() => { runner?.setPreviews(previews); }, [runner, previews]);\n const live = useSyncExternalStore(runner?.subscribe ?? noSubscribe, () => runner?.state ?? null);\n const planned = useMemo(\n () => (runner !== null ? undefined : errorsRun(livePlan(pipeline, nodes ?? audioStageNodes, sources ?? {}).errors)),\n [runner, pipeline, nodes, sources],\n );\n const playing = live?.playing ?? false;\n\n const loop = useVisibleRaf((_now, self) => {\n if (runner === null || !runner.state.playing || previews === 'off') return;\n runner.frame();\n self.request();\n }, {\n ...(target !== undefined ? { target } : {}),\n ...(requestFrame !== undefined ? { requestFrame } : {}),\n ...(cancelFrame !== undefined ? { cancelFrame } : {}),\n });\n useEffect(() => {\n if (playing && previews !== 'off') loop.request();\n else loop.cancel();\n }, [playing, previews, loop]);\n\n useEffect(() => { runner?.drawn(live?.run); }, [runner, live?.run]);\n return live ?? { run: planned, playing: false };\n}\n","import { useEffect, useState } from 'react';\nimport { useLatest, useStableByContent } from '@weasel-js/react';\nimport { createLiveAudioRunner, type LiveAudioRunner, type LiveAudioRunnerOptions, type LiveAudioRunnerState } from './liveRunner';\nimport type { AudioStageNodes } from './nodes';\nimport { useFollowAudioRunner, type FollowAudioRunnerOptions } from './useFollowAudioRunner';\n\n/** Options for `useLiveAudioRunner`: the runner's, which it follows as they change, and how its preview loop is gated. */\nexport interface UseLiveAudioRunnerOptions\n extends LiveAudioRunnerOptions, Pick<FollowAudioRunnerOptions, 'previews' | 'target' | 'requestFrame' | 'cancelFrame'> {}\n\n/** What `useLiveAudioRunner` returns: the runner's state, and the runner to drive, null until it mounts. */\nexport interface LiveAudioRunnerHandle extends LiveAudioRunnerState {\n runner: LiveAudioRunner | null;\n}\n\n/**\n * A runner made on mount and remade when `engine`, `bus` or `nodes` change, following `pipeline`,\n * `sources` and `previews` through `useFollowAudioRunner`, and disposed on unmount. Before the first\n * mount the runner is null and the run holds the plan's errors. The engine is the caller's. `nodes`\n * counts as changed only when a type is added, dropped or given a different node, so it can be built in render.\n */\nexport function useLiveAudioRunner(opts: UseLiveAudioRunnerOptions): LiveAudioRunnerHandle {\n const { engine, bus } = opts;\n const nodes = useStableByContent(opts.nodes, sameNodes);\n const latest = useLatest(opts);\n const [runner, setRunner] = useState<LiveAudioRunner | null>(null);\n useEffect(() => {\n const { pipeline, sources } = latest.current;\n const made = createLiveAudioRunner({\n engine, pipeline,\n ...(nodes !== undefined ? { nodes } : {}),\n ...(sources !== undefined ? { sources } : {}),\n ...(bus !== undefined ? { bus } : {}),\n });\n // eslint-disable-next-line react-hooks/set-state-in-effect -- publishes the runner this effect creates\n setRunner(made);\n return () => made.dispose();\n }, [engine, bus, nodes, latest]);\n const state = useFollowAudioRunner(runner, { ...opts, ...(nodes !== undefined ? { nodes } : {}) });\n return { ...state, runner };\n}\n\nfunction sameNodes(a: AudioStageNodes | undefined, b: AudioStageNodes | undefined): boolean {\n if (a === undefined || b === undefined) return a === b;\n const keys = Object.keys(a);\n return keys.length === Object.keys(b).length && keys.every((k) => Object.hasOwn(b, k) && a[k] === b[k]);\n}\n"]}
package/dist/effect.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { c as EffectDoc, E as EffectPipeline, d as EffectWire, e as EffectStage, f as EffectPort, g as EffectGroup, a as EffectRun, b as EffectStageType, L as LookRoutes, h as EffectParamControl, i as EffectBox } from './stageTypes-DvnR8cKQ.js';
2
2
  export { j as EffectParam, k as EffectPlaces, l as EffectStageRun, m as EffectType, n as LookRoute, o as formatParam, s as stageFromType } from './stageTypes-DvnR8cKQ.js';
3
- import { D as DiagramTheme, a as DiagramData, b as DiagramSceneOptions, N as NodeStyle, c as DataEdge, E as EdgeStyle, d as DataNode, e as DiagramRouter, f as DiagramSpec } from './dataTypes-B-iEwKZp.js';
4
- import { a as Row, M as MeasureRowText } from './types-BbHunLXm.js';
3
+ import { D as DiagramTheme, a as DiagramData, b as DiagramSceneOptions, N as NodeStyle, c as DataEdge, E as EdgeStyle, d as DataNode, e as DiagramRouter, f as DiagramSpec } from './dataTypes-DHdkzCL8.js';
4
+ import { a as Row, M as MeasureRowText } from './types-M_ccNAlk.js';
5
5
  import * as react from 'react';
6
6
  import { Paint } from '@weasel-js/core';
7
7
  import { Vec2 } from '@weasel-js/core/math';
package/dist/effect.js CHANGED
@@ -1,9 +1,9 @@
1
- import { DiagramView, reorderContribution, ANYWHERE, isBodyEnd, sequenceSlots } from './chunk-CI3I3I6T.js';
2
- import './chunk-T6DQT553.js';
3
- import { stageFromType, LOOK_THEME, drawableWires, uniqueStages, shownPorts, valueRowId, NO_VALUE, previewRowId, formatParam, stageStyle, PROBLEM_COLOR, typeColors, kindOf, boxNode, portOn, wireStyle, isControl, wireEdge, sceneStyles, uniqueGroups, wireEdges, exitLabel, splitProblem, checkPipeline, PREVIEW_DENSITY, runOrder, PREVIEW_SIZE, closeBitmaps, previewsOf, paramValues } from './chunk-QKSWZEJH.js';
4
- export { LOOK_THEME, NO_VALUE, PREVIEW_SIZE, PROBLEM_COLOR, checkPipeline, drawableWires, exitLabel, formatParam, isControl, kindOf, portOn, previewRowId, runOrder, shownPorts, stageFromType, stageRows, stageStyle, typeColors, uniqueGroups, uniqueStages, valueRowId, wireEdges, wireStyle } from './chunk-QKSWZEJH.js';
5
- import { diagramScene, diagramPages, edgeIdOf, titleIdOf, groupLabelIdOf, nestGroups, LABEL_PLACEMENT, groupMinWidth, EDGE_DERIVE_PATH } from './chunk-43LDZ6L4.js';
6
- import { portOf, DEFAULT_GROUP_INSET, SIDE_TRACK_GAP, widenForMinWidth, portSitesOf, labelCenter, insetOf, rankGaps } from './chunk-IM6DHWZO.js';
1
+ import { DiagramView, reorderContribution, ANYWHERE, isBodyEnd, sequenceSlots } from './chunk-DYDX6EJC.js';
2
+ import './chunk-GA4BX7SH.js';
3
+ import { stageFromType, LOOK_THEME, drawableWires, uniqueStages, shownPorts, valueRowId, NO_VALUE, previewRowId, formatParam, stageStyle, PROBLEM_COLOR, typeColors, kindOf, boxNode, portOn, wireStyle, isControl, wireEdge, sceneStyles, uniqueGroups, wireEdges, exitLabel, splitProblem, checkPipeline, PREVIEW_DENSITY, runOrder, PREVIEW_SIZE, closeBitmaps, previewsOf, paramValues } from './chunk-5GIP2LA6.js';
4
+ export { LOOK_THEME, NO_VALUE, PREVIEW_SIZE, PROBLEM_COLOR, checkPipeline, drawableWires, exitLabel, formatParam, isControl, kindOf, portOn, previewRowId, runOrder, shownPorts, stageFromType, stageRows, stageStyle, typeColors, uniqueGroups, uniqueStages, valueRowId, wireEdges, wireStyle } from './chunk-5GIP2LA6.js';
5
+ import { diagramScene, diagramPages, edgeIdOf, titleIdOf, groupLabelIdOf, nestGroups, groupMinWidth, LABEL_PLACEMENT, EDGE_DERIVE_PATH } from './chunk-2SYY4W3B.js';
6
+ import { portOf, insetOf, diagramNodeOf, DEFAULT_GROUP_INSET, SIDE_TRACK_GAP, widenForMinWidth, rankGaps, portSitesOf, labelCenter } from './chunk-R2XB6D32.js';
7
7
  import { polygonFromPoints } from '@weasel-js/core/math';
8
8
  import { forwardRef, useMemo, useRef, useState, useImperativeHandle, useEffect, useCallback, useSyncExternalStore } from 'react';
9
9
  import { useLatest, bitmapSrc, ActionDisabledReason, pointAlongPath } from '@weasel-js/core';
@@ -1391,8 +1391,20 @@ function clearLabel(path, size, offset, keepOut) {
1391
1391
  return void 0;
1392
1392
  }
1393
1393
  var inkOf = (id, specs) => specs.filter((s) => s.id === id || s.parent === id || String(s.id).startsWith(`${id}/mark:`)).map((s) => s.pose);
1394
+ function walledIn(grid, walls) {
1395
+ if (walls.length === 0) return grid;
1396
+ const over = (c) => walls.filter((w) => w.first <= c && c <= w.last);
1397
+ return {
1398
+ edges: grid.edges,
1399
+ ink: grid.ink.map((boxes, c) => boxes.concat(over(c).map((w) => w.box))),
1400
+ columns: grid.columns.map(([lo, hi], c) => over(c).reduce(([l, h], { box, first, last }) => [
1401
+ c === first ? Math.min(l, box.x - CLEAR) : l,
1402
+ c === last ? Math.max(h, box.x + box.width + CLEAR) : h
1403
+ ], [lo, hi]))
1404
+ };
1405
+ }
1394
1406
  function routeWires(wires, nodes, laid) {
1395
- const specs = diagramScene({ nodes, edges: wires.map((w) => w.edge) }, {
1407
+ const specs = diagramScene({ nodes, edges: wires.map((w) => w.edge), ...laid.groups !== void 0 ? { groups: laid.groups } : {} }, {
1396
1408
  layout: "none",
1397
1409
  router: laid.router,
1398
1410
  ...laid.measure !== void 0 ? { measure: laid.measure } : {}
@@ -1405,7 +1417,13 @@ function routeWires(wires, nodes, laid) {
1405
1417
  const [site, ...sites] = portSitesOf({ id: stage, data: s.data }, s.pose, port);
1406
1418
  return { column: laid.column.get(stage), point: site?.point ?? { x: 0, y: 0 }, normal: site?.normal ?? null, sites };
1407
1419
  };
1408
- const courses = wires.map(({ edge }) => edge.from === edge.to ? void 0 : laneCourse(grid, end(edge.from, edge.fromPort), end(edge.to, edge.toPort)));
1420
+ const walls = nestGroups(laid.groups ?? [], (id) => ink.has(id)).flatMap((g) => {
1421
+ const box = spec.get(g.id)?.pose;
1422
+ const at = g.members.flatMap((m) => laid.column.has(m) ? [laid.column.get(m)] : []);
1423
+ return box === void 0 || at.length === 0 ? [] : [{ box, first: Math.min(...at), last: Math.max(...at), holds: new Set(g.members) }];
1424
+ });
1425
+ const grids = wires.map(({ edge }) => walledIn(grid, walls.filter((w) => !w.holds.has(edge.from) && !w.holds.has(edge.to))));
1426
+ const courses = wires.map(({ edge }, w) => edge.from === edge.to ? void 0 : laneCourse(grids[w], end(edge.from, edge.fromPort), end(edge.to, edge.toPort)));
1409
1427
  const { stretches, tracks } = assignTracks(courses);
1410
1428
  const [top, bottom] = [grid.edges[0] ?? 0, grid.edges[grid.edges.length - 1] ?? 0];
1411
1429
  const keepOut = [...ink.values()].flat().concat({ x: -1e9, y: top - 1e9, width: 2e9, height: 1e9 }, { x: -1e9, y: bottom, width: 2e9, height: 1e9 });
@@ -1416,7 +1434,7 @@ function routeWires(wires, nodes, laid) {
1416
1434
  const s = stretches[w].find((t) => t.edge === at.edge && t.lo <= column && column <= t.hi);
1417
1435
  return trackY(grid, at.edge, s.track, tracks.get(at.edge));
1418
1436
  });
1419
- const waypoints = course === void 0 ? void 0 : waypointsOf(grid, course, ys);
1437
+ const waypoints = course === void 0 ? void 0 : waypointsOf(grids[w], course, ys);
1420
1438
  return { waypoints, path: routeOf(spec.get(edge.from), edge.fromPort, spec.get(edge.to), edge.toPort, laid.router, waypoints) };
1421
1439
  });
1422
1440
  const segments = routes.map(({ path }) => {
@@ -1483,6 +1501,9 @@ function controlSideOf(stage, pipeline, lane) {
1483
1501
  function sizesOf(nodes, groups, measure) {
1484
1502
  const specs = diagramScene({ nodes, edges: [], groups }, { layout: "none", ...measure !== void 0 ? { measure } : {} });
1485
1503
  const pose = new Map(specs.map((s) => [s.id, s.pose]));
1504
+ const spec = new Map(specs.map((s) => [s.id, s]));
1505
+ const nested = nestGroups(groups, (id) => nodes.some((n) => n.id === id)).map((g) => ({ members: g.members, inset: insetOf(diagramNodeOf({ id: g.id, kind: "leaf", data: spec.get(g.id)?.data })?.group?.inset) }));
1506
+ const boxed = (id, side) => nested.reduce((sum, g) => sum + (g.members.includes(id) ? g.inset[side] : 0), 0);
1486
1507
  const titles = new Map(groups.flatMap((g) => {
1487
1508
  const title2 = pose.get(groupLabelIdOf(g.id));
1488
1509
  return title2 === void 0 ? [] : [[g.id, title2.width]];
@@ -1492,9 +1513,9 @@ function sizesOf(nodes, groups, measure) {
1492
1513
  const ink = inkOf(n.id, specs);
1493
1514
  const over = {
1494
1515
  left: box.x - Math.min(...ink.map((b) => b.x)),
1495
- top: box.y - Math.min(...ink.map((b) => b.y)),
1516
+ top: box.y - Math.min(...ink.map((b) => b.y)) + boxed(n.id, "top"),
1496
1517
  right: Math.max(...ink.map((b) => b.x + b.width)) - box.x - box.width,
1497
- bottom: Math.max(...ink.map((b) => b.y + b.height)) - box.y - box.height
1518
+ bottom: Math.max(...ink.map((b) => b.y + b.height)) - box.y - box.height + boxed(n.id, "bottom")
1498
1519
  };
1499
1520
  return [n.id, { box, over }];
1500
1521
  }));
@@ -1585,13 +1606,14 @@ var lanes = (pipeline, options = {}) => {
1585
1606
  const wires = wireEdges(pipeline, color);
1586
1607
  let insets = insetsFor(rows.length + 1, /* @__PURE__ */ new Map());
1587
1608
  let laid = place2(plan, insets);
1588
- let routed = routeWires(wires, laid.nodes, { grid: laid, column, router, measure: options.measure });
1609
+ const route = (at) => routeWires(wires, at.nodes, { grid: at, column, router, measure: options.measure, groups });
1610
+ let routed = route(laid);
1589
1611
  for (let round = 0; round < 4; round++) {
1590
1612
  const need2 = insetsFor(rows.length + 1, routed.tracks);
1591
1613
  if (need2.every((n, k) => n <= insets[k])) break;
1592
1614
  insets = need2.map((n, k) => Math.max(n, insets[k]));
1593
1615
  laid = place2(plan, insets);
1594
- routed = routeWires(wires, laid.nodes, { grid: laid, column, router, measure: options.measure });
1616
+ routed = route(laid);
1595
1617
  }
1596
1618
  const { columns, tops, heights } = laid;
1597
1619
  const right = columns.length === 0 ? plan.start : laid.end + MARGIN;
@@ -2001,7 +2023,11 @@ function renameGroupContribution(now, rename) {
2001
2023
  }
2002
2024
  }],
2003
2025
  // Empty space included: an unlabeled group's grip is padding.
2004
- bindings: [{ spec: { kind: "doubleClick", target: { kindOf: ANYWHERE } }, actionId: RENAME_GROUP_ACTION_ID }]
2026
+ bindings: [{
2027
+ spec: { kind: "doubleClick", target: { kindOf: ANYWHERE } },
2028
+ actionId: RENAME_GROUP_ACTION_ID,
2029
+ opts: { id: `${RENAME_GROUP_ACTION_ID}.doubleClick` }
2030
+ }]
2005
2031
  };
2006
2032
  }
2007
2033