flowsvg 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +54 -1
  2. package/PATTERNS.md +71 -4
  3. package/README.md +148 -438
  4. package/README.zh-CN.md +148 -438
  5. package/dist/adapters/react.d.ts +55 -0
  6. package/dist/adapters/react.js +138 -0
  7. package/dist/adapters/vue.d.ts +158 -0
  8. package/dist/adapters/vue.js +177 -0
  9. package/dist/adapters/web-component.d.ts +111 -0
  10. package/dist/adapters/web-component.js +425 -0
  11. package/dist/{player-controls.d.ts → browser/controls.d.ts} +7 -3
  12. package/dist/{player-controls.js → browser/controls.js} +23 -31
  13. package/dist/browser/export-controls.d.ts +32 -0
  14. package/dist/browser/export-controls.js +151 -0
  15. package/dist/browser/player.d.ts +77 -0
  16. package/dist/browser/player.js +412 -0
  17. package/dist/browser/select-control.d.ts +33 -0
  18. package/dist/browser/select-control.js +171 -0
  19. package/dist/browser.d.ts +5 -69
  20. package/dist/browser.js +3 -353
  21. package/dist/core/color.d.ts +3 -0
  22. package/dist/core/color.js +18 -0
  23. package/dist/core/diagram.d.ts +40 -0
  24. package/dist/core/diagram.js +481 -0
  25. package/dist/core/edge-geometry.d.ts +45 -0
  26. package/dist/core/edge-geometry.js +609 -0
  27. package/dist/{core.d.ts → core/model.d.ts} +37 -61
  28. package/dist/core/model.js +1 -0
  29. package/dist/core/node-content-measurement.d.ts +34 -0
  30. package/dist/core/node-content-measurement.js +66 -0
  31. package/dist/{node-content-paint.d.ts → core/node-content-paint.d.ts} +2 -2
  32. package/dist/{node-content-paint.js → core/node-content-paint.js} +11 -20
  33. package/dist/{node-content.d.ts → core/node-content.d.ts} +18 -1
  34. package/dist/{node-content.js → core/node-content.js} +30 -6
  35. package/dist/core/svg-number.d.ts +5 -0
  36. package/dist/core/svg-number.js +7 -0
  37. package/dist/{theme.d.ts → core/theme.d.ts} +6 -0
  38. package/dist/core/theme.js +17 -0
  39. package/dist/{timeline.d.ts → core/timeline.d.ts} +11 -5
  40. package/dist/{timeline.js → core/timeline.js} +30 -22
  41. package/dist/core/validation.d.ts +11 -0
  42. package/dist/core/validation.js +399 -0
  43. package/dist/export/browser.d.ts +9 -0
  44. package/dist/export/browser.js +172 -0
  45. package/dist/export/captions.d.ts +18 -0
  46. package/dist/export/captions.js +44 -0
  47. package/dist/export/plan.d.ts +25 -0
  48. package/dist/export/plan.js +94 -0
  49. package/dist/export/types.d.ts +64 -0
  50. package/dist/export/types.js +9 -0
  51. package/dist/export/worker-source.d.ts +1 -0
  52. package/dist/export/worker-source.js +1 -0
  53. package/dist/export.d.ts +3 -0
  54. package/dist/export.js +2 -0
  55. package/dist/index.d.ts +7 -1
  56. package/dist/index.js +3 -1
  57. package/dist/node/cli.d.ts +2 -0
  58. package/dist/node/cli.js +72 -0
  59. package/dist/node/gif.d.ts +16 -0
  60. package/dist/node/gif.js +184 -0
  61. package/dist/node/html.d.ts +19 -0
  62. package/dist/node/html.js +61 -0
  63. package/dist/node/output.d.ts +2 -0
  64. package/dist/node/output.js +22 -0
  65. package/dist/node.d.ts +6 -0
  66. package/dist/node.js +3 -0
  67. package/dist/portable/LICENSE.esbuild.txt +21 -0
  68. package/dist/portable/LICENSE.flowsvg.txt +21 -0
  69. package/dist/portable/LICENSE.gifenc.txt +21 -0
  70. package/dist/portable/export.js +5 -0
  71. package/dist/portable/manifest.json +36 -0
  72. package/dist/portable/player.js +2 -0
  73. package/dist/portable/styles.css +227 -0
  74. package/dist/react.d.ts +3 -48
  75. package/dist/react.js +2 -126
  76. package/dist/styles.css +194 -14
  77. package/dist/vue.d.ts +3 -132
  78. package/dist/vue.js +2 -161
  79. package/dist/web-component.d.ts +3 -103
  80. package/dist/web-component.js +2 -396
  81. package/docs/images/entity-graph.png +0 -0
  82. package/docs/images/facts-timeline.png +0 -0
  83. package/docs/images/facts-timeline.zh-CN.png +0 -0
  84. package/docs/images/flowsvg-wordmark.gif +0 -0
  85. package/docs/images/node-content.png +0 -0
  86. package/docs/images/numbered-list.png +0 -0
  87. package/docs/images/numbered-list.zh-CN.png +0 -0
  88. package/docs/images/quick-start.png +0 -0
  89. package/docs/images/record-tags.png +0 -0
  90. package/package.json +38 -6
  91. package/dist/core.js +0 -1149
  92. package/dist/theme.js +0 -6
  93. /package/dist/{player-accessibility.d.ts → browser/accessibility.d.ts} +0 -0
  94. /package/dist/{player-accessibility.js → browser/accessibility.js} +0 -0
  95. /package/dist/{player-lifecycle.d.ts → browser/lifecycle.d.ts} +0 -0
  96. /package/dist/{player-lifecycle.js → browser/lifecycle.js} +0 -0
  97. /package/dist/{svg-dom.d.ts → browser/svg-dom.d.ts} +0 -0
  98. /package/dist/{svg-dom.js → browser/svg-dom.js} +0 -0
@@ -0,0 +1,184 @@
1
+ /** Node GIF bridge. Reuse the built browser exporter in an isolated, offline Chromium page. */
2
+ import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+ import { createDiagram } from "../core/diagram.js";
7
+ import { planGif, validateGifOptions } from "../export/plan.js";
8
+ import { GifExportError } from "../export/types.js";
9
+ import { assertNodeRuntime } from "./html.js";
10
+ /**
11
+ * Return GIF bytes using the same exporter as flowsvg/export. Requires Node 20+ and preinstalled Chromium.
12
+ * Snapshot inputs before asynchronous work. Success, error and cancellation release task-owned resources;
13
+ * a supplied browser is never closed. Progress is forwarded from the browser exporter.
14
+ */
15
+ export async function exportGif(document, options = {}) {
16
+ assertNodeRuntime();
17
+ validateGifOptions(options);
18
+ const { browser: externalBrowser, executablePath, signal, onProgress, ...settings } = options;
19
+ const snapshot = snapshotInput(document, "document");
20
+ const fixedOptions = snapshotInput(settings, "options");
21
+ if (executablePath !== undefined && (typeof executablePath !== "string" || executablePath.length === 0)) {
22
+ throw new GifExportError("options", "executablePath must identify an installed Chromium executable.");
23
+ }
24
+ if (externalBrowser !== undefined && executablePath !== undefined)
25
+ throw new GifExportError("options", "Choose browser or executablePath, not both.");
26
+ throwIfCancelled(signal);
27
+ let duration;
28
+ try {
29
+ duration = createDiagram(snapshot).totalDuration;
30
+ }
31
+ catch (cause) {
32
+ throw new GifExportError("document", "Invalid diagram document. Correct validation issues before exporting.", { cause });
33
+ }
34
+ planGif(snapshot, duration, fixedOptions);
35
+ const job = new BrowserExportJob(signal, onProgress);
36
+ try {
37
+ return await job.run(snapshot, fixedOptions, externalBrowser, executablePath);
38
+ }
39
+ finally {
40
+ await job.dispose();
41
+ }
42
+ }
43
+ /** Own one export page/context, optional launched browser and temporary directory. Abort also interrupts launch. */
44
+ class BrowserExportJob {
45
+ signal;
46
+ onProgress;
47
+ browser;
48
+ context;
49
+ page;
50
+ directory;
51
+ ownedBrowser = false;
52
+ contextClosing;
53
+ callbackError;
54
+ callbackFailed = false;
55
+ rejectAbort;
56
+ cancellation;
57
+ abort = () => {
58
+ this.rejectAbort?.(cancelledError());
59
+ // Closing the isolated context interrupts font/raster/worker work even if the page cannot evaluate abort.
60
+ // dispose() awaits this same promise and reports cleanup failures after releasing other resources.
61
+ void this.closeContext().catch(() => undefined);
62
+ };
63
+ constructor(signal, onProgress) {
64
+ this.signal = signal;
65
+ this.onProgress = onProgress;
66
+ this.cancellation = new Promise((_, reject) => { this.rejectAbort = reject; });
67
+ // A cancellation can arrive during a file read, before launch starts observing this promise.
68
+ void this.cancellation.catch(() => undefined);
69
+ this.signal?.addEventListener("abort", this.abort, { once: true });
70
+ }
71
+ async run(document, options, externalBrowser, executablePath) {
72
+ try {
73
+ return await this.execute(document, options, externalBrowser, executablePath);
74
+ }
75
+ catch (error) {
76
+ if (this.callbackFailed)
77
+ throw new GifExportError("encoding", "GIF progress callback failed. Correct the callback and retry.", { cause: this.callbackError });
78
+ throwIfCancelled(this.signal);
79
+ if (error instanceof GifExportError)
80
+ throw error;
81
+ throw new GifExportError("environment", "Cannot run Chromium GIF export. Prepare Chromium with npx --no-install playwright-core install chromium (and --with-deps on supported Linux), or set executablePath to an installed Chromium executable.", { cause: error });
82
+ }
83
+ }
84
+ async execute(document, options, externalBrowser, executablePath) {
85
+ const script = await readFile(new URL("../portable/export.js", import.meta.url), "utf8");
86
+ throwIfCancelled(this.signal);
87
+ this.browser = externalBrowser ?? await this.launch(executablePath);
88
+ this.ownedBrowser = externalBrowser === undefined;
89
+ throwIfCancelled(this.signal);
90
+ this.context = await this.browser.newContext({ offline: true });
91
+ throwIfCancelled(this.signal);
92
+ this.page = await this.context.newPage();
93
+ await this.page.exposeFunction("flowSvgProgress", (progress) => {
94
+ if (this.signal?.aborted)
95
+ return;
96
+ try {
97
+ this.onProgress?.(progress);
98
+ }
99
+ catch (error) {
100
+ this.callbackFailed = true;
101
+ this.callbackError = error;
102
+ this.abort();
103
+ }
104
+ });
105
+ this.directory = await mkdtemp(join(tmpdir(), "flowsvg-gif-"));
106
+ const html = join(this.directory, "export.html");
107
+ await writeFile(html, `<meta charset="utf-8"><script>${script}</script>`);
108
+ throwIfCancelled(this.signal);
109
+ await this.page.goto(pathToFileURL(html).href);
110
+ const result = await this.page.evaluate(async ({ document, options }) => {
111
+ const bridge = globalThis;
112
+ const controller = new AbortController();
113
+ const progressPending = [];
114
+ try {
115
+ const bytes = await bridge.FlowSVGExport.exportGif(document, {
116
+ ...options, signal: controller.signal,
117
+ onProgress: (progress) => { progressPending.push(bridge.flowSvgProgress(progress)); }
118
+ });
119
+ await Promise.all(progressPending);
120
+ return { bytes: Array.from(bytes) };
121
+ }
122
+ catch (error) {
123
+ const failure = error;
124
+ return { error: { code: failure.code ?? "encoding", message: failure.message ?? "Browser GIF export failed." } };
125
+ }
126
+ }, { document, options });
127
+ throwIfCancelled(this.signal);
128
+ if ("error" in result)
129
+ throw new GifExportError(result.error.code, result.error.message);
130
+ return Uint8Array.from(result.bytes);
131
+ }
132
+ async launch(executablePath) {
133
+ let automation;
134
+ try {
135
+ automation = await import("playwright-core");
136
+ }
137
+ catch (error) {
138
+ throw new GifExportError("environment", "GIF export requires playwright-core. Reinstall flowsvg with its runtime dependencies, then prepare Chromium explicitly.", { cause: error });
139
+ }
140
+ throwIfCancelled(this.signal);
141
+ // The host/CLI owns process signals; Playwright defaults can otherwise exit before our cleanup.
142
+ const launched = automation.chromium.launch({ executablePath, handleSIGINT: false, handleSIGTERM: false, handleSIGHUP: false }).then(async (browser) => {
143
+ // A cancelled launch can settle after run() returned; close that late process.
144
+ if (this.signal?.aborted) {
145
+ await browser.close();
146
+ throw cancelledError();
147
+ }
148
+ return browser;
149
+ });
150
+ return await Promise.race([launched, this.cancellation]);
151
+ }
152
+ closeContext() {
153
+ if (this.context)
154
+ this.contextClosing ??= this.context.close();
155
+ return this.contextClosing ?? Promise.resolve();
156
+ }
157
+ async dispose() {
158
+ this.signal?.removeEventListener("abort", this.abort);
159
+ try {
160
+ await this.closeContext();
161
+ }
162
+ finally {
163
+ try {
164
+ if (this.ownedBrowser)
165
+ await this.browser?.close();
166
+ }
167
+ finally {
168
+ if (this.directory)
169
+ await rm(this.directory, { recursive: true, force: true });
170
+ }
171
+ }
172
+ }
173
+ }
174
+ function cancelledError() { return new GifExportError("cancelled", "GIF export was cancelled. Start a new export when ready."); }
175
+ function throwIfCancelled(signal) { if (signal?.aborted)
176
+ throw cancelledError(); }
177
+ function snapshotInput(value, code) {
178
+ try {
179
+ return structuredClone(value);
180
+ }
181
+ catch (cause) {
182
+ throw new GifExportError(code, `GIF ${code} must contain serializable values. Remove functions or other unsupported values and retry.`, { cause });
183
+ }
184
+ }
@@ -0,0 +1,19 @@
1
+ import type { DiagramDocument, ThemeName } from "../core/model.js";
2
+ /** Offline playback options. Default to document/light theme, paused at zero, with controls and caption. */
3
+ export interface HtmlRenderOptions {
4
+ theme?: ThemeName;
5
+ autoplay?: boolean;
6
+ /** Defaults to false. Loop live playback; GIF loopCount remains an independent export option. */
7
+ loop?: boolean;
8
+ controls?: boolean;
9
+ /** Embed offline GIF export assets and show GIF controls when controls are visible. Defaults to false. */
10
+ gifExport?: boolean;
11
+ }
12
+ /**
13
+ * Return one offline HTML file containing validated data, the player, CSS and optional GIF assets. Requires Node 20+.
14
+ * Text remains data, including HTML delimiters and Unicode separators. No browser is required.
15
+ * @throws For invalid documents/options, an unsupported Node runtime, or missing built assets.
16
+ */
17
+ export declare function renderHtml(document: DiagramDocument, options?: HtmlRenderOptions): Promise<string>;
18
+ /** Fail before reading files or allocating browser resources on the Node-only path. */
19
+ export declare function assertNodeRuntime(): void;
@@ -0,0 +1,61 @@
1
+ /** Node-only HTML assembly. Read versioned built assets; never start a browser or import automation/encoding dependencies. */
2
+ import { readFile } from "node:fs/promises";
3
+ import { createDiagram } from "../core/diagram.js";
4
+ import { DIAGRAM_FONT_FAMILY, resolveThemePalette } from "../core/theme.js";
5
+ /**
6
+ * Return one offline HTML file containing validated data, the player, CSS and optional GIF assets. Requires Node 20+.
7
+ * Text remains data, including HTML delimiters and Unicode separators. No browser is required.
8
+ * @throws For invalid documents/options, an unsupported Node runtime, or missing built assets.
9
+ */
10
+ export async function renderHtml(document, options = {}) {
11
+ assertNodeRuntime();
12
+ const snapshot = structuredClone(document);
13
+ const playbackOptions = structuredClone(options);
14
+ createDiagram(snapshot);
15
+ validateOptions(playbackOptions);
16
+ const [script, styles, exporter] = await Promise.all([
17
+ readFile(new URL("../portable/player.js", import.meta.url), "utf8"),
18
+ readFile(new URL("../portable/styles.css", import.meta.url), "utf8"),
19
+ playbackOptions.gifExport ? readFile(new URL("../portable/export.js", import.meta.url), "utf8") : ""
20
+ ]);
21
+ const data = escapeJson({ document: snapshot, options: playbackOptions });
22
+ const title = escapeHtml(snapshot.title ?? "FlowSVG");
23
+ const palette = resolveThemePalette(playbackOptions.theme ?? snapshot.theme);
24
+ const pageStyles = `body{margin:0;background:${palette.background};color:${palette.text};font-family:${DIAGRAM_FONT_FAMILY}}
25
+ #flowsvg-player{max-width:1280px;margin:auto}.flowsvg-canvas svg{display:block;width:100%}
26
+ .flowsvg-caption{padding:0 16px;white-space:pre-wrap}
27
+ .flowsvg-controls{--flowsvg-control-background:${palette.background};--flowsvg-control-color:${palette.text}}`;
28
+ return `<!doctype html>
29
+ <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
30
+ <title>${title}</title><style>${styles}\n${pageStyles}</style></head>
31
+ <body><main id="flowsvg-player"></main>
32
+ <script id="flowsvg-data" type="application/json">${data}</script>
33
+ ${exporter ? `<script>${exporter}</script>\n` : ""}<script>${script}</script></body></html>`;
34
+ }
35
+ /** Fail before reading files or allocating browser resources on the Node-only path. */
36
+ export function assertNodeRuntime() {
37
+ const MIN_NODE_MAJOR = 20;
38
+ if (Number(process.versions.node.split(".")[0]) < MIN_NODE_MAJOR) {
39
+ throw new Error("FlowSVG Node tools require Node 20 or newer. Upgrade Node and retry.");
40
+ }
41
+ }
42
+ function validateOptions(options) {
43
+ if (options.theme !== undefined && options.theme !== "light" && options.theme !== "dark") {
44
+ throw new Error("HTML theme must be light or dark.");
45
+ }
46
+ for (const key of ["autoplay", "controls", "gifExport", "loop"]) {
47
+ if (options[key] !== undefined && typeof options[key] !== "boolean") {
48
+ throw new Error(`HTML ${key} must be a boolean.`);
49
+ }
50
+ }
51
+ }
52
+ function escapeJson(value) {
53
+ const ESCAPES = {
54
+ "<": "\\u003c", ">": "\\u003e", "&": "\\u0026", "\u2028": "\\u2028", "\u2029": "\\u2029"
55
+ };
56
+ return JSON.stringify(value).replace(/[<>&\u2028\u2029]/g, (character) => ESCAPES[character]);
57
+ }
58
+ function escapeHtml(value) {
59
+ const ESCAPES = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" };
60
+ return value.replace(/[&<>"']/g, (character) => ESCAPES[character]);
61
+ }
@@ -0,0 +1,2 @@
1
+ /** Atomically publish complete bytes or text. Only explicit overwrite replaces an existing output. */
2
+ export declare function publishOutput(destination: string, content: string | Uint8Array, overwrite: boolean, signal: AbortSignal): Promise<void>;
@@ -0,0 +1,22 @@
1
+ /** Publish complete CLI output on the destination filesystem; exclusive linking protects concurrent writers. */
2
+ import { randomUUID } from "node:crypto";
3
+ import { link, rename, unlink, writeFile } from "node:fs/promises";
4
+ /** Atomically publish complete bytes or text. Only explicit overwrite replaces an existing output. */
5
+ export async function publishOutput(destination, content, overwrite, signal) {
6
+ signal.throwIfAborted();
7
+ const temporaryPath = `${destination}.${randomUUID()}.tmp`;
8
+ try {
9
+ await writeFile(temporaryPath, content, { flag: "wx", signal });
10
+ signal.throwIfAborted();
11
+ if (overwrite)
12
+ await rename(temporaryPath, destination);
13
+ else
14
+ await link(temporaryPath, destination);
15
+ }
16
+ finally {
17
+ await unlink(temporaryPath).catch((error) => {
18
+ if (!(error instanceof Error && "code" in error && error.code === "ENOENT"))
19
+ throw error;
20
+ });
21
+ }
22
+ }
package/dist/node.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export { renderHtml } from "./node/html.js";
2
+ export type { HtmlRenderOptions } from "./node/html.js";
3
+ export { exportGif } from "./node/gif.js";
4
+ export type { NodeGifExportOptions } from "./node/gif.js";
5
+ export { GifExportError } from "./export/types.js";
6
+ export type { GifExportOptions, GifExportProgress, GifExportErrorCode } from "./export/types.js";
package/dist/node.js ADDED
@@ -0,0 +1,3 @@
1
+ export { renderHtml } from "./node/html.js";
2
+ export { exportGif } from "./node/gif.js";
3
+ export { GifExportError } from "./export/types.js";
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Evan Wallace
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 zac_ma
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2017 Matt DesLauriers
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
20
+ OR OTHER DEALINGS IN THE SOFTWARE.
21
+
@@ -0,0 +1,5 @@
1
+ var FlowSVGExport=(()=>{var bt=Object.defineProperty;var Ge=Object.getOwnPropertyDescriptor;var ke=Object.getOwnPropertyNames;var Fe=Object.prototype.hasOwnProperty;var We=(t,e)=>{for(var n in e)bt(t,n,{get:e[n],enumerable:!0})},He=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ke(e))!Fe.call(t,i)&&i!==n&&bt(t,i,{get:()=>e[i],enumerable:!(o=Ge(e,i))||o.enumerable});return t};var je=t=>He(bt({},"__esModule",{value:!0}),t);var vo={};We(vo,{GifExportError:()=>$,exportGif:()=>Ft});var Be=new Intl.Segmenter("en",{granularity:"grapheme"});function wt(t){return t==="rect"||t==="roundedRect"||t==="cylinder"}function ze(t,e,n){let o=n==="roundedRect"?4:0,i=n==="cylinder"?Math.min(14,t.height/4)*2:0,r=e+o,s=r+i;return{x:t.x+r,y:t.y+s,width:Math.max(0,t.width-r*2),height:Math.max(0,t.height-s*2)}}function zt(t,e,n,o){return Ue(t,e,n,o).layout}function Ue(t,e,n,o){let i=ze(e,t.style?.padding??16,o),r=i.y,s=!1,a=!1,l=[],u=[],h=[],c=t.blocks.flatMap((f,d)=>{let g=f.type==="graph"?Ve(f,i,r,n,d,u):f.type==="list"?Xe(f,i,r,n,d):W(f.text,f.type==="title"?"title":f.role??"body",f.style,i,r,n,d),m=g.widthOverflow||g.lines.some(y=>Ye(y,i));return m&&h.push({blockIndex:d,dimension:"width"}),g.heightOverflow&&h.push({blockIndex:d,dimension:"height"}),s||=m,a||=g.heightOverflow??!1,l.push(...g.tags),r=g.bottom+(d<t.blocks.length-1?t.style?.blockGap??14:0),g.lines});return{contentHeight:r-i.y,overflows:h,layout:{safeArea:i,lines:c,tags:l,...u.length?{graphs:u}:{},widthOverflow:s,heightOverflow:a||r>i.y+i.height+1e-6}}}function Ve(t,e,n,o,i,r){let s=new Map(t.nodes.map(h=>[h.id,{x:e.x+h.x,y:n+h.y}])),a=t.nodes.map(h=>({...s.get(h.id),radius:4,fill:h.highlighted?o.accentText:o.mutedText,highlighted:h.highlighted??!1})),l=t.edges.map(h=>{let c=s.get(h.from),f=s.get(h.to),d=[h.from,h.to].every(g=>t.nodes.find(m=>m.id===g)?.highlighted);return{x1:c.x,y1:c.y,x2:f.x,y2:f.y,color:d?o.accentText:o.mutedText,highlighted:d}}),u=t.nodes.map(h=>{let c=Math.max(0,Math.min(h.x,e.width-h.x)),f={...e,x:e.x+h.x-c,width:c*2};return W(h.label,"body",{fontSize:12,fontWeight:h.highlighted?700:400,align:"center"},f,n+h.y-4-7-12,o,i)});return r.push({blockIndex:i,nodes:a,edges:l}),{lines:u.flatMap(h=>h.lines),tags:[],bottom:n+t.height,heightOverflow:u.some(h=>h.lines.some(c=>c.y-c.fontSize<n-1e-6)||h.bottom>n+t.height)||t.nodes.some(h=>h.y-4<0||h.y+4>t.height),widthOverflow:u.some(h=>h.widthOverflow)||t.nodes.some(h=>h.x<4||h.x+4>e.width)}}function Ye(t,e){return t.width>e.width||t.spans.some(n=>n.x<e.x-1e-6||n.x+n.width>e.x+e.width+1e-6)}function W(t,e,n,o,i,r,s,a,l=0){let u=n?.fontSize??(e==="title"?20:e==="auxiliary"||e==="status"?12:e==="tag"?11:14),h=n?.fontWeight??(e==="title"?700:400),c=n?.color??(e==="auxiliary"?r.mutedText:e==="tag"?r.tagText:e==="status"?r.accentText:r.text),f=n?.align??"left",d=o.x+(f==="right"?o.width:f==="center"?o.width/2:0),g=Kt(t,o.width,{fontSize:u,fontWeight:h,color:c,explicitColor:n?.color!==void 0}),m=i,y=g.map((x,b)=>{let P=x.length>0?x.reduce((E,_)=>Math.max(E,_.style.fontSize),0):u,w=Math.max(P,b===0?l:0),M=x.reduce((E,_)=>E+_.width,0),A=m+w,v=d-(f==="right"?M:f==="center"?M/2:0),S=nn(x,v,A);return m+=Math.max(20,w*1.35),{text:x.map(E=>E.text).join(""),spans:S,x:d,y:A,width:M,fontSize:w,fontWeight:h,color:c,align:f,role:e,blockIndex:s,...a===void 0?{}:{itemIndex:a}}});return{lines:y,tags:[],bottom:m,widthOverflow:y.some(x=>x.width>o.width)}}function Xe(t,e,n,o,i){let r=n,s=[],a=[],l=!1,u=Qe(t),h=u>0?u+8:0,c={...e,x:e.x+h,width:Math.max(0,e.width-h)};return t.items.forEach((f,d)=>{if(!Xt(f))return;s.length>0&&(r+=t.style?.itemGap??12);let g=s.length,m=u===0?0:f.body===void 0?f.auxiliaryStyle?.fontSize??12:f.style?.fontSize??t.style?.fontSize??14,y=Ke(f,c,r,o,i,d,t.style?.tagGap??6,m);if(s.push(...y.lines),a.push(...y.tags),l||=y.widthOverflow,r=y.bottom,f.body!==void 0){let x=W(f.body,"body",Bt(t.style,f.style),c,r,o,i,d,m);s.push(...x.lines),l||=x.widthOverflow,r=x.bottom}if(f.auxiliary!==void 0){let x=W(f.auxiliary,"auxiliary",f.auxiliaryStyle,c,r,o,i,d,f.body===void 0?m:0);s.push(...x.lines),l||=x.widthOverflow,r=x.bottom}if(u>0){let x=s[g],b=f.body===void 0?f.auxiliaryStyle:Bt(t.style,f.style),P=W(t.marker==="bullet"?"\u2022":`${d+1}.`,"marker",{...b,fontSize:b?.fontSize??(f.body===void 0?12:14),align:"left"},{...e,width:u},n,o,i,d).lines[0];s.splice(g,0,{...P,y:x.y,spans:P.spans.map(w=>({...w,y:x.y}))})}}),{lines:s,tags:a,bottom:r,widthOverflow:l}}function Ke(t,e,n,o,i,r,s,a){let l=Ze(t.tags??[],e,n,o,i,r,s,a);if(t.status===void 0)return l;let u=Yt(t.status,t.statusStyle,12),h=l.tags.at(-1),c=h?h.x+h.width-e.x:0,f=l.tags.every(b=>b.y===n)&&l.lines.length===l.tags.length,d=!Je(t.status).match(/[\r\n]/),g=f&&d&&c+(h?s:0)+u<=e.width,m=g?n:l.bottom,y=W(t.status,"status",{...t.statusStyle,align:"right"},e,m,o,i,r,a),x=l;if(g&&l.lines.length>0){let b=Math.max(...l.lines.map(P=>P.y),y.lines[0].y);x=Ut(l,b-l.lines[0].y),y=Vt(y,b-y.lines[0].y)}return{lines:[...x.lines,...y.lines],tags:x.tags,bottom:Math.max(x.bottom,y.bottom),widthOverflow:x.widthOverflow||y.widthOverflow}}function Ze(t,e,n,o,i,r,s,a){let l=[],u=e.x,h={lines:[],tags:[],bottom:n,widthOverflow:!1},c=()=>{if(l.length===0)return;let f=h.tags.length>0?h.bottom+s:n,d=l.map(({tag:y,tagIndex:x,width:b,x:P})=>qe(y,{...e,x:P,width:b},f,o,i,r,x,a)),g=Math.max(...d.map(y=>y.lines[0].y)),m=d.map(y=>Ut(y,g-y.lines[0].y));h={lines:[...h.lines,...m.flatMap(y=>y.lines)],tags:[...h.tags,...m.flatMap(y=>y.tags)],bottom:Math.max(...m.map(y=>y.bottom)),widthOverflow:h.widthOverflow||m.some(y=>y.widthOverflow)},l=[],u=e.x};return t.forEach((f,d)=>{let g=Math.min(e.width,Yt(f.text,f.style,11)+12);l.length>0&&u+g>e.x+e.width&&c(),l.push({tag:f,tagIndex:d,width:g,x:u}),u+=g+s}),c(),h}function qe(t,e,n,o,i,r,s,a){let l={...e,x:e.x+6,width:Math.max(0,e.width-12)},u=W(t.text,"tag",t.style,l,n+2,o,i,r,a);return{...u,widthOverflow:u.widthOverflow||e.width<12,lines:u.lines.map(h=>({...h,tagIndex:s})),bottom:u.bottom+2,tags:[{x:e.x,y:n,width:e.width,height:u.bottom-n+2,fill:t.style?.fill??o.tagFill,explicitFill:t.style?.fill!==void 0,...t.style?.shape===void 0?{}:{shape:t.style.shape},blockIndex:i,itemIndex:r,tagIndex:s}]}}function Ut(t,e){return{...Vt(t,e),tags:t.tags.map(n=>({...n,height:n.height+e}))}}function Vt(t,e){return{...t,bottom:t.bottom+e,lines:t.lines.map(n=>({...n,y:n.y+e,spans:n.spans.map(o=>({...o,y:o.y+e}))}))}}function Je(t){return typeof t=="string"?t:t.map(e=>e.text).join("")}function Yt(t,e,n){let o=Kt(t,Number.MAX_VALUE,{fontSize:e?.fontSize??n,fontWeight:e?.fontWeight??400,color:e?.color??"#000000",explicitColor:e?.color!==void 0});return Math.max(0,...o.map(i=>i.reduce((r,s)=>r+s.width,0)))}function Xt(t){return t.body!==void 0||t.auxiliary!==void 0||t.status!==void 0||(t.tags?.length??0)>0}function Qe(t){return t.marker===void 0||t.marker==="none"?0:t.items.reduce((e,n,o)=>{if(!Xt(n))return e;let i=n.body===void 0?n.auxiliaryStyle?.fontSize??12:n.style?.fontSize??t.style?.fontSize??14;return Math.max(e,Zt(t.marker==="bullet"?"\u2022":`${o+1}.`,i))},0)}function Bt(t,e){return{fontSize:e?.fontSize??t?.fontSize,fontWeight:e?.fontWeight??t?.fontWeight,color:e?.color??t?.color,align:e?.align??t?.align}}function Kt(t,e,n){let i=tn(typeof t=="string"?[{text:t}]:t,n),r=[[]];return i.forEach(s=>{/^\r\n$|^[\r\n]$/.test(s.text)?r.push([]):r.at(-1).push(s)}),r.flatMap(s=>en(s,e))}function tn(t,e){let n=t.map(r=>r.text).join(""),o=0,i=t[0]?.text.length??0;return Array.from(Be.segment(n),({segment:r,index:s})=>{for(;s>=i&&o<t.length-1;)o+=1,i+=t[o].text.length;let a=t[o]?.style,l={...e,...a,explicitColor:a?.color!==void 0||e.explicitColor};return{text:r,sourceIndex:o,style:l,width:Zt(r,l.fontSize)}})}function en(t,e){let n=t,o=[];for(;n.length>0;){let i=0,r=0;for(;i<n.length&&r+n[i].width<=e;)r+=n[i].width,i+=1;if(i>=n.length){o.push(n);break}let s=n.slice(0,i+1).map(l=>l.text).lastIndexOf(" "),a=s>0?s:Math.max(1,i);for(o.push(n.slice(0,a)),n=n.slice(a);n[0]?.text===" ";)n=n.slice(1)}return o.length>0?o:[[]]}function nn(t,e,n){let o=[],i=e,r=-1;for(let s of t){let a=o.at(-1);a&&r===s.sourceIndex?o[o.length-1]={...a,text:a.text+s.text,width:a.width+s.width}:o.push({text:s.text,x:i,y:n,width:s.width,...s.style}),i+=s.width,r=s.sourceIndex}return o}function Zt(t,e){return t==="\u2022"?e*.6:/\p{Extended_Pictographic}|\p{Regional_Indicator}|\u20e3/u.test(t)?e:Array.from(t).filter(n=>!/\p{Mark}|\p{Default_Ignorable_Code_Point}/u.test(n)).reduce((n,o)=>n+e*(o.codePointAt(0)>255||"MWmw@%".includes(o)?1:.6),0)}function $t(t,e,n){if(!O(t)){n.push({path:e,message:"must be an object"});return}if(N(t,["blocks","style"],e,n),!Array.isArray(t.blocks)){n.push({path:`${e}.blocks`,message:"must be an array"});return}an(t.style,`${e}.style`,n);for(let o=0;o<t.blocks.length;o+=1)o in t.blocks||n.push({path:`${e}.blocks[${o}]`,message:"must be a value"});t.blocks.forEach((o,i)=>{let r=`${e}.blocks[${i}]`;if(!O(o)){n.push({path:r,message:"must be an object"});return}if(o.type==="list"){rn(o,r,n);return}if(o.type==="graph"){on(o,r,n);return}N(o,o.type==="paragraph"?["type","text","role","style"]:["type","text","style"],r,n),o.type!=="title"&&o.type!=="paragraph"&&n.push({path:`${r}.type`,message:"must be title, paragraph, list or graph"}),K(o.text,`${r}.text`,n),L(o.style,`${r}.style`,n),o.role!==void 0&&o.role!=="body"&&o.role!=="auxiliary"&&n.push({path:`${r}.role`,message:"must be body or auxiliary"})})}function on(t,e,n){N(t,["type","height","nodes","edges"],e,n),B(t.height,`${e}.height`,n,!0);let o=new Set;if(!Array.isArray(t.nodes))n.push({path:`${e}.nodes`,message:"must be an array"});else for(let i=0;i<t.nodes.length;i+=1){let r=t.nodes[i],s=`${e}.nodes[${i}]`;if(!O(r)){n.push({path:s,message:"must be an object"});continue}N(r,["id","label","x","y","highlighted"],s,n),typeof r.id!="string"||!r.id.trim()||o.has(r.id)?n.push({path:`${s}.id`,message:"must be a unique nonempty local ID"}):o.add(r.id),typeof r.label!="string"&&n.push({path:`${s}.label`,message:"must be a string"});for(let a of["x","y"])B(r[a],`${s}.${a}`,n);r.highlighted!==void 0&&typeof r.highlighted!="boolean"&&n.push({path:`${s}.highlighted`,message:"must be a boolean"})}if(!Array.isArray(t.edges)){n.push({path:`${e}.edges`,message:"must be an array"});return}for(let i=0;i<t.edges.length;i+=1){let r=t.edges[i],s=`${e}.edges[${i}]`;if(!O(r)){n.push({path:s,message:"must be an object"});continue}N(r,["from","to"],s,n);for(let a of["from","to"])(typeof r[a]!="string"||!o.has(r[a]))&&n.push({path:`${s}.${a}`,message:"must reference a node in this graph block"})}}function rn(t,e,n){if(N(t,["type","marker","items","style"],e,n),t.marker!==void 0&&t.marker!=="none"&&t.marker!=="bullet"&&t.marker!=="number"&&n.push({path:`${e}.marker`,message:"must be none, bullet or number"}),O(t.style)){let{itemGap:o,tagGap:i,...r}=t.style;L(r,`${e}.style`,n),o!==void 0&&B(o,`${e}.style.itemGap`,n),i!==void 0&&B(i,`${e}.style.tagGap`,n)}else L(t.style,`${e}.style`,n);if(!Array.isArray(t.items)){n.push({path:`${e}.items`,message:"must be an array"});return}for(let o=0;o<t.items.length;o+=1){let i=t.items[o],r=`${e}.items[${o}]`;if(!O(i)){n.push({path:r,message:"must be an object"});continue}N(i,["body","auxiliary","style","auxiliaryStyle","tags","status","statusStyle"],r,n),i.body!==void 0&&K(i.body,`${r}.body`,n),i.auxiliary!==void 0&&K(i.auxiliary,`${r}.auxiliary`,n),sn(i.tags,`${r}.tags`,n),i.status!==void 0&&K(i.status,`${r}.status`,n),L(i.statusStyle,`${r}.statusStyle`,n,!0),L(i.style,`${r}.style`,n),L(i.auxiliaryStyle,`${r}.auxiliaryStyle`,n)}}function sn(t,e,n){if(t!==void 0){if(!Array.isArray(t)){n.push({path:e,message:"must be an array"});return}for(let o=0;o<t.length;o+=1){let i=t[o],r=`${e}[${o}]`;if(!O(i)){n.push({path:r,message:"must be an object"});continue}if(N(i,["text","style"],r,n),K(i.text,`${r}.text`,n),!O(i.style)){L(i.style,`${r}.style`,n,!0);continue}let{fill:s,shape:a,...l}=i.style;L(l,`${r}.style`,n,!0),s!==void 0&&qt(s,`${r}.style.fill`,n),a!==void 0&&a!=="rounded"&&a!=="pill"&&n.push({path:`${r}.style.shape`,message:"must be rounded or pill"})}}}function K(t,e,n){if(typeof t!="string"){if(!Array.isArray(t)){n.push({path:e,message:"must be a string or an array of text spans"});return}for(let o=0;o<t.length;o+=1){let i=t[o],r=`${e}[${o}]`;if(!O(i)){n.push({path:r,message:"must be an object"});continue}N(i,["text","style"],r,n),typeof i.text!="string"&&n.push({path:`${r}.text`,message:"must be a string"}),L(i.style,`${r}.style`,n,!0)}}}function L(t,e,n,o=!1){if(t!==void 0){if(!O(t)){n.push({path:e,message:"must be an object"});return}N(t,o?["fontSize","fontWeight","color"]:["fontSize","fontWeight","color","align"],e,n),t.fontSize!==void 0&&B(t.fontSize,`${e}.fontSize`,n,!0),t.fontWeight!==void 0&&(typeof t.fontWeight!="number"||!Number.isInteger(t.fontWeight)||t.fontWeight<100||t.fontWeight>900)&&n.push({path:`${e}.fontWeight`,message:"must be an integer from 100 through 900"}),t.align!==void 0&&t.align!=="left"&&t.align!=="center"&&t.align!=="right"&&n.push({path:`${e}.align`,message:"must be left, center or right"}),t.color!==void 0&&qt(t.color,`${e}.color`,n)}}function qt(t,e,n){(typeof t!="string"||!/^#(?:[\da-f]{3}|[\da-f]{4}|[\da-f]{6}|[\da-f]{8})$/i.test(t))&&n.push({path:e,message:"must be a hexadecimal color"})}function an(t,e,n){if(t!==void 0){if(!O(t)){n.push({path:e,message:"must be an object"});return}N(t,["padding","blockGap"],e,n);for(let o of["padding","blockGap"])t[o]!==void 0&&B(t[o],`${e}.${o}`,n)}}function B(t,e,n,o=!1){typeof t!="number"||!Number.isFinite(t)?n.push({path:e,message:"must be a finite number"}):(o?t<=0:t<0)&&n.push({path:e,message:o?"must be greater than zero":"must be zero or greater"})}function O(t){if(typeof t!="object"||t===null||Array.isArray(t))return!1;let e=Object.getPrototypeOf(t);return e===Object.prototype||e===null}function N(t,e,n,o){for(let i of Object.keys(t))e.includes(i)||o.push({path:`${n}.${i}`,message:"unknown field"})}var Jt="#000000",Qt="#ffffff";function ee(t,e,n){return e===0?t:{...t,...t.graphs?{graphs:t.graphs.map(o=>({...o,nodes:o.nodes.map(i=>({...i,fill:Mt(i.fill,n)})),edges:o.edges.map(i=>({...i,color:Mt(i.color,n)}))}))}:{},lines:t.lines.map(o=>{let r=(o.role==="tag"?t.tags.find(l=>l.blockIndex===o.blockIndex&&l.itemIndex===o.itemIndex&&l.tagIndex===o.tagIndex):void 0)?.fill??n,s=l=>Mt(l,r),a=o.spans.map(l=>({...l,color:l.explicitColor?l.color:s(l.color)}));return{...o,spans:a,color:a[0]?.color??s(o.color)}})}}function Mt(t,e){return Pt(t,e)>=4.5?t:Pt(Jt,e)>=Pt(Qt,e)?Jt:Qt}function Pt(t,e){let n=te(t),o=te(e);return(Math.max(n,o)+.05)/(Math.min(n,o)+.05)}function te(t){let e=t.slice(1),n=e.length<=4?[...e.slice(0,3)].map(i=>i+i).join(""):e,o=[0,2,4].map(i=>Number.parseInt(n.slice(i,i+2),16)/255).map(i=>i<=.04045?i/12.92:((i+.055)/1.055)**2.4);return o[0]*.2126+o[1]*.7152+o[2]*.0722}function H(t,e,n){if(n===0)return t;if(n===1)return e;let o=l=>{let u=l.slice(1),h=u.length<=4?[...u].map(c=>c+c).join(""):u;return[0,2,4,6].map(c=>c<h.length?parseInt(h.slice(c,c+2),16):255)},i=o(t),r=o(e),s=i.map((l,u)=>Math.round(l+(r[u]-l)*n));return`#${s.map(l=>l.toString(16).padStart(2,"0")).slice(0,s[3]===255?3:4).join("")}`}var k=class extends Error{issues;constructor(e){super(`Invalid diagram document (${e.length} issue${e.length===1?"":"s"})`),this.name="DiagramValidationError",this.issues=e}};function ie(t){let e=[];if(!T(t))return[{path:"$",message:"document must be an object"}];R(t,["version","title","viewport","theme","nodes","edges","scenes"],"$",e),t.version!==1&&e.push({path:"version",message:"must be 1"}),t.title!==void 0&&typeof t.title!="string"&&e.push({path:"title",message:"must be a string"}),t.theme!==void 0&&t.theme!=="light"&&t.theme!=="dark"&&e.push({path:"theme",message:"must be light or dark"});let n=t.viewport;T(n)?(R(n,["width","height","fitHeight"],"viewport",e),Z(n.width,"viewport.width",e),Z(n.height,"viewport.height",e),n.fitHeight!==void 0&&(T(n.fitHeight)?(R(n.fitHeight,["padding"],"viewport.fitHeight",e),Q(n.fitHeight.padding,"viewport.fitHeight.padding",e)):e.push({path:"viewport.fitHeight",message:"must be an object"}))):e.push({path:"viewport",message:"must be an object"}),Array.isArray(t.nodes)||e.push({path:"nodes",message:"must be an array"}),Array.isArray(t.edges)||e.push({path:"edges",message:"must be an array"}),Array.isArray(t.scenes)||e.push({path:"scenes",message:"must be an array"});let o=Array.isArray(t.nodes)?t.nodes:[],i=Array.isArray(t.edges)?t.edges:[],r=Array.isArray(t.scenes)?t.scenes:[];q(o,"nodes",e),q(i,"edges",e),q(r,"scenes",e);let s=new Set;o.forEach((c,f)=>{let d=`nodes[${f}]`;if(!T(c)){e.push({path:d,message:"must be an object"});return}R(c,["id","kind","x","y","width","height","label","content","parentId","visible","style"],d,e),C(c.id)?s.has(c.id)?e.push({path:`${d}.id`,message:`duplicate id "${c.id}"`}):s.add(c.id):e.push({path:`${d}.id`,message:"must be a non-empty string"}),ln(c.kind)||e.push({path:`${d}.kind`,message:"must be a supported node kind"}),J(c.x,`${d}.x`,e),J(c.y,`${d}.y`,e),Z(c.width,`${d}.width`,e),Z(c.height,`${d}.height`,e),c.label!==void 0&&typeof c.label!="string"&&e.push({path:`${d}.label`,message:"must be a string"}),c.content!==void 0&&($t(c.content,`${d}.content`,e),c.label!==void 0&&e.push({path:`${d}.content`,message:"must not be declared together with label"}),wt(c.kind)||e.push({path:`${d}.content`,message:"requires a rect, roundedRect or cylinder node"})),c.parentId!==void 0&&!C(c.parentId)&&e.push({path:`${d}.parentId`,message:"must be a non-empty string"}),c.visible!==void 0&&typeof c.visible!="boolean"&&e.push({path:`${d}.visible`,message:"must be a boolean"}),cn(c.style,`${d}.style`,e)});let a=new Map;o.forEach(c=>{T(c)&&C(c.id)&&a.set(c.id,c)}),o.forEach((c,f)=>{if(T(c)&&c.parentId!==void 0&&C(c.parentId)){let d=a.get(c.parentId);d?d.kind!=="group"&&e.push({path:`nodes[${f}].parentId`,message:"must reference a group node"}):e.push({path:`nodes[${f}].parentId`,message:"must reference an existing node"})}}),un(o,a,e);let l=new Map;i.forEach((c,f)=>{let d=`edges[${f}]`;if(!T(c)){e.push({path:d,message:"must be an object"});return}R(c,["id","from","to","label","route","fromPort","toPort","visible","style"],d,e),C(c.id)?s.has(c.id)?e.push({path:`${d}.id`,message:`duplicate id "${c.id}"`}):(s.add(c.id),l.set(c.id,c)):e.push({path:`${d}.id`,message:"must be a non-empty string"}),oe(c.from,`${d}.from`,a,e),oe(c.to,`${d}.to`,a,e),c.label!==void 0&&typeof c.label!="string"&&e.push({path:`${d}.label`,message:"must be a string"}),c.route!==void 0&&c.route!=="straight"&&c.route!=="orthogonal"&&c.route!=="curved"&&e.push({path:`${d}.route`,message:"must be straight, orthogonal or curved"}),c.fromPort!==void 0&&!ne(c.fromPort)&&e.push({path:`${d}.fromPort`,message:"must be top, right, bottom or left"}),c.toPort!==void 0&&!ne(c.toPort)&&e.push({path:`${d}.toPort`,message:"must be top, right, bottom or left"}),c.visible!==void 0&&typeof c.visible!="boolean"&&e.push({path:`${d}.visible`,message:"must be a boolean"}),hn(c.style,`${d}.style`,e)});let u=new Set([...a.keys(),...l.keys()]),h=new Set;return r.forEach((c,f)=>{let d=`scenes[${f}]`;if(!T(c)){e.push({path:d,message:"must be an object"});return}R(c,["id","label","beats"],d,e),C(c.id)?h.has(c.id)?e.push({path:`${d}.id`,message:`duplicate id "${c.id}"`}):h.add(c.id):e.push({path:`${d}.id`,message:"must be a non-empty string"}),C(c.label)||e.push({path:`${d}.label`,message:"must be a non-empty string"}),Array.isArray(c.beats)?(q(c.beats,`${d}.beats`,e),c.beats.length===0&&e.push({path:`${d}.beats`,message:"must contain at least one beat"}),c.beats.forEach((g,m)=>dn(g,`${d}.beats[${m}]`,u,a,l,e))):e.push({path:`${d}.beats`,message:"must be an array"})}),e}function T(t){if(typeof t!="object"||t===null||Array.isArray(t))return!1;let e=Object.getPrototypeOf(t);return e===Object.prototype||e===null}function C(t){return typeof t=="string"&&t.length>0}function ln(t){return t==="rect"||t==="roundedRect"||t==="ellipse"||t==="cylinder"||t==="group"}function ne(t){return t==="top"||t==="right"||t==="bottom"||t==="left"}function J(t,e,n){(typeof t!="number"||!Number.isFinite(t))&&n.push({path:e,message:"must be a finite number"})}function Z(t,e,n){J(t,e,n),typeof t=="number"&&Number.isFinite(t)&&t<=0&&n.push({path:e,message:"must be greater than zero"})}function Q(t,e,n){J(t,e,n),typeof t=="number"&&Number.isFinite(t)&&t<0&&n.push({path:e,message:"must be zero or greater"})}function R(t,e,n,o){let i=new Set(e);for(let r of Object.keys(t))i.has(r)||o.push({path:n==="$"?r:`${n}.${r}`,message:"unknown field"})}function q(t,e,n){for(let o=0;o<t.length;o+=1)o in t||n.push({path:`${e}[${o}]`,message:"must be a value"})}function At(t,e,n){(typeof t!="string"||!/^#(?:[\da-f]{3}|[\da-f]{4}|[\da-f]{6}|[\da-f]{8})$/i.test(t))&&n.push({path:e,message:"must be a hexadecimal color"})}function cn(t,e,n){if(t!==void 0){if(!T(t)){n.push({path:e,message:"must be an object"});return}R(t,["fill","stroke","strokeWidth","textColor","dashed"],e,n);for(let o of["fill","stroke","textColor"])t[o]!==void 0&&At(t[o],`${e}.${o}`,n);t.strokeWidth!==void 0&&Q(t.strokeWidth,`${e}.strokeWidth`,n),t.dashed!==void 0&&typeof t.dashed!="boolean"&&n.push({path:`${e}.dashed`,message:"must be a boolean"})}}function hn(t,e,n){if(t!==void 0){if(!T(t)){n.push({path:e,message:"must be an object"});return}R(t,["stroke","strokeWidth","dashed"],e,n),t.stroke!==void 0&&At(t.stroke,`${e}.stroke`,n),t.strokeWidth!==void 0&&Q(t.strokeWidth,`${e}.strokeWidth`,n),t.dashed!==void 0&&typeof t.dashed!="boolean"&&n.push({path:`${e}.dashed`,message:"must be a boolean"})}}function oe(t,e,n,o){if(!C(t)){o.push({path:e,message:"must reference an existing node"});return}n.get(t)||o.push({path:e,message:"must reference an existing node"})}function un(t,e,n){let o=new Set;for(let[i,r]of e){let s=new Set,a=i;for(;a;){if(s.has(a)){let u=t.findIndex(c=>T(c)&&c.id===i),h=u>=0?`nodes[${u}].parentId`:"nodes.parentId";o.has(h)||(n.push({path:h,message:"group parent references form a cycle"}),o.add(h));break}s.add(a);let l=e.get(a)?.parentId;a=C(l)?l:void 0}}}function dn(t,e,n,o,i,r){if(!T(t)){r.push({path:e,message:"must be an object"});return}if(R(t,["durationMs","transitionMs","caption","actions"],e,r),Z(t.durationMs,`${e}.durationMs`,r),t.transitionMs!==void 0&&(Q(t.transitionMs,`${e}.transitionMs`,r),typeof t.durationMs=="number"&&Number.isFinite(t.durationMs)&&typeof t.transitionMs=="number"&&Number.isFinite(t.transitionMs)&&t.transitionMs>t.durationMs&&r.push({path:`${e}.transitionMs`,message:"must not exceed durationMs"})),t.caption!==void 0&&typeof t.caption!="string"&&r.push({path:`${e}.caption`,message:"must be a string"}),!Array.isArray(t.actions)){r.push({path:`${e}.actions`,message:"must be an array"});return}q(t.actions,`${e}.actions`,r);let s=new Set;t.actions.forEach((a,l)=>fn(a,`${e}.actions[${l}]`,n,o,i,s,r))}function fn(t,e,n,o,i,r,s){if(!T(t)){s.push({path:e,message:"must be an object"});return}if(typeof t.type!="string"){s.push({path:`${e}.type`,message:"must be a supported action"});return}let a=t.type,l={show:["type","target"],hide:["type","target"],highlight:["type","target"],unhighlight:["type","target"],updateNode:["type","target","value"],updateEdge:["type","target","value"],focus:["type","target"],flow:["type","target","direction","text","highlightParticipants"]},u=Object.hasOwn(l,a)?l[a]:void 0;if(!u){s.push({path:`${e}.type`,message:"unknown action"});return}if(R(t,u,e,s),["show","hide","highlight","unhighlight"].includes(a)){if(!C(t.target)){s.push({path:`${e}.target`,message:"must reference an existing object"});return}n.has(t.target)||s.push({path:`${e}.target`,message:"must reference an existing object"}),rt(`${a==="show"||a==="hide"?"visibility":"highlight"}:${t.target}`,e,r,s);return}if(a==="focus"){t.target!==null&&(!C(t.target)||!o.has(t.target))&&s.push({path:`${e}.target`,message:"must reference a node or group"}),(t.target===null||C(t.target)&&o.has(t.target))&&rt("focus",e,r,s);return}if(a==="flow"){C(t.target)?i.has(t.target)||s.push({path:`${e}.target`,message:"must reference an existing edge"}):s.push({path:`${e}.target`,message:"must reference an existing edge"}),t.direction!=="forward"&&t.direction!=="reverse"&&s.push({path:`${e}.direction`,message:"must be forward or reverse"}),t.text!==void 0&&typeof t.text!="string"&&s.push({path:`${e}.text`,message:"must be a string"}),t.highlightParticipants!==void 0&&typeof t.highlightParticipants!="boolean"&&s.push({path:`${e}.highlightParticipants`,message:"must be a boolean"}),C(t.target)&&i.has(t.target)&&rt(`flow:${t.target}`,`${e}.target`,r,s);return}C(t.target)?(a==="updateNode"?!o.has(t.target):!i.has(t.target))&&s.push({path:`${e}.target`,message:`must reference an existing ${a==="updateNode"?"node":"edge"}`}):s.push({path:`${e}.target`,message:`must reference a ${a==="updateNode"?"node":"edge"}`}),mn(t.value,`${e}.value`,a==="updateNode",r,t.target,s);let h=typeof t.target=="string"?o.get(t.target):void 0;a==="updateNode"&&h&&T(t.value)&&t.value.content!==void 0&&t.value.content!==null&&!wt(h.kind)&&s.push({path:`${e}.value.content`,message:"requires a rect, roundedRect or cylinder node"})}function mn(t,e,n,o,i,r){if(!T(t)){r.push({path:e,message:"must be an object"});return}let s=n?["x","y","width","height","label","content","fill","stroke","opacity"]:["label","stroke","strokeWidth","opacity"];R(t,s,e,r),n&&Object.hasOwn(t,"label")&&Object.hasOwn(t,"content")&&r.push({path:`${e}.content`,message:"must not be declared together with label"});for(let a of Object.keys(t)){if(!s.includes(a))continue;let l=n&&(a==="label"||a==="content")?"text-mode":a;rt(`${n?"node":"edge"}:${String(i)}:${l}`,`${e}.${a}`,o,r);let u=t[a];["x","y","width","height","opacity"].includes(a)&&J(u,`${e}.${a}`,r),a==="strokeWidth"&&Q(u,`${e}.${a}`,r),["width","height"].includes(a)&&typeof u=="number"&&u<=0&&r.push({path:`${e}.${a}`,message:"must be greater than zero"}),a==="opacity"&&typeof u=="number"&&(u<0||u>1)&&r.push({path:`${e}.${a}`,message:"must be between zero and one"}),["fill","stroke"].includes(a)&&At(u,`${e}.${a}`,r),a==="label"&&typeof u!="string"&&r.push({path:`${e}.${a}`,message:"must be a string"}),a==="content"&&u!==null&&$t(u,`${e}.${a}`,r)}}function rt(t,e,n,o){n.has(t)?o.push({path:e,message:"duplicate beat assignment"}):n.add(t)}var gn=250,re=200,pn=100,Et=200,yn=re+pn+Et,xn=["x","y","width","height","opacity","strokeWidth"],bn=2,tt=class{totalDuration;schedule;beats;initial;title;constructor(e,n=new Map){this.initial=new Map([...e.nodes.map(l=>[l.id,{visible:l.visible!==!1,highlighted:!1,kind:"node",values:{x:l.x,y:l.y,width:l.width,height:l.height,label:l.label,content:l.content,fill:l.style?.fill,stroke:l.style?.stroke,opacity:1}}]),...e.edges.map(l=>[l.id,{visible:l.visible!==!1,highlighted:!1,kind:"edge",values:{label:l.label,stroke:l.style?.stroke,strokeWidth:l.style?.strokeWidth??bn,opacity:1}}])]),this.title=e.title;let o=[],i=this.initial,r=null,s=0,a=e.title;for(let[l,u]of e.scenes.entries())u.beats.forEach((h,c)=>{let f=new Map(i),d=r,g=[];for(let w of h.actions){if(w.type==="flow"){g.push({target:w.target,direction:w.direction,highlightParticipants:w.highlightParticipants??!0,...w.text!==void 0?{text:w.text}:{}});continue}if(w.type==="focus"){r=w.target;continue}let M=f.get(w.target);if(M)if(w.type==="updateNode"||w.type==="updateEdge"){let A=w.type!=="updateNode"?{}:Object.hasOwn(w.value,"content")?{label:void 0}:Object.hasOwn(w.value,"label")?{content:void 0}:{};f.set(w.target,{...M,values:{...M.values,...A,...w.value}})}else f.set(w.target,w.type==="show"||w.type==="hide"?{...M,visible:w.type==="show"}:{...M,highlighted:w.type==="highlight"})}a=h.caption??a;let m=`${u.id}:${c}`,y=n.get(m)??h.durationMs,x=n.has(m)?y+yn:h.durationMs,b=s+x,P=Math.min(x,h.transitionMs??Math.min(gn,h.durationMs));if(!Number.isFinite(y)||!Number.isFinite(b))throw new k([{path:`scenes[${l}].beats[${c}].durationMs`,message:"effective beat timing must be finite"}]);o.push({startMs:s,endMs:b,movementMs:y,transitionMs:P,sceneId:u.id,beatId:m,beatIndex:c,caption:a,focusBefore:d,focusAfter:r,before:i,after:f,flows:g}),i=f,s=b});this.beats=o,this.schedule=Object.freeze(o.map(({sceneId:l,beatId:u,beatIndex:h,startMs:c,endMs:f,caption:d})=>Object.freeze({sceneId:l,beatId:u,beatIndex:h,startMs:c,endMs:f,...d!==void 0?{caption:d}:{}}))),this.totalDuration=s}evaluateAt(e,n,o){let i=Number.isFinite(e)?Math.max(0,Math.min(e,this.totalDuration)):0,r=this.findBeat(i),s=!r||n.reducedMotion||r.transitionMs===0?1:vt(Math.min(1,(i-r.startMs)/r.transitionMs)),a=r?.before??this.initial,l=r?.after??this.initial,u=new Map([...l].map(([h,c])=>{let f=a.get(h)??c,d=wn(f,c,s,o),g=Number(f.visible)+(Number(c.visible)-Number(f.visible))*s;return[h,{values:d,visible:c.visible||f.visible&&s<1,opacity:Math.min(d.opacity??1,g),highlighted:c.highlighted,highlight:Number(f.highlighted)+(Number(c.highlighted)-Number(f.highlighted))*s}]}));return{timeMs:i,sceneId:r?.sceneId??null,beatId:r?.beatId??null,beatProgress:r?(i-r.startMs)/(r.endMs-r.startMs):0,flowProgress:r?Math.min(1,(i-r.startMs)/r.movementMs):0,flowArrivalProgress:!r||n.reducedMotion||r.flows.length!==1?1:vt(Math.max(0,Math.min(1,(i-r.startMs-r.movementMs)/re))),flowDepartureProgress:!r||n.reducedMotion||r.flows.length!==1?0:vt(Math.max(0,Math.min(1,(i-r.endMs+Et)/Et))),transitionProgress:s,focusBefore:r?.focusBefore??null,focusAfter:r?.focusAfter??null,caption:r?.caption??this.title,objects:u,flows:r&&i<r.endMs?r.flows:[]}}findBeat(e){let n=0,o=this.beats.length-1;for(;n<o;){let i=Math.floor((n+o)/2);e<this.beats[i].endMs?o=i:n=i+1}return this.beats[n]}};function vt(t){return t<.5?4*t**3:1-(-2*t+2)**3/2}function wn(t,e,n,o){if(n===0)return{...t.values,label:e.values.label,content:e.values.content};if(n===1)return{...e.values};let i=Object.fromEntries(xn.flatMap(s=>{let a=t.values[s],l=e.values[s];return a===void 0||l===void 0?[]:[[s,a*(1-n)+l*n]]})),r=e.kind==="node"?o.stroke:o.edge;return{...e.values,...i,fill:H(t.values.fill??o.fill,e.values.fill??o.fill,n),stroke:H(t.values.stroke??r,e.values.stroke??r,n)}}var $n={background:"#ffffff",fill:"#ffffff",stroke:"#cfd8e3",text:"#1d2939",mutedText:"#5a6473",tagText:"#1d4fa8",tagFill:"#eaf1ff",accentText:"#1d4fa8",edge:"#8892a4",highlight:"#2a63c8",highlightFill:"#eaf1ff",highlightText:"#ffffff"},Mn={background:"#101828",fill:"#1d2939",stroke:"#475467",text:"#f2f4f7",mutedText:"#b8c2d1",tagText:"#caddff",tagFill:"#253b5c",accentText:"#9bbfff",edge:"#98a2b3",highlight:"#8ab4f8",highlightFill:"#233b60",highlightText:"#101828"},st=1.2,se=8,at='system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif';function lt(t){return t==="dark"?Mn:$n}function p(t){return Number.isInteger(t)?String(t):String(Number(t.toFixed(3)))}function Pn(t,e){let n={x:t.x+t.width/2,y:t.y+t.height/2},o={x:e.x+e.width/2,y:e.y+e.height/2},i=de(t,o),r=de(e,n);return[i,r]}var D=8,An=24,fe=24,Tt=12,ae=16,vn=.002,En=16,le=1e3,In=14,Y=7;function ft(){return V([])}function V(t,e,n,o){let i=mt(t),r=e??Wn(i),s=i.slice(1).map((c,f)=>({start:i[f],end:c,length:Math.hypot(c.x-i[f].x,c.y-i[f].y)})),a=s.reduce((c,f)=>c+f.length,0),l=i.map(c=>c.x),u=i.map(c=>c.y),h=l.length===0?{left:0,top:0,right:0,bottom:0}:{left:Math.min(...l),top:Math.min(...u),right:Math.max(...l),bottom:Math.max(...u)};return{path:r,points:i,length:a||1,terminalDirection:Tn(i,n),paintedBottom:o??h.bottom,bounds:h,pointAt(c){if(i.length===0)return{x:0,y:0};if(i.length===1||a===0)return i[0];let f=Math.min(1,Math.max(0,c))*a,d=0;for(let g of s){if(f<=d+g.length){let m=g.length===0?0:(f-d)/g.length;return{x:g.start.x+(g.end.x-g.start.x)*m,y:g.start.y+(g.end.y-g.start.y)*m}}d+=g.length}return i.at(-1)}}}function Tn(t,e){let n=t.at(-1),o=e??t.at(-2);if(!n||!o)return{x:1,y:0};let i=n.x-o.x,r=n.y-o.y,s=Math.hypot(i,r);return s>0?{x:i/s,y:r/s}:{x:1,y:0}}function Cn(t,e,n){let o=mt(t);if(o.length<3)return V(o);let i=[o[0]],r=[`M ${p(o[0].x)} ${p(o[0].y)}`],s=Math.max(fe,n*Y+D);for(let l=1;l<o.length-1;l+=1){let u=o[l-1],h=o[l],c=o[l+1],f=Math.hypot(h.x-u.x,h.y-u.y),d=Math.hypot(c.x-h.x,c.y-h.y),m=(h.x-u.x)*(c.x-h.x)+(h.y-u.y)*(c.y-h.y)===0?Math.max(0,Math.min(Tt,f/2,d/2,l===o.length-2?d-Math.min(s,d):Tt)):0,y=Sn(h,u,c,m,e,n/2),x=ht(h,u,y),b=ht(h,c,y);if(r.push(`L ${p(x.x)} ${p(x.y)}`),i.push(x),y!==0){r.push(`Q ${p(h.x)} ${p(h.y)} ${p(b.x)} ${p(b.y)}`);for(let P=1;P<=ae;P+=1){let w=P/ae,M=1-w;i.push({x:M**2*x.x+2*M*w*h.x+w**2*b.x,y:M**2*x.y+2*M*w*h.y+w**2*b.y})}}}let a=o.at(-1);return r.push(`L ${p(a.x)} ${p(a.y)}`),i.push(a),V(i,r.join(" "))}function ht(t,e,n){let o=Math.hypot(e.x-t.x,e.y-t.y);return{x:t.x+(e.x-t.x)/o*n,y:t.y+(e.y-t.y)/o*n}}function Sn(t,e,n,o,i,r){let s=u=>{let h=ht(t,e,u),c=ht(t,n,u),f=r+vn;return!i.some(d=>Math.min(h.x,t.x,c.x)<d.right+f&&Math.max(h.x,t.x,c.x)>d.left-f&&Math.min(h.y,t.y,c.y)<d.bottom+f&&Math.max(h.y,t.y,c.y)>d.top-f)};if(o===0||!s(0))return 0;if(s(o))return o;let a=0,l=o;for(let u=0;u<En;u+=1){let h=(a+l)/2;s(h)?a=h:l=h}return Math.floor(a*le)/le}function _n(t,e,n,o){let i=[];for(let a=0;a<=32;a+=1){let l=a/32,u=1-l;i.push({x:u**3*t.x+3*u**2*l*e.x+3*u*l**2*n.x+l**3*o.x,y:u**3*t.y+3*u**2*l*e.y+3*u*l**2*n.y+l**3*o.y})}let s=`M ${p(t.x)} ${p(t.y)} C ${p(e.x)} ${p(e.y)} ${p(n.x)} ${p(n.y)} ${p(o.x)} ${p(o.y)}`;return V(i,s,n,Ct(t,e,n,o))}function Ct(t,e,n,o){let i=Math.max(Math.abs(t.y),Math.abs(e.y),Math.abs(n.y),Math.abs(o.y),1),r=t.y/i,s=e.y/i,a=n.y/i,l=o.y/i,u=-r+3*s-3*a+l,h=2*(r-2*s+a),c=s-r,f=h*h-4*u*c,d=u===0?h===0?[]:[-c/h]:f<0?[]:[(-h-Math.sqrt(f))/(2*u),(-h+Math.sqrt(f))/(2*u)],g=Math.max(t.y,o.y);for(let m of d){if(m<=0||m>=1)continue;let y=1-m,x=y**3*t.y+3*y**2*m*e.y+3*y*m**2*n.y+m**3*o.y;g=Math.max(g,x)}return g}function Dn(t,e,n,o,i,r,s){let a=[],l=(h,c,f,d)=>{for(let g=0;g<=16;g+=1){if(a.length>0&&g===0)continue;let m=g/16,y=1-m;a.push({x:y**3*h.x+3*y**2*m*c.x+3*y*m**2*f.x+m**3*d.x,y:y**3*h.y+3*y**2*m*c.y+3*y*m**2*f.y+m**3*d.y})}};l(t,e,o,n),l(n,i,r,s);let u=`M ${p(t.x)} ${p(t.y)} C ${p(e.x)} ${p(e.y)} ${p(o.x)} ${p(o.y)} ${p(n.x)} ${p(n.y)} C ${p(i.x)} ${p(i.y)} ${p(r.x)} ${p(r.y)} ${p(s.x)} ${p(s.y)}`;return V(a,u,r,Math.max(Ct(t,e,o,n),Ct(n,i,r,s)))}function me(t,e,n){for(let o=1;o<e.points.length;o+=1)if(Nn(t,e.points[o-1],e.points[o])<=n)return!0;return!1}function Nn(t,e,n){let o=n.x-e.x,i=n.y-e.y;if(o===0&&i===0)return Math.hypot(t.x-e.x,t.y-e.y);let r=Math.max(0,Math.min(1,((t.x-e.x)*o+(t.y-e.y)*i)/(o*o+i*i)));return Math.hypot(t.x-(e.x+r*o),t.y-(e.y+r*i))}function ge(t,e,n,o,i){if(t.route==="curved"){let s=nt(e,n),a=t.fromPort??s.from,l=t.toPort??s.to,u=z(e,a),h=z(n,l,i.targetOffset);return Gn(u,h,a,l,i.reverseOffset)}if(t.route!=="orthogonal"){let s=t.fromPort||t.toPort?[z(e,t.fromPort??nt(e,n).from),z(n,t.toPort??nt(e,n).to)]:Pn(e,n);return V(s)}let r=o.filter(s=>s.visible&&s.kind!=="group"&&s.id!==e.id&&s.id!==n.id).map(U);return Cn(On(t,e,n,r,i.targetOffset,o),[...r,U(e),U(n)],t.style?.strokeWidth??2)}function pe(t,e){let n=new Map;for(let i of t){if(i.route!=="orthogonal"&&i.route!=="curved")continue;let r=e.get(i.from),s=e.get(i.to);if(!r||!s)continue;let a=i.toPort??nt(r,s).to,l=JSON.stringify([s.id,a]),u=n.get(l),h=a==="top"||a==="bottom"?r.x+r.width/2:r.y+r.height/2;n.set(l,{node:s,side:a,inputs:[...u?.inputs??[],{id:i.id,position:h}]})}let o=new Map;for(let{node:i,side:r,inputs:s}of n.values()){let a=r==="top"||r==="bottom"?i.width:i.height,l=Math.min(An,a/(2*s.length));[...s].sort((u,h)=>u.position-h.position).forEach((u,h)=>o.set(u.id,(h-(s.length-1)/2)*l))}return o}function U(t){return{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height}}function It(t,e,n=D){return{left:t.left-(e==="left"?n:D),top:t.top-(e==="top"?n:D),right:t.right+(e==="right"?n:D),bottom:t.bottom+(e==="bottom"?n:D)}}function On(t,e,n,o,i,r){let s=nt(e,n),a=t.fromPort??s.from,l=t.toPort??s.to,u=z(e,a),h=z(n,l,i),c=Math.max(fe,(t.style?.strokeWidth??2)*Y+D),f=U(e),d=U(n),g=ce(ct(u,a,f),a,D,[...o,d]),m=ce(ct(h,l,d),l,c+Tt,[...o,f]),y=It(f,a,g),x=It(d,l,m),b=ct(u,a,y),P=ct(h,l,x),w=[...o.map(S=>It(S)),y,x],M=Rn(b,P,a,l,[f,d,...Ln(e,n,r)],c),v=M&&M.every((S,E)=>E===0||!dt(M[E-1],S,w))?M:kn(b,P,w);return[u,...v,h]}function Rn(t,e,n,o,i,r){let s=n==="top"||n==="bottom";if(s!==(o==="top"||o==="bottom"))return;let a=s?"y":"x",l=ut(n),u=s?l.y:l.x,h;if(n===o){let c=s?u<0?"top":"bottom":u<0?"left":"right",f=i.map(g=>g[c]),d=(u<0?Math.min(...f):Math.max(...f))+u*r;h=u<0?Math.min(d,t[a],e[a]):Math.max(d,t[a],e[a])}else{if((e[a]-t[a])*u<0)return;let c=i[0],f=i[1],d=s?u<0?c.top:c.bottom:u<0?c.left:c.right,g=s?u<0?f.bottom:f.top:u<0?f.right:f.left,m=(d+g)/2;h=Math.max(Math.min(t[a],e[a]),Math.min(Math.max(t[a],e[a]),m))}return mt([t,{...t,[a]:h},{...e,[a]:h},e])}function Ln(t,e,n){let o=new Map(n.map(u=>[u.id,u])),i=u=>{let h=[],c=u.parentId?o.get(u.parentId):void 0;for(;c;)h.push(c),c=c.parentId?o.get(c.parentId):void 0;return h},r=i(t),s=i(e),a=new Set([t.id,...r.map(({id:u})=>u)]),l=new Set([e.id,...s.map(({id:u})=>u)]);return[...r.filter(({id:u})=>!l.has(u)),...s.filter(({id:u})=>!a.has(u))].map(U)}function ce(t,e,n,o){let i=e==="top"||e==="bottom",r=ut(e);return o.reduce((s,a)=>{let l=i?t.x:t.y,u=i?a.left:a.top,h=i?a.right:a.bottom;if(l<u-D||l>h+D)return s;let c=i?(e==="top"?a.bottom-t.y:a.top-t.y)*r.y:(e==="left"?a.right-t.x:a.left-t.x)*r.x;return c<0?s:Math.min(s,Math.max(c-D,c/2))},n)}function ct(t,e,n){return e==="top"?{x:t.x,y:n.top}:e==="bottom"?{x:t.x,y:n.bottom}:e==="left"?{x:n.left,y:t.y}:{x:n.right,y:t.y}}function nt(t,e){let n={x:t.x+t.width/2,y:t.y+t.height/2},o={x:e.x+e.width/2,y:e.y+e.height/2};if(Math.abs(o.x-n.x)>=Math.abs(o.y-n.y)){let s=o.x>=n.x;return{from:s?"right":"left",to:s?"left":"right"}}let r=o.y>=n.y;return{from:r?"bottom":"top",to:r?"top":"bottom"}}function z(t,e,n=0){let o={x:t.x+t.width/2,y:t.y+t.height/2},i=e==="top"||e==="bottom",r=(i?t.width:t.height)/2,s=Math.sqrt(Math.max(0,1-(n/r)**2)),a=t.kind==="ellipse"?(i?t.height:t.width)/2*(1-s):t.kind==="cylinder"&&i?Math.min(In,t.height/4)*(1-s):0;return e==="top"?{x:o.x+n,y:t.y+a}:e==="right"?{x:t.x+t.width-a,y:o.y+n}:e==="bottom"?{x:o.x+n,y:t.y+t.height-a}:{x:t.x+a,y:o.y+n}}function Gn(t,e,n,o,i){let r=Math.hypot(e.x-t.x,e.y-t.y),s=Math.max(24,r*.32),a=ut(n),l=ut(o),u={x:-(e.y-t.y),y:e.x-t.x},h=Math.hypot(u.x,u.y)||1,c=i*Math.min(72,Math.max(28,r*.16));if(i!==0){let g={x:(t.x+e.x)/2+u.x/h*c,y:(t.y+e.y)/2+u.y/h*c},m={x:e.x-t.x,y:e.y-t.y},y=Math.hypot(m.x,m.y)||1,x={x:m.x/y,y:m.y/y};return Dn(t,{x:t.x+a.x*s,y:t.y+a.y*s},g,{x:g.x-x.x*s*.5,y:g.y-x.y*s*.5},{x:g.x+x.x*s*.5,y:g.y+x.y*s*.5},{x:e.x+l.x*s,y:e.y+l.y*s},e)}let f={x:t.x+a.x*s+u.x/h*c,y:t.y+a.y*s+u.y/h*c},d={x:e.x+l.x*s+u.x/h*c,y:e.y+l.y*s+u.y/h*c};return _n(t,f,d,e)}function ut(t){return t==="top"?{x:0,y:-1}:t==="right"?{x:1,y:0}:t==="bottom"?{x:0,y:1}:{x:-1,y:0}}function kn(t,e,n){let o=ue([t.x,e.x,...n.flatMap(g=>[g.left,g.right])]),i=ue([t.y,e.y,...n.flatMap(g=>[g.top,g.bottom])]),r=new Map(o.map((g,m)=>[g,m])),s=new Map(i.map((g,m)=>[g,m])),a=et(t),l=et(e),u=[t],h=new Map([[a,void 0]]),c=Math.abs(e.x-t.x)>=Math.abs(e.y-t.y),f=c?[[1,0],[0,-1],[0,1],[-1,0]]:[[0,1],[1,0],[-1,0],[0,-1]];for(;u.length>0;){let g=u.shift();if(et(g)===l)break;let m=r.get(g.x),y=s.get(g.y);if(!(m===void 0||y===void 0))for(let[x,b]of f){let P=o[m+x],w=i[y+b];if(P===void 0||w===void 0)continue;let M={x:P,y:w},A=et(M);h.has(A)||ye(M,n)||dt(g,M,n)||(h.set(A,g),u.push(M))}}let d=[];if(h.has(l)){let g=e;for(;g;)d.push(g),g=h.get(et(g));d.reverse()}else{let g=c?{x:e.x,y:t.y}:{x:t.x,y:e.y};d.push(t,g,e)}return Fn(d,n)}function Fn(t,e){let n=[...t],o=D*2;for(let i=1;i+2<n.length;i+=1){let r=n[i-1],s=n[i],a=n[i+1],l=n[i+2];if(Math.abs(a.x-s.x)+Math.abs(a.y-s.y)>=o)continue;let h=r.x===s.x?{x:s.x,y:l.y}:{x:l.x,y:s.y};ye(h,e)||dt(r,h,e)||dt(h,l,e)||(n.splice(i,2,h),i=Math.max(0,i-2))}return n}function Wn(t){return mt(t).map((e,n)=>`${n===0?"M":"L"} ${p(e.x)} ${p(e.y)}`).join(" ")}function mt(t){let e=[];for(let o of t){let i=e.at(-1);(!i||i.x!==o.x||i.y!==o.y)&&e.push(o)}let n=[];for(let o of e){let i=n.at(-1),r=n.at(-2),s=i&&r&&(i.x-r.x)*(o.x-i.x)+(i.y-r.y)*(o.y-i.y)>=0;i&&r&&s&&(r.x===i.x&&i.x===o.x||r.y===i.y&&i.y===o.y)?n[n.length-1]=o:n.push(o)}return n}function dt(t,e,n){for(let o of n)if(t.x===e.x){if(t.x>o.left&&t.x<o.right&&he(t.y,e.y,o.top,o.bottom))return!0}else if(t.y===e.y&&t.y>o.top&&t.y<o.bottom&&he(t.x,e.x,o.left,o.right))return!0;return!1}function ye(t,e){return e.some(n=>t.x>n.left&&t.x<n.right&&t.y>n.top&&t.y<n.bottom)}function he(t,e,n,o){return Math.max(Math.min(t,e),n)<Math.min(Math.max(t,e),o)}function et(t){return`${t.x},${t.y}`}function ue(t){return[...new Set(t)].sort((e,n)=>e-n)}function de(t,e){let n={x:t.x+t.width/2,y:t.y+t.height/2},o=e.x-n.x,i=e.y-n.y;if(o===0&&i===0)return n;let r=o/(t.width/2),s=i/(t.height/2),a=1/(t.kind==="ellipse"?Math.hypot(r,s):Math.max(Math.abs(r),Math.abs(s)));return{x:n.x+o*a,y:n.y+i*a}}function xe(t){let e=t.points;if(e.length<2)return{x:0,y:-12};let n={start:e[0],end:e[1],length:0};for(let i=1;i<e.length;i+=1){let r=e[i-1],s=e[i],a=Math.hypot(s.x-r.x,s.y-r.y);a>n.length&&(n={start:r,end:s,length:a})}let o=n.start.y===n.end.y;return{x:(n.start.x+n.end.x)/2+(o?0:20),y:(n.start.y+n.end.y)/2+(o?-12:0)}}function Nt(t){let e=ie(t);if(e.length>0)throw new k(e);return new Dt(so(t))}var Dt=class{totalDuration;beats;timeline;document;nodesById;constructor(e){this.document=_e(e),this.nodesById=new Map(e.nodes.map(r=>[r.id,r]));let n=new tt(e),o=new Map,i=0;for(let[r,s]of e.scenes.entries())s.beats.forEach((a,l)=>{let u=a.actions.filter(h=>h.type==="flow");if(u.length===1){let h=this.evaluateFrame(i,{reducedMotion:!0},n).edgeGeometries.get(u[0].target);if(!Number.isFinite(h.length)||h.points.some(c=>!Number.isFinite(c.x)||!Number.isFinite(c.y)))throw new k([{path:`scenes[${r}].beats[${l}].durationMs`,message:"effective beat timing must be finite"}]);o.set(`${s.id}:${l}`,Math.max(zn,h.length/Bn*Un))}i+=a.durationMs});this.timeline=new tt(e,o),this.totalDuration=this.timeline.totalDuration,this.beats=this.timeline.schedule}evaluateAt(e,n={}){return this.evaluateFrame(e,n).frame}evaluateFrame(e,n={},o=this.timeline){let i=Ie(this.document,n),r=o.evaluateAt(e,n,i),s=new Map(this.document.nodes.map(m=>{let y=r.objects.get(m.id).values;return[m.id,{...m,x:y.x??m.x,y:y.y??m.y,width:y.width??m.width,height:y.height??m.height,label:y.label,content:y.content??void 0}]})),a=Vn(r.flows,this.document.edges,r.flowArrivalProgress,r.flowDepartureProgress),l=[],u=[...s.values()].map((m,y)=>{let x=this.resolvePosition(m.id,s),b=m.label?be(m.label,Math.max(1,m.width-St*2),G):[],P=m.kind==="group"?x.y+24:x.y+m.height/2,w=we(b,x.x+m.width/2,P,G);m.label&&b.length*G.lineHeight>Math.max(0,m.height-St*2)&&l.push({path:`nodes[${y}].label`,objectId:m.id,code:"text-overflow",message:`label for node "${m.id}" exceeds its height`});let M=this.resolveVisibility(m.id,r.objects),A=r.objects.get(m.id),v=Math.max(A.highlight,a.get(m.id)??0),S={strokeWidth:st,textColor:i.text,...m.style,fill:H(A.values.fill??i.fill,i.highlightFill,v),stroke:H(A.values.stroke??i.stroke,i.highlight,v)},E=m.content?ee(zt(m.content,{...x,width:m.width,height:m.height},i,m.kind),v,S.fill):void 0;if(E)for(let _ of["width","height"])E[_==="width"?"widthOverflow":"heightOverflow"]&&l.push({path:`nodes[${y}].content`,objectId:m.id,code:"text-overflow",message:`content for node "${m.id}" exceeds its ${_}`});return{...m,contentLayout:E,...M,highlighted:A.highlighted||a.has(m.id),style:S,x:x.x,y:x.y,labelLines:b,labelBoxes:w}}),h=new Map(u.map(m=>[m.id,m])),c=pe(this.document.edges,h),f=new Map,d=this.document.edges.map(m=>{let y=r.objects.get(m.id),x=r.flows.find(j=>j.target===m.id),b={...m,label:y.values.label},P=h.get(b.from),w=h.get(b.to),M=y.visible&&!!(P?.visible&&w?.visible),A=Math.min(y.opacity,P?.opacity??0,w?.opacity??0),v={...b.style,strokeWidth:y.values.strokeWidth??b.style?.strokeWidth??2,dashed:b.style?.dashed??!1,stroke:H(y.values.stroke??i.edge,i.highlight,Math.max(y.highlight,+(x!==void 0)*(1-r.flowDepartureProgress)))},E=b.route==="curved"&&this.document.edges.some(j=>j.id!==b.id&&j.route==="curved"&&j.from===b.to&&j.to===b.from)?1:0,_=P&&w?ge({...b,style:v},P,w,u,{reverseOffset:E,targetOffset:c.get(b.id)??0}):ft();f.set(b.id,_);let Wt=b.label?be(b.label,Math.max(1,_.length-St*2),gt):[],Ht=xe(_),jt=x&&M&&A>0&&!n.reducedMotion?{direction:x.direction,progress:r.flowProgress,point:_.pointAt(x.direction==="forward"?r.flowProgress:1-r.flowProgress),...x.text!==void 0?{text:x.text}:{}}:void 0;return{...b,visible:M,opacity:A,highlighted:y.highlighted||x!==void 0,style:v,path:_.path,labelLines:Wt,labelBoxes:we(Wt,Ht.x,Ht.y,gt),...jt?{flow:jt}:{}}}),g=Qn(this.document.viewport,r.focusBefore,r.focusAfter,r.transitionProgress,u,d,f);return{frame:{timeMs:r.timeMs,sceneId:r.sceneId,beatId:r.beatId,beatProgress:r.beatProgress,nodes:u,edges:d,camera:g,warnings:l,...r.caption!==void 0?{caption:r.caption}:{}},edgeGeometries:f}}renderSvg(e=0,n={}){let o=this.evaluateAt(e,n),i=Ie(this.document,n);return Yn(this.document,o,i)}hitTest(e,n,o={}){if(!Number.isFinite(n.x)||!Number.isFinite(n.y))return null;let i=this.evaluateFrame(e,o),r=i.frame,s=[...r.nodes].reverse(),a=c=>c.visible&&c.opacity>0&&ro(n,c),l=s.find(c=>c.kind!=="group"&&a(c));if(l)return{id:l.id,type:"node"};let u=[...r.edges].reverse().find(c=>c.visible&&c.opacity>0&&me(n,i.edgeGeometries.get(c.id)??ft(),(c.style?.strokeWidth??2)+Jn));if(u)return{id:u.id,type:"edge"};let h=s.find(c=>c.kind==="group"&&a(c));return h?{id:h.id,type:"node"}:null}resolvePosition(e,n){let o=n.get(e);if(!o)return{x:0,y:0};let i=o.parentId?this.resolvePosition(o.parentId,n):{x:0,y:0};return{x:o.x+i.x,y:o.y+i.y}}resolveVisibility(e,n){let o=this.nodesById.get(e),i=n.get(e);if(!o?.parentId)return{visible:i.visible,opacity:i.opacity};let r=this.resolveVisibility(o.parentId,n);return{visible:i.visible&&r.visible,opacity:Math.min(i.opacity,r.opacity)}}},St=12,Hn=3,G={fontSize:16,lineHeight:20,charWidth:8.5},gt={fontSize:14,lineHeight:18,charWidth:8.4},Te=.25,_t={fontSize:12,lineHeight:16,charWidth:7.2},ot=24,jn=10,Ce=5,Bn=180,zn=400,Un=1e3;function be(t,e,n=G){let o=Math.max(1,Math.floor(e/n.charWidth)),i=[];for(let r of t.split(`
2
+ `)){if(r.length===0){i.push("");continue}let s=Array.from(r);for(;s.length>o;){let l=s.slice(0,o+1).lastIndexOf(" "),u=l>0?l:o;i.push(s.slice(0,u).join("")),s=Array.from(s.slice(u).join("").replace(/^\s+/,""))}i.push(s.join(""))}return i}function Vn(t,e,n,o){let i=new Map,r=1-o;for(let s of t){if(!s.highlightParticipants)continue;let a=e.find(h=>h.id===s.target);if(!a)continue;let l=s.direction==="forward"?a.from:a.to,u=s.direction==="forward"?a.to:a.from;i.set(l,r),i.set(u,Math.max(i.get(u)??0,n*r))}return i}function we(t,e,n,o){let i=n-(t.length-1)*o.lineHeight/2+o.fontSize*.35;return t.map((r,s)=>({text:r,x:e,y:i+s*o.lineHeight}))}function Yn(t,e,n){let o=it(t.title??"Diagram"),i=e.edges.filter(d=>d.opacity>0).map(d=>{let g=d.style?.stroke??n.edge,m=d.style?.strokeWidth??2,y=d.style?.dashed?' stroke-dasharray="6 4"':"";return`<path d="${I(d.path)}" fill="none" stroke="${I(g)}" color="${I(g)}" stroke-width="${m}"${y} marker-end="url(#diagram-arrow)" data-id="${I(d.id)}" opacity="${d.opacity}"/>`}).join(""),r=e.nodes.filter(d=>d.opacity>0&&d.kind==="group").map(d=>$e(d,n)).join(""),s=e.nodes.filter(d=>d.opacity>0&&d.kind!=="group").map(d=>$e(d,n)).join(""),a=e.edges.filter(d=>d.opacity>0).map(d=>Me(d.labelLines,d.labelBoxes,d.style?.stroke??n.text,gt,d.opacity,n.background)).join("")+e.nodes.filter(d=>d.opacity>0).map(d=>Me(d.labelLines,d.labelBoxes,d.style?.textColor??n.text,G,d.opacity)).join(""),l=e.nodes.filter(d=>d.opacity>0&&d.contentLayout).map((d,g)=>Xn(d,g)).join(""),u=e.edges.filter(d=>d.opacity>0&&d.flow).map(d=>Kn(d.flow,d.id,n,d.opacity)).join(""),h=`<defs><marker id="diagram-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="${Y}" markerHeight="${Y}" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z" fill="context-stroke"/></marker></defs>`,c=I(t.title??"Diagram");return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${`${p(e.camera.x)} ${p(e.camera.y)} ${p(e.camera.width)} ${p(e.camera.height)}`}" role="img" aria-label="${c}" font-family="${I(at)}"><title>${o}</title>${h}<rect x="${p(e.camera.x)}" y="${p(e.camera.y)}" width="${p(e.camera.width)}" height="${p(e.camera.height)}" fill="${n.background}"/>${r}${i}${s}${a}${l}${u}</svg>`}function Xn(t,e){let n=t.contentLayout,o=n.safeArea,i=[o.x,o.y,o.width,o.height].map(h=>String(h).replaceAll("-","n").replaceAll(".","p").replaceAll("+","a")).join("-"),r=`diagram-content-clip-${e}-${i}`,s=`<defs><clipPath id="${r}" clipPathUnits="userSpaceOnUse"><rect x="${p(o.x)}" y="${p(o.y)}" width="${p(o.width)}" height="${p(o.height)}"/></clipPath></defs>`,a=n.tags.map(h=>`<rect x="${p(h.x)}" y="${p(h.y)}" width="${p(h.width)}" height="${p(h.height)}" rx="${p(h.shape==="pill"?h.height/2:Hn)}" fill="${I(h.fill)}"/>`).join(""),l=n.lines.map(h=>`<text x="${p(h.x)}" y="${p(h.y)}" fill="${I(h.color)}" font-size="${h.fontSize}" font-weight="${h.fontWeight}" text-anchor="${h.align==="left"?"start":h.align==="right"?"end":"middle"}">${h.spans.map(c=>`<tspan x="${p(c.x)}" y="${p(c.y)}" fill="${I(c.color)}" font-size="${c.fontSize}" font-weight="${c.fontWeight}" text-anchor="start">${it(c.text)}</tspan>`).join("")}</text>`).join(""),u=(n.graphs??[]).map(h=>`<g data-content-graph="${h.blockIndex}" aria-hidden="true">${h.edges.map(c=>`<line x1="${p(c.x1)}" y1="${p(c.y1)}" x2="${p(c.x2)}" y2="${p(c.y2)}" stroke="${c.color}"/>`).join("")}${h.nodes.map(c=>`<circle cx="${p(c.x)}" cy="${p(c.y)}" r="${c.radius}" fill="${c.fill}"/>`).join("")}</g>`).join("");return`${s}<g id="diagram-content-${e}" data-content-id="${I(t.id)}" clip-path="url(#${r})" opacity="${t.opacity}">${a}${u}${l}</g>`}function Kn(t,e,n,o){let i=`fill="${n.highlight}" data-flow-id="${I(e)}" opacity="${o}" pointer-events="none" aria-hidden="true"`;if(t.text===void 0)return`<circle cx="${p(t.point.x)}" cy="${p(t.point.y)}" r="${Ce}" ${i}/>`;let r=Math.max(ot,Se(t.text,_t)+jn*2),s=p(t.point.x-r/2),a=p(t.point.y-ot/2),l=`<text x="${p(t.point.x)}" y="${p(t.point.y+_t.fontSize*.35)}" fill="${n.highlightText}" font-size="${_t.fontSize}" text-anchor="middle">${it(t.text)}</text>`;return`<g ${i}><rect x="${s}" y="${a}" width="${p(r)}" height="${ot}" rx="${ot/2}"/>${l}</g>`}function Se(t,e){return Array.from(t).reduce((n,o)=>{let i=o.codePointAt(0)>255||"MWmw@%".includes(o);return n+(i?e.fontSize:e.charWidth)},0)}function $e(t,e){let n=t.style?.fill??e.fill,o=t.style?.stroke??e.stroke,i=t.style?.strokeWidth??st,r=t.kind==="group"&&t.style?.dashed?' stroke-dasharray="10 7"':"",s=`fill="${I(n)}" stroke="${I(o)}" stroke-width="${i}"${r} data-id="${I(t.id)}" opacity="${t.opacity}"`;if(t.kind==="ellipse")return`<ellipse cx="${p(t.x+t.width/2)}" cy="${p(t.y+t.height/2)}" rx="${p(t.width/2)}" ry="${p(t.height/2)}" ${s}/>`;if(t.kind==="cylinder"){let l=Math.min(14,t.height/4),u=t.y+t.height-l,h=`M ${p(t.x)} ${p(t.y+l)} L ${p(t.x+t.width)} ${p(t.y+l)} L ${p(t.x+t.width)} ${p(u)} A ${p(t.width/2)} ${p(l)} 0 0 1 ${p(t.x)} ${p(u)} Z`,c=`<ellipse cx="${p(t.x+t.width/2)}" cy="${p(t.y+l)}" rx="${p(t.width/2)}" ry="${p(l)}"/>`;return`<g ${s}><path d="${h}"/>${c}</g>`}let a=t.kind==="roundedRect"?` rx="${Math.min(se,t.width/4,t.height/4)}"`:"";return`<rect x="${p(t.x)}" y="${p(t.y)}" width="${p(t.width)}" height="${p(t.height)}"${a} ${s}/>`}function Me(t,e,n,o,i=1,r){if(t.length===0)return"";let s=e[0]?.x??0,a=t.map((u,h)=>`<tspan x="${p(s)}" y="${p(e[h]?.y??0)}">${it(u)}</tspan>`).join(""),l=r?` stroke="${I(r)}" stroke-width="6" stroke-linejoin="round" paint-order="stroke"`:"";return`<text fill="${I(n)}"${l} font-size="${o.fontSize}" text-anchor="middle" opacity="${i}">${a}</text>`}var Pe=24,Zn=1,qn=3,Jn=6;function Qn(t,e,n,o,i,r,s){let a={x:0,y:0,width:t.width,height:to(t,i,r,s)},l=ve(t,e,i,r,s)??a,u=ve(t,n,i,r,s)??a;return o<=0?l:o>=1?u:{x:l.x+(u.x-l.x)*o,y:l.y+(u.y-l.y)*o,width:l.width+(u.width-l.width)*o,height:l.height+(u.height-l.height)*o}}function to(t,e,n,o){if(!t.fitHeight)return t.height;let i=[];for(let a of e)if(!(a.opacity<=0)){i.push(a.y+a.height+(a.style?.strokeWidth??st)/2);for(let l of Ae(a.labelBoxes,G))i.push(l)}for(let a of n){if(a.opacity<=0)continue;let l=o.get(a.id);if(l){let u=a.style?.strokeWidth??2;i.push(l.paintedBottom+u/2,eo(l,u))}for(let u of Ae(a.labelBoxes,gt,qn))i.push(u);a.flow&&i.push(a.flow.point.y+(a.flow.text===void 0?Ce:ot/2))}if(i.length===0)return t.height;let r=i.reduce((a,l)=>Math.max(a,l),0),s=Math.max(Zn,Math.ceil(r+t.fitHeight.padding));if(!Number.isFinite(s))throw new k([{path:"viewport.fitHeight",message:"current painted geometry and padding must produce a finite height"}]);return s}function eo(t,e){let n=t.points.at(-1);if(!n)return 0;let o=t.terminalDirection,i=Y*e,r=Math.max(.1*o.y,-.9*o.y+.5*Math.abs(o.x));return n.y+i*r}function Ae(t,e,n=0){return t.filter(o=>o.text.length>0).map(o=>o.y+e.fontSize*Te+n)}function ve(t,e,n,o,i){if(!e||!n.find(b=>b.id===e))return;let s=new Set(n.filter(b=>b.id===e||no(b,e,n)).map(b=>b.id)),a=n.filter(b=>s.has(b.id)).map(oo);for(let b of o)b.visible&&b.opacity>0&&(s.has(b.from)||s.has(b.to))&&a.push((i.get(b.id)??ft()).bounds);let l=io(a);if(!l)return;let u=t.width/t.height,h=l.right-l.left+Pe*2,c=l.bottom-l.top+Pe*2,f=Math.max(h,c*u),d=Math.max(c,h/u);f>t.width&&(f=t.width,d=f/u),d>t.height&&(d=t.height,f=d*u);let g=(l.left+l.right)/2,m=(l.top+l.bottom)/2,y=Ee(g-f/2,0,t.width-f),x=Ee(m-d/2,0,t.height-d);return{x:y,y:x,width:f,height:d}}function no(t,e,n){let o=new Map(n.map(r=>[r.id,r])),i=t.parentId;for(;i;){if(i===e)return!0;i=o.get(i)?.parentId}return!1}function oo(t){return{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height}}function io(t){if(t.length!==0)return{left:Math.min(...t.map(e=>e.left)),top:Math.min(...t.map(e=>e.top)),right:Math.max(...t.map(e=>e.right)),bottom:Math.max(...t.map(e=>e.bottom))}}function Ee(t,e,n){return Math.min(n,Math.max(e,t))}function ro(t,e){if(e.labelBoxes.some(o=>{if(o.text.length===0)return!1;let i=Se(o.text,G)/2;return t.x>=o.x-i&&t.x<=o.x+i&&t.y>=o.y-G.fontSize&&t.y<=o.y+G.fontSize*Te}))return!0;if(e.kind==="ellipse"){let o=(t.x-(e.x+e.width/2))/(e.width/2),i=(t.y-(e.y+e.height/2))/(e.height/2);return o*o+i*i<=1}return t.x>=e.x&&t.x<=e.x+e.width&&t.y>=e.y&&t.y<=e.y+e.height}function it(t){return t.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&apos;")}function I(t){return it(t)}function so(t){return JSON.parse(JSON.stringify(t))}function _e(t){if(typeof t=="object"&&t!==null){Object.freeze(t);for(let e of Object.values(t))_e(e)}return t}function Ie(t,e){return lt(e.theme??t.theme)}var $=class extends Error{constructor(n,o,i){super(o,i);this.code=n;this.name="GifExportError"}};var pt=`16px ${at}`,Ot=22,yt=16,Rt=12;function Lt(t,e,n){let o=[];for(let i of e.split(`
3
+ `)){let r="";for(let s of i)r&&t.measureText(r+s).width>n&&(o.push(r),r=""),r+=s;o.push(r)}return o}function De(t,e,n){return t.beats.length===0?[{text:t.evaluateAt(0).caption??"",location:"static document title"}]:t.beats.filter(o=>o.startMs<n&&o.endMs>e).map(o=>({text:o.caption??"",location:`scene "${o.sceneId}", beat ${o.beatIndex+1}`}))}function Ne(t,e,n){t.font=pt;let o=n.width-yt*2,i=n.captionHeight-Rt*2;for(let{text:r,location:s}of e){if(r==="")continue;let a=Lt(t,r,o);if(a.length*Ot>i||a.some(l=>t.measureText(l).width>o))throw new $("caption-overflow",`Caption overflows at ${s}; increase captionHeight or width, shorten the text, or disable captions.`)}}var ao=12e4,lo=1800,co=1801,ho=65535,uo=1920,fo=1280,mo=15,go=80,po=1e3,yo=1,xo=30,bo=65536,X=10,xt=1e3;function Gt(t){if(t===null||typeof t!="object"||Array.isArray(t))throw new $("options","Provide GIF options as an object.");for(let e of["width","fps","captionHeight","startMs","endMs","speed","finalHoldMs","loopCount"]){let n=t[e];if(n!==void 0&&!Number.isFinite(n))throw new $("options",`${e} must be a finite number.`)}for(let e of["includeCaptions","reducedMotion"])if(t[e]!==void 0&&typeof t[e]!="boolean")throw new $("options",`${e} must be a boolean.`);if(t.theme!==void 0&&t.theme!=="light"&&t.theme!=="dark")throw new $("options","theme must be light or dark.");if(t.captionHeight!==void 0&&t.captionHeight<0)throw new $("options","captionHeight must be nonnegative.");if(t.onProgress!==void 0&&typeof t.onProgress!="function")throw new $("options","onProgress must be a function.");if(t.signal!==void 0&&!(t.signal instanceof AbortSignal))throw new $("options","signal must be an AbortSignal from an AbortController.")}function Oe(t,e,n){Gt(n);let o=n.width??Math.min(fo,t.viewport.width),i=n.fps??mo,r=n.includeCaptions===!1?0:n.captionHeight??go,s=n.startMs??0,a=n.endMs??e,l=n.speed??1,u=n.finalHoldMs??po,h=n.loopCount??0;for(let[v,S]of Object.entries({width:o,fps:i,captionHeight:r,startMs:s,endMs:a,speed:l,finalHoldMs:u,loopCount:h}))if(!Number.isFinite(S))throw new $("options",`${v} must be finite; provide a valid number.`);if(o<=0||l<=0||u<0||r<0||!Number.isInteger(i)||i<yo||i>xo)throw new $("options","Use positive width/speed, nonnegative hold/caption height and an integer fps from 1 to 30.");if(!Number.isInteger(h)||h<0||h>bo)throw new $("options","loopCount must be an integer from 0 to 65,536 (maximum total plays).");if(!Number.isFinite(e)||s<0||a>e||(e===0?s!==0||a!==0:s>=a))throw new $("options","Choose a finite, nonempty range within the document timeline; static documents accept only zero.");let c=Math.max(1,Math.round(o)),f=Math.max(1,Math.round(o*t.viewport.height/t.viewport.width)),d=f+Math.round(r),g=(a-s)/l,m=e===0?0:Math.max(1,Math.ceil(g*i/xt)),y=m>1&&(m-1)*xt/i>=g?m-1:m;if(g>ao||y>lo||Math.max(c,d)>uo)throw new $("limit","Reduce duration, fps or dimensions: limits are 120 seconds, 1800 samples and a 1920px final long edge.");let x=e===0?Math.max(1,Math.round(u/X)):Math.round(u/X),b=e===0||u>0||a===e;if(y+(b?Math.max(1,Math.ceil(x/ho)):0)>co)throw new $("limit","GIF requires more than 1801 encoded frames including final-hold splits; reduce finalHoldMs, duration or fps.");let w=e===0?0:wo(a),M=[];for(let v=0;v<y;v++){let S=v*xt/i,E=Math.min(g,(v+1)*xt/i);M.push({timeMs:Math.min(w,s+S*l),delayMs:(Math.round(E/X)-Math.round(S/X))*X})}let A=a===e?a:w;return b&&M.push({timeMs:A,delayMs:x*X}),{width:c,diagramHeight:f,height:d,captionHeight:Math.round(r),theme:n.theme??t.theme??"light",frames:M,startMs:s,endMs:a,reducedMotion:n.reducedMotion??!1,loopCount:h}}function wo(t){let e=new DataView(new ArrayBuffer(8));return e.setFloat64(0,t),e.setBigUint64(0,e.getBigUint64(0)-1n),e.getFloat64(0)}var Re=`(()=>{var se=Object.create;var W=Object.defineProperty;var le=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var fe=Object.getPrototypeOf,ue=Object.prototype.hasOwnProperty;var ge=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var de=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ae(t))!ue.call(e,r)&&r!==o&&W(e,r,{get:()=>t[r],enumerable:!(n=le(t,r))||n.enumerable});return e};var he=(e,t,o)=>(o=e!=null?se(fe(e)):{},de(t||!e||!e.__esModule?W(o,"default",{value:e,enumerable:!0}):o,e));var ce=ge(H=>{var J=Object.defineProperty,we=e=>J(e,"__esModule",{value:!0}),ye=(e,t)=>{for(var o in t)J(e,o,{get:t[o],enumerable:!0})};we(H);ye(H,{GIFEncoder:()=>oe,applyPalette:()=>Ce,default:()=>qe,nearestColor:()=>Fe,nearestColorIndex:()=>ne,nearestColorIndexWithDistance:()=>re,prequantize:()=>ve,quantize:()=>xe,snapColorsToPalette:()=>Ee});var be={signature:"GIF",version:"89a",trailer:59,extensionIntroducer:33,applicationExtensionLabel:255,graphicControlExtensionLabel:249,imageSeparator:44,signatureSize:3,versionSize:3,globalColorTableFlagMask:128,colorResolutionMask:112,sortFlagMask:8,globalColorTableSizeMask:7,applicationIdentifierSize:8,applicationAuthCodeSize:3,disposalMethodMask:28,userInputFlagMask:2,transparentColorFlagMask:1,localColorTableFlagMask:128,interlaceFlagMask:64,idSortFlagMask:32,localColorTableSizeMask:7};function Q(e=256){let t=0,o=new Uint8Array(e);return{get buffer(){return o.buffer},reset(){t=0},bytesView(){return o.subarray(0,t)},bytes(){return o.slice(0,t)},writeByte(r){n(t+1),o[t]=r,t++},writeBytes(r,i=0,c=r.length){n(t+c);for(let l=0;l<c;l++)o[t++]=r[l+i]},writeBytesView(r,i=0,c=r.byteLength){n(t+c),o.set(r.subarray(i,i+c),t),t+=c}};function n(r){var i=o.length;if(i>=r)return;var c=1024*1024;r=Math.max(r,i*(i<c?2:1.125)>>>0),i!=0&&(r=Math.max(r,256));let l=o;o=new Uint8Array(r),t>0&&o.set(l.subarray(0,t),0)}}var V=12,Y=5003,pe=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];function Ae(e,t,o,n,r=Q(512),i=new Uint8Array(256),c=new Int32Array(Y),l=new Int32Array(Y)){let g=c.length,f=Math.max(2,n);i.fill(0),l.fill(0),c.fill(-1);let a=0,s=0,d=f+1,p=d,h=!1,w=p,B=(1<<w)-1,u=1<<d-1,I=u+1,M=u+2,y=0,x=o[0],F=0;for(let A=g;A<65536;A*=2)++F;F=8-F,r.writeByte(f),v(u);let b=o.length;for(let A=1;A<b;A++)e:{let k=o[A],E=(k<<V)+x,_=k<<F^x;if(c[_]===E){x=l[_];break e}let P=_===0?1:g-_;for(;c[_]>=0;)if(_-=P,_<0&&(_+=g),c[_]===E){x=l[_];break e}v(x),x=k,M<1<<V?(l[_]=M++,c[_]=E):(c.fill(-1),M=u+2,h=!0,v(u))}return v(x),v(I),r.writeByte(0),r.bytesView();function v(A){for(a&=pe[s],s>0?a|=A<<s:a=A,s+=w;s>=8;)i[y++]=a&255,y>=254&&(r.writeByte(y),r.writeBytesView(i,0,y),y=0),a>>=8,s-=8;if((M>B||h)&&(h?(w=p,B=(1<<w)-1,h=!1):(++w,B=w===V?1<<w:(1<<w)-1)),A==I){for(;s>0;)i[y++]=a&255,y>=254&&(r.writeByte(y),r.writeBytesView(i,0,y),y=0),a>>=8,s-=8;y>0&&(r.writeByte(y),r.writeBytesView(i,0,y),y=0)}}}var Me=Ae;function $(e,t,o){return e<<8&63488|t<<2&992|o>>3}function ee(e,t,o,n){return e>>4|t&240|(o&240)<<4|(n&240)<<8}function te(e,t,o){return e>>4<<8|t&240|o>>4}function q(e,t,o){return e<t?t:e>o?o:e}function S(e){return e*e}function Z(e,t,o){var n=0,r=1e100;let i=e[t],c=i.cnt,l=i.ac,g=i.rc,f=i.gc,a=i.bc;for(var s=i.fw;s!=0;s=e[s].fw){let p=e[s],h=p.cnt,w=c*h/(c+h);if(!(w>=r)){var d=0;o&&(d+=w*S(p.ac-l),d>=r)||(d+=w*S(p.rc-g),!(d>=r)&&(d+=w*S(p.gc-f),!(d>=r)&&(d+=w*S(p.bc-a),!(d>=r)&&(r=d,n=s))))}}i.err=r,i.nn=n}function O(){return{ac:0,rc:0,gc:0,bc:0,cnt:0,nn:0,fw:0,bk:0,tm:0,mtm:0,err:0}}function Be(e,t){let o=t==="rgb444"?4096:65536,n=new Array(o),r=e.length;if(t==="rgba4444")for(let i=0;i<r;++i){let c=e[i],l=c>>24&255,g=c>>16&255,f=c>>8&255,a=c&255,s=ee(a,f,g,l),d=s in n?n[s]:n[s]=O();d.rc+=a,d.gc+=f,d.bc+=g,d.ac+=l,d.cnt++}else if(t==="rgb444")for(let i=0;i<r;++i){let c=e[i],l=c>>16&255,g=c>>8&255,f=c&255,a=te(f,g,l),s=a in n?n[a]:n[a]=O();s.rc+=f,s.gc+=g,s.bc+=l,s.cnt++}else for(let i=0;i<r;++i){let c=e[i],l=c>>16&255,g=c>>8&255,f=c&255,a=$(f,g,l),s=a in n?n[a]:n[a]=O();s.rc+=f,s.gc+=g,s.bc+=l,s.cnt++}return n}function xe(e,t,o={}){let{format:n="rgb565",clearAlpha:r=!0,clearAlphaColor:i=0,clearAlphaThreshold:c=0,oneBitAlpha:l=!1}=o;if(!e||!e.buffer)throw new Error("quantize() expected RGBA Uint8Array data");if(!(e instanceof Uint8Array)&&!(e instanceof Uint8ClampedArray))throw new Error("quantize() expected RGBA Uint8Array data");let g=new Uint32Array(e.buffer),f=o.useSqrt!==!1,a=n==="rgba4444",s=Be(g,n),d=s.length,p=d-1,h=new Uint32Array(d+1);for(var w=0,u=0;u<d;++u){let C=s[u];if(C!=null){var B=1/C.cnt;a&&(C.ac*=B),C.rc*=B,C.gc*=B,C.bc*=B,s[w++]=C}}S(t)/w<.022&&(f=!1);for(var u=0;u<w-1;++u)s[u].fw=u+1,s[u+1].bk=u,f&&(s[u].cnt=Math.sqrt(s[u].cnt));f&&(s[u].cnt=Math.sqrt(s[u].cnt));var I,M,y;for(u=0;u<w;++u){Z(s,u,!1);var x=s[u].err;for(M=++h[0];M>1&&(y=M>>1,!(s[I=h[y]].err<=x));M=y)h[M]=I;h[M]=u}var F=w-t;for(u=0;u<F;){for(var b;;){var v=h[1];if(b=s[v],b.tm>=b.mtm&&s[b.nn].mtm<=b.tm)break;b.mtm==p?v=h[1]=h[h[0]--]:(Z(s,v,!1),b.tm=u);var x=s[v].err;for(M=1;(y=M+M)<=h[0]&&(y<h[0]&&s[h[y]].err>s[h[y+1]].err&&y++,!(x<=s[I=h[y]].err));M=y)h[M]=I;h[M]=v}var A=s[b.nn],k=b.cnt,E=A.cnt,B=1/(k+E);a&&(b.ac=B*(k*b.ac+E*A.ac)),b.rc=B*(k*b.rc+E*A.rc),b.gc=B*(k*b.gc+E*A.gc),b.bc=B*(k*b.bc+E*A.bc),b.cnt+=A.cnt,b.mtm=++u,s[A.bk].fw=A.fw,s[A.fw].bk=A.bk,A.mtm=p}let _=[];var P=0;for(u=0;;++P){let R=q(Math.round(s[u].rc),0,255),C=q(Math.round(s[u].gc),0,255),L=q(Math.round(s[u].bc),0,255),T=255;a&&(T=q(Math.round(s[u].ac),0,255),l&&(T=T<=(typeof l=="number"?l:127)?0:255),r&&T<=c&&(R=C=L=i,T=0));let X=a?[R,C,L,T]:[R,C,L];if(_e(_,X)||_.push(X),(u=s[u].fw)==0)break}return _}function _e(e,t){for(let o=0;o<e.length;o++){let n=e[o],r=n[0]===t[0]&&n[1]===t[1]&&n[2]===t[2],i=n.length>=4&&t.length>=4?n[3]===t[3]:!0;if(r&&i)return!0}return!1}function G(e,t){var o=0,n;for(n=0;n<e.length;n++){let r=e[n]-t[n];o+=r*r}return o}function D(e,t){return t>1?Math.round(e/t)*t:e}function ve(e,{roundRGB:t=5,roundAlpha:o=10,oneBitAlpha:n=null}={}){let r=new Uint32Array(e.buffer);for(let i=0;i<r.length;i++){let c=r[i],l=c>>24&255,g=c>>16&255,f=c>>8&255,a=c&255;l=D(l,o),n&&(l=l<=(typeof n=="number"?n:127)?0:255),a=D(a,t),f=D(f,t),g=D(g,t),r[i]=l<<24|g<<16|f<<8|a<<0}}function Ce(e,t,o="rgb565"){if(!e||!e.buffer)throw new Error("quantize() expected RGBA Uint8Array data");if(!(e instanceof Uint8Array)&&!(e instanceof Uint8ClampedArray))throw new Error("quantize() expected RGBA Uint8Array data");if(t.length>256)throw new Error("applyPalette() only works with 256 colors or less");let n=new Uint32Array(e.buffer),r=n.length,i=o==="rgb444"?4096:65536,c=new Uint8Array(r),l=new Array(i),g=o==="rgba4444";if(o==="rgba4444")for(let f=0;f<r;f++){let a=n[f],s=a>>24&255,d=a>>16&255,p=a>>8&255,h=a&255,w=ee(h,p,d,s),B=w in l?l[w]:l[w]=Ie(h,p,d,s,t);c[f]=B}else{let f=o==="rgb444"?te:$;for(let a=0;a<r;a++){let s=n[a],d=s>>16&255,p=s>>8&255,h=s&255,w=f(h,p,d),B=w in l?l[w]:l[w]=ke(h,p,d,t);c[a]=B}}return c}function Ie(e,t,o,n,r){let i=0,c=1e100;for(let l=0;l<r.length;l++){let g=r[l],f=g[3],a=z(f-n);if(a>c)continue;let s=g[0];if(a+=z(s-e),a>c)continue;let d=g[1];if(a+=z(d-t),a>c)continue;let p=g[2];a+=z(p-o),!(a>c)&&(c=a,i=l)}return i}function ke(e,t,o,n){let r=0,i=1e100;for(let c=0;c<n.length;c++){let l=n[c],g=l[0],f=z(g-e);if(f>i)continue;let a=l[1];if(f+=z(a-t),f>i)continue;let s=l[2];f+=z(s-o),!(f>i)&&(i=f,r=c)}return r}function Ee(e,t,o=5){if(!e.length||!t.length)return;let n=e.map(c=>c.slice(0,3)),r=o*o,i=e[0].length;for(let c=0;c<t.length;c++){let l=t[c];l.length<i?l=[l[0],l[1],l[2],255]:l.length>i?l=l.slice(0,3):l=l.slice();let g=re(n,l.slice(0,3),G),f=g[0],a=g[1];a>0&&a<=r&&(e[f]=l)}}function z(e){return e*e}function ne(e,t,o=G){let n=1/0,r=-1;for(let i=0;i<e.length;i++){let c=e[i],l=o(t,c);l<n&&(n=l,r=i)}return r}function re(e,t,o=G){let n=1/0,r=-1;for(let i=0;i<e.length;i++){let c=e[i],l=o(t,c);l<n&&(n=l,r=i)}return[r,n]}function Fe(e,t,o=G){return e[ne(e,t,o)]}function oe(e={}){let{initialCapacity:t=4096,auto:o=!0}=e,n=Q(t),r=5003,i=new Uint8Array(256),c=new Int32Array(r),l=new Int32Array(r),g=!1;return{reset(){n.reset(),g=!1},finish(){n.writeByte(be.trailer)},bytes(){return n.bytes()},bytesView(){return n.bytesView()},get buffer(){return n.buffer},get stream(){return n},writeHeader:f,writeFrame(a,s,d,p={}){let{transparent:h=!1,transparentIndex:w=0,delay:B=0,palette:u=null,repeat:I=0,colorDepth:M=8,dispose:y=-1}=p,x=!1;if(o?g||(x=!0,f(),g=!0):x=!!p.first,s=Math.max(0,Math.floor(s)),d=Math.max(0,Math.floor(d)),x){if(!u)throw new Error("First frame must include a { palette } option");ze(n,s,d,u,M),K(n,u),I>=0&&Te(n,I)}let F=Math.round(B/10);me(n,y,F,h,w);let b=!!u&&!x;Ue(n,s,d,b?u:null),b&&K(n,u),Se(n,a,s,d,M,i,c,l)}};function f(){ie(n,"GIF89a")}}function me(e,t,o,n,r){e.writeByte(33),e.writeByte(249),e.writeByte(4),r<0&&(r=0,n=!1);var i,c;n?(i=1,c=2):(i=0,c=0),t>=0&&(c=t&7),c<<=2,e.writeByte(0|c|0|i),m(e,o),e.writeByte(r||0),e.writeByte(0)}function ze(e,t,o,n,r=8){let l=j(n.length)-1,g=128|r-1<<4|0|l,f=0,a=0;m(e,t),m(e,o),e.writeBytes([g,f,a])}function Te(e,t){e.writeByte(33),e.writeByte(255),e.writeByte(11),ie(e,"NETSCAPE2.0"),e.writeByte(3),e.writeByte(1),m(e,t),e.writeByte(0)}function K(e,t){let o=1<<j(t.length);for(let n=0;n<o;n++){let r=[0,0,0];n<t.length&&(r=t[n]),e.writeByte(r[0]),e.writeByte(r[1]),e.writeByte(r[2])}}function Ue(e,t,o,n){if(e.writeByte(44),m(e,0),m(e,0),m(e,t),m(e,o),n){let c=j(n.length)-1;e.writeByte(128|c)}else e.writeByte(0)}function Se(e,t,o,n,r=8,i,c,l){Me(o,n,t,r,e,i,c,l)}function m(e,t){e.writeByte(t&255),e.writeByte(t>>8&255)}function ie(e,t){for(var o=0;o<t.length;o++)e.writeByte(t.charCodeAt(o))}function j(e){return Math.max(Math.ceil(Math.log2(e)),1)}var qe=oe});var U=he(ce(),1),N=(0,U.GIFEncoder)(),De=655350,Ge=256;self.onmessage=e=>{try{let t=e.data;if(t.type==="finish"){N.finish();let c=N.bytes();self.postMessage({bytes:c},{transfer:[c.buffer]});return}let o=new Uint8Array(t.rgba),n=(0,U.quantize)(o,Ge),r=(0,U.applyPalette)(o,n),i=t.delayMs;do{let c=Math.min(i,De);N.writeFrame(r,t.width,t.height,{palette:n,delay:c,repeat:t.repeat}),i-=c}while(i>0);self.postMessage({acknowledged:!0})}catch(t){self.postMessage({error:t instanceof Error?t.message:String(t)})}};})();
4
+ `;async function Ft(t,e={}){Gt(e);let n={...e};F(n.signal);try{Nt(t)}catch(g){throw new $("document","Invalid diagram document; correct the validation issues before exporting.",{cause:g})}let o=JSON.parse(JSON.stringify(t)),{fitHeight:i,...r}=o.viewport,s=Nt({...o,viewport:r}),a=Oe(o,s.totalDuration,n);if(typeof globalThis.document>"u"||typeof Worker!="function")throw new $("environment","GIF export requires a modern browser with canvas and workers; use flowsvg/node in Node.");let l=(g,m)=>{F(n.signal),n.onProgress?.({phase:g,completed:m,total:a.frames.length}),F(n.signal)};l("preparing",0);let u=globalThis.document.createElement("canvas");u.width=a.width,u.height=a.height;let h,c,f=new AbortController,d=g=>f.abort(new $("encoding",`Worker failed: ${g.message||"startup or execution was blocked"}. Check Blob worker permissions and retry.`));try{let g=u.getContext("2d",{willReadFrequently:!0});if(!g)throw new $("environment","Canvas 2D is unavailable; enable browser canvas support.");let m=n.includeCaptions===!1?[]:De(s,a.startMs,a.endMs);await Mo([o.title??"\u4E2D\u6587",...m.map(({text:x})=>x)].join(`
5
+ `),n.signal),Ne(g,m,a),F(n.signal),c=URL.createObjectURL(new Blob([Re],{type:"text/javascript"})),h=Po(c),h.addEventListener("error",d);for(let[x,b]of a.frames.entries()){l("sampling",x);let P=s.evaluateAt(b.timeMs,a).caption??"";await $o(g,u,s.renderSvg(b.timeMs,a),P,a,n.signal,f.signal);let w=Ao(g,a);l("encoding",x),await Le(h,{type:"frame",rgba:w.data.buffer,width:a.width,height:a.height,delayMs:b.delayMs,repeat:a.loopCount===1?-1:a.loopCount===0?0:a.loopCount-1},[w.data.buffer],n.signal,f.signal),await new Promise(M=>setTimeout(M,0))}let y=await Le(h,{type:"finish"},[],n.signal,f.signal);if(!y.bytes)throw new $("encoding","Encoder returned no bytes; retry with a smaller export.");return l("complete",a.frames.length),y.bytes}finally{h?.removeEventListener("error",d),h?.terminate(),c&&URL.revokeObjectURL(c),u.width=0,u.height=0}}function F(t,e){if(t?.aborted)throw new $("cancelled","GIF export cancelled; start another export when ready.");if(e?.aborted)throw e.reason}function Le(t,e,n,o,i){return F(o,i),new Promise((r,s)=>{let a=()=>{t.removeEventListener("message",h),i.removeEventListener("abort",u),o?.removeEventListener("abort",l)},l=()=>{a(),s(new $("cancelled","GIF export cancelled; start another export when ready."))},u=()=>{a(),s(i.reason)},h=c=>{a(),c.data.error?s(new $("encoding",`${c.data.error}; retry with a smaller export.`)):r(c.data)};t.addEventListener("message",h),i.addEventListener("abort",u,{once:!0}),o?.addEventListener("abort",l,{once:!0});try{t.postMessage(e,n)}catch(c){a(),s(new $("encoding","Cannot send pixels to the encoder; retry the export.",{cause:c}))}})}async function $o(t,e,n,o,i,r,s){F(r,s);let a=URL.createObjectURL(new Blob([n],{type:"image/svg+xml"})),l=new Image;try{l.src=a,await kt(l.decode(),r,s),F(r,s);let u=lt(i.theme);if(t.fillStyle=u.background,t.fillRect(0,0,e.width,e.height),t.drawImage(l,0,0,i.width,i.diagramHeight),!i.captionHeight)return;t.font=pt,t.fillStyle=u.text,t.textBaseline="top",Lt(t,o,i.width-yt*2).forEach((h,c)=>t.fillText(h,yt,i.diagramHeight+Rt+c*Ot))}catch(u){throw u instanceof $?u:new $("rasterization","Cannot rasterize the diagram; check browser SVG/canvas support and retry.",{cause:u})}finally{l.src="",URL.revokeObjectURL(a)}}function kt(t,e,n){return F(e,n),new Promise((o,i)=>{let r=()=>{e?.removeEventListener("abort",s),n?.removeEventListener("abort",a)},s=()=>{r(),i(new $("cancelled","GIF export cancelled; start another export when ready."))},a=()=>{r(),i(n?.reason)};e?.addEventListener("abort",s,{once:!0}),n?.addEventListener("abort",a,{once:!0}),Promise.resolve(t).then(l=>{r(),o(l)},l=>{r(),i(l)})})}async function Mo(t,e){try{await kt(globalThis.document.fonts.load(pt,t),e),await kt(globalThis.document.fonts.ready,e)}catch(n){throw n instanceof $?n:new $("environment","Cannot prepare system fonts; check browser font support and retry.",{cause:n})}}function Po(t){try{return new Worker(t)}catch(e){throw new $("environment","Cannot start the GIF worker; allow Blob workers in the browser content security policy.",{cause:e})}}function Ao(t,e){try{return t.getImageData(0,0,e.width,e.height)}catch(n){throw new $("rasterization","Cannot read rendered pixels; check browser canvas permissions and retry.",{cause:n})}}return je(vo);})();
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "flowsvg",
3
+ "version": "0.2.0",
4
+ "modules": [
5
+ "core",
6
+ "browser",
7
+ "export"
8
+ ],
9
+ "files": [
10
+ "export.js",
11
+ "LICENSE.gifenc.txt",
12
+ "player.js",
13
+ "styles.css",
14
+ "LICENSE.flowsvg.txt",
15
+ "LICENSE.esbuild.txt"
16
+ ],
17
+ "thirdParty": [
18
+ {
19
+ "name": "gifenc",
20
+ "version": "1.0.3",
21
+ "license": "MIT",
22
+ "licenseFile": "LICENSE.gifenc.txt",
23
+ "modules": [
24
+ "export"
25
+ ]
26
+ }
27
+ ],
28
+ "buildTools": [
29
+ {
30
+ "name": "esbuild",
31
+ "version": "0.25.12",
32
+ "license": "MIT",
33
+ "licenseFile": "LICENSE.esbuild.txt"
34
+ }
35
+ ]
36
+ }