@phin-tech/dottie 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- /*! dottie.js 0.10.0 | Apache-2.0 | https://github.com/phin-tech/dottie */
1
+ /*! dottie.js 0.11.0 | Apache-2.0 | https://github.com/phin-tech/dottie */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value2) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value: value2 }) : obj[key] = value2;
4
4
  var __export = (target, all) => {
@@ -68,82 +68,332 @@ __export(index_exports, {
68
68
  withRoughness: () => withRoughness
69
69
  });
70
70
 
71
- // src/state.ts
71
+ // src/expression.ts
72
+ var METRIC_NAMES = ["throughput", "load", "delay", "backlog", "depth", "inFlight", "transit", "backup"];
73
+ var FUNCTIONS = { min: null, max: null, abs: 1, floor: 1, ceil: 1, round: 1, clamp: 3 };
72
74
  var MAX_NAME = 64;
73
- function isName(name) {
74
- return name.length <= MAX_NAME && /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);
75
+ var truthy = (v) => typeof v === "boolean" ? v : v !== 0 && !Number.isNaN(v);
76
+ var num = (v) => typeof v === "boolean" ? v ? 1 : 0 : v;
77
+ var parsed = /* @__PURE__ */ new Map();
78
+ function parseExpr(text) {
79
+ const hit = parsed.get(text);
80
+ if (hit !== void 0) return hit;
81
+ const p = new Parser(text);
82
+ let e = p.or();
83
+ if (e && !p.atEnd()) e = null;
84
+ if (parsed.size > 4096) parsed.clear();
85
+ parsed.set(text, e);
86
+ return e;
75
87
  }
76
- var METRIC_NAMES = ["throughput", "load", "delay", "backlog", "depth", "inFlight", "transit", "backup"];
77
- var OPS = [">=", "<=", "==", "!=", ">", "<"];
78
- function metricTerm(term) {
79
- const t = trim(term);
80
- if (!t.includes("(")) {
81
- const op2 = t.search(/[>=<!]/);
82
- if (op2 < 0) return null;
83
- const name2 = trim(t.slice(0, op2));
84
- if (!METRIC_NAMES.includes(name2)) return null;
85
- const m = metricTerm(name2 + "() " + t.slice(op2));
86
- return m ? { ...m, target: "" } : null;
87
- }
88
- const open = t.indexOf("("), close = t.indexOf(")");
89
- if (open < 0 || close < 0 || open >= close) return null;
90
- const name = trim(t.slice(0, open)), target = trim(t.slice(open + 1, close));
91
- let rest = trim(t.slice(close + 1));
92
- if (!METRIC_NAMES.includes(name) || target.includes("(")) return null;
93
- const op = OPS.find((o) => rest.startsWith(o));
94
- if (op === void 0) return null;
95
- rest = trim(rest.slice(op.length));
96
- if (!/^-?[0-9]+(\.[0-9]+)?$/.test(rest)) return null;
97
- return { metric: name, target, op, value: Number(rest) };
98
- }
99
- function passes(m, v) {
100
- switch (m.op) {
101
- case ">":
102
- return v > m.value;
103
- case ">=":
104
- return v >= m.value;
105
- case "<":
106
- return v < m.value;
107
- case "<=":
108
- return v <= m.value;
109
- case "==":
110
- return v === m.value;
111
- default:
112
- return v !== m.value;
88
+ function evaluate(e, state, metric = null) {
89
+ switch (e.k) {
90
+ case "lit":
91
+ return e.v;
92
+ case "name":
93
+ return state[e.name] ?? false;
94
+ case "metric":
95
+ return metric?.(e.metric, e.target) ?? NaN;
96
+ case "not":
97
+ return !truthy(evaluate(e.e, state, metric));
98
+ case "neg":
99
+ return -num(evaluate(e.e, state, metric));
100
+ case "call": {
101
+ const xs = e.args.map((a) => num(evaluate(a, state, metric)));
102
+ const fold = (better) => {
103
+ if (xs.some(Number.isNaN)) return NaN;
104
+ let out = xs[0];
105
+ for (const x of xs.slice(1)) if (better(x, out)) out = x;
106
+ return out;
107
+ };
108
+ switch (e.fn) {
109
+ case "min":
110
+ return fold((a, b) => a < b);
111
+ case "max":
112
+ return fold((a, b) => a > b);
113
+ case "abs":
114
+ return Math.abs(xs[0]);
115
+ case "floor":
116
+ return Math.floor(xs[0]);
117
+ case "ceil":
118
+ return Math.ceil(xs[0]);
119
+ case "round":
120
+ return Math.floor(xs[0] + 0.5);
121
+ default:
122
+ if (xs.some(Number.isNaN)) return NaN;
123
+ return xs[0] < xs[1] ? xs[1] : xs[0] > xs[2] ? xs[2] : xs[0];
124
+ }
125
+ }
126
+ case "bin": {
127
+ if (e.op === "&&") return truthy(evaluate(e.l, state, metric)) && truthy(evaluate(e.r, state, metric));
128
+ if (e.op === "||") return truthy(evaluate(e.l, state, metric)) || truthy(evaluate(e.r, state, metric));
129
+ const a = evaluate(e.l, state, metric), b = evaluate(e.r, state, metric);
130
+ const x = num(a), y = num(b);
131
+ switch (e.op) {
132
+ case "+":
133
+ return x + y;
134
+ case "-":
135
+ return x - y;
136
+ case "*":
137
+ return x * y;
138
+ case "/":
139
+ return x / y;
140
+ case "%":
141
+ return x % y;
142
+ }
143
+ if (Number.isNaN(x) || Number.isNaN(y)) return false;
144
+ switch (e.op) {
145
+ case "<":
146
+ return x < y;
147
+ case "<=":
148
+ return x <= y;
149
+ case ">":
150
+ return x > y;
151
+ case ">=":
152
+ return x >= y;
153
+ case "==":
154
+ return typeof a === "boolean" && typeof b === "boolean" ? a === b : x === y;
155
+ default:
156
+ return typeof a === "boolean" && typeof b === "boolean" ? a !== b : x !== y;
157
+ }
158
+ }
113
159
  }
114
160
  }
115
- function mentionsMetric(condition) {
116
- return condition.split("||").some((any) => any.split("&&").some((all) => metricTerm(all) !== null));
161
+ function exprNames(e) {
162
+ const out = [];
163
+ const walk = (x) => {
164
+ switch (x.k) {
165
+ case "name":
166
+ if (!out.includes(x.name)) out.push(x.name);
167
+ break;
168
+ case "not":
169
+ case "neg":
170
+ walk(x.e);
171
+ break;
172
+ case "bin":
173
+ walk(x.l);
174
+ walk(x.r);
175
+ break;
176
+ case "call":
177
+ x.args.forEach(walk);
178
+ break;
179
+ }
180
+ };
181
+ walk(e);
182
+ return out;
117
183
  }
118
- function conditionNames(condition) {
184
+ function exprMetrics(e) {
119
185
  const out = [];
120
- for (const any of condition.split("||")) {
121
- for (const all of any.split("&&")) {
122
- if (metricTerm(all) !== null) continue;
123
- let term = trim(all);
124
- if (term.startsWith("!")) term = trim(term.slice(1));
125
- if (!isName(term)) return null;
126
- out.push(term);
186
+ const walk = (x) => {
187
+ switch (x.k) {
188
+ case "metric":
189
+ out.push({ metric: x.metric, target: x.target });
190
+ break;
191
+ case "not":
192
+ case "neg":
193
+ walk(x.e);
194
+ break;
195
+ case "bin":
196
+ walk(x.l);
197
+ walk(x.r);
198
+ break;
199
+ case "call":
200
+ x.args.forEach(walk);
201
+ break;
127
202
  }
128
- }
203
+ };
204
+ walk(e);
129
205
  return out;
130
206
  }
207
+ var isDigit = (c) => c !== void 0 && c >= "0" && c <= "9";
208
+ var isLetter = (c) => c !== void 0 && (c === "_" || c >= "a" && c <= "z" || c >= "A" && c <= "Z");
209
+ var Parser = class {
210
+ constructor(text) {
211
+ __publicField(this, "s");
212
+ __publicField(this, "i", 0);
213
+ this.s = [...text];
214
+ }
215
+ atEnd() {
216
+ this.skip();
217
+ return this.i === this.s.length;
218
+ }
219
+ skip() {
220
+ while (this.i < this.s.length && " \n\r".includes(this.s[this.i])) this.i++;
221
+ }
222
+ eat(token) {
223
+ this.skip();
224
+ const t = [...token];
225
+ if (this.i + t.length > this.s.length) return false;
226
+ for (let k = 0; k < t.length; k++) if (this.s[this.i + k] !== t[k]) return false;
227
+ if (t.length === 1 && this.s[this.i + 1] === "=" && "<>!=".includes(t[0])) return false;
228
+ this.i += t.length;
229
+ return true;
230
+ }
231
+ or() {
232
+ let l = this.and();
233
+ if (!l) return null;
234
+ while (this.eat("||")) {
235
+ const r = this.and();
236
+ if (!r) return null;
237
+ l = { k: "bin", op: "||", l, r };
238
+ }
239
+ return l;
240
+ }
241
+ and() {
242
+ let l = this.compare();
243
+ if (!l) return null;
244
+ while (this.eat("&&")) {
245
+ const r = this.compare();
246
+ if (!r) return null;
247
+ l = { k: "bin", op: "&&", l, r };
248
+ }
249
+ return l;
250
+ }
251
+ compare() {
252
+ const l = this.sum();
253
+ if (!l) return null;
254
+ for (const op of ["<=", ">=", "==", "!=", "<", ">"]) {
255
+ if (this.eat(op)) {
256
+ const r = this.sum();
257
+ return r ? { k: "bin", op, l, r } : null;
258
+ }
259
+ }
260
+ return l;
261
+ }
262
+ sum() {
263
+ let l = this.product();
264
+ if (!l) return null;
265
+ for (; ; ) {
266
+ const op = this.eat("+") ? "+" : this.eat("-") ? "-" : null;
267
+ if (!op) return l;
268
+ const r = this.product();
269
+ if (!r) return null;
270
+ l = { k: "bin", op, l, r };
271
+ }
272
+ }
273
+ product() {
274
+ let l = this.unary();
275
+ if (!l) return null;
276
+ for (; ; ) {
277
+ const op = ["*", "/", "%"].find((o) => this.eat(o));
278
+ if (!op) return l;
279
+ const r = this.unary();
280
+ if (!r) return null;
281
+ l = { k: "bin", op, l, r };
282
+ }
283
+ }
284
+ unary() {
285
+ if (this.eat("!")) {
286
+ const e = this.unary();
287
+ return e ? { k: "not", e } : null;
288
+ }
289
+ if (this.eat("-")) {
290
+ const e = this.unary();
291
+ return e ? { k: "neg", e } : null;
292
+ }
293
+ return this.primary();
294
+ }
295
+ primary() {
296
+ this.skip();
297
+ if (this.i >= this.s.length) return null;
298
+ if (this.eat("(")) {
299
+ const e = this.or();
300
+ return e && this.eat(")") ? e : null;
301
+ }
302
+ const s = this.s;
303
+ const c = s[this.i];
304
+ if (isDigit(c)) {
305
+ const start3 = this.i;
306
+ while (isDigit(s[this.i])) this.i++;
307
+ if (s[this.i] === "." && isDigit(s[this.i + 1])) {
308
+ this.i++;
309
+ while (isDigit(s[this.i])) this.i++;
310
+ }
311
+ return { k: "lit", v: Number(s.slice(start3, this.i).join("")) };
312
+ }
313
+ if (!isLetter(c)) return null;
314
+ const start2 = this.i;
315
+ while (isLetter(s[this.i]) || isDigit(s[this.i])) this.i++;
316
+ const name = s.slice(start2, this.i).join("");
317
+ if (name.length > MAX_NAME) return null;
318
+ let j = this.i;
319
+ while (s[j] === " " || s[j] === " ") j++;
320
+ const called = s[j] === "(";
321
+ if (METRIC_NAMES.includes(name)) {
322
+ if (!called) return { k: "metric", metric: name, target: "" };
323
+ this.eat("(");
324
+ const from = this.i;
325
+ while (this.i < s.length && s[this.i] !== ")" && s[this.i] !== "(") this.i++;
326
+ if (s[this.i] !== ")") return null;
327
+ const target = s.slice(from, this.i).join("").replace(/^[ \t]+|[ \t]+$/g, "");
328
+ this.i++;
329
+ return { k: "metric", metric: name, target };
330
+ }
331
+ if (name in FUNCTIONS) {
332
+ if (!called || !this.eat("(")) return null;
333
+ const args = [];
334
+ if (!this.eat(")")) {
335
+ do {
336
+ const a = this.or();
337
+ if (!a) return null;
338
+ args.push(a);
339
+ } while (this.eat(","));
340
+ if (!this.eat(")")) return null;
341
+ }
342
+ const arity = FUNCTIONS[name];
343
+ if (arity !== null ? args.length !== arity : args.length === 0) return null;
344
+ return { k: "call", fn: name, args };
345
+ }
346
+ if (called) return null;
347
+ if (name === "true") return { k: "lit", v: true };
348
+ if (name === "false") return { k: "lit", v: false };
349
+ return { k: "name", name };
350
+ }
351
+ };
352
+ function describeVar(v) {
353
+ return typeof v === "boolean" ? v ? "true" : "false" : formatTwo(v);
354
+ }
355
+ function formatTwo(v) {
356
+ const n = Math.floor(Math.abs(v) * 100 + 0.5);
357
+ if (!(n < 1e15)) return v < 0 ? "-\u221E" : "\u221E";
358
+ const whole = Math.floor(n / 100), part = n - whole * 100;
359
+ let s = String(whole);
360
+ if (part > 0) s += "." + String(part).padStart(2, "0").replace(/0+$/, "");
361
+ return (v < 0 && n > 0 ? "-" : "") + s;
362
+ }
363
+ function filling(text, values) {
364
+ if (!text.includes("{")) return text;
365
+ let out = "", rest = text;
366
+ for (let open = rest.indexOf("{"); open >= 0; open = rest.indexOf("{")) {
367
+ out += rest.slice(0, open);
368
+ const close = rest.indexOf("}", open);
369
+ if (close < 0) {
370
+ out += rest.slice(open);
371
+ rest = "";
372
+ break;
373
+ }
374
+ const inner = rest.slice(open + 1, close);
375
+ const e = inner.includes("{") ? null : parseExpr(inner);
376
+ const names = e ? exprNames(e) : [];
377
+ if (e && exprMetrics(e).length === 0 && names.length > 0 && names.every((n) => values[n] !== void 0)) out += describeVar(evaluate(e, values));
378
+ else out += rest.slice(open, close + 1);
379
+ rest = rest.slice(close + 1);
380
+ }
381
+ return out + rest;
382
+ }
383
+
384
+ // src/state.ts
385
+ var MAX_NAME2 = 64;
386
+ function isName(name) {
387
+ return name.length <= MAX_NAME2 && /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);
388
+ }
389
+ function mentionsMetric(condition) {
390
+ const e = parseExpr(condition);
391
+ return e !== null && exprMetrics(e).length > 0;
392
+ }
131
393
  function holds(condition, state, metric = null) {
132
- if (conditionNames(condition) === null) return false;
133
- return condition.split("||").some((any) => any.split("&&").every((all) => {
134
- const m = metricTerm(all);
135
- if (m !== null) {
136
- const v = metric ? metric(m) : null;
137
- return v !== null && passes(m, v);
138
- }
139
- let term = trim(all);
140
- let negated = false;
141
- if (term.startsWith("!")) {
142
- negated = true;
143
- term = trim(term.slice(1));
144
- }
145
- return (state[term] ?? false) !== negated;
146
- }));
394
+ const e = parseExpr(condition);
395
+ if (!e) return false;
396
+ return truthy(evaluate(e, state, metric ? (m, target) => metric({ metric: m, target, op: "", value: 0 }) : null));
147
397
  }
148
398
  function stateValues(page, choice) {
149
399
  if (choice === "all") return null;
@@ -182,7 +432,7 @@ function applyOverride(o, e) {
182
432
  return out;
183
433
  }
184
434
  function changesState(c) {
185
- return !!c && (c.reset === true || Object.keys(c.set ?? {}).length > 0 || (c.toggle ?? []).length > 0);
435
+ return !!c && (c.reset === true || Object.keys(c.set ?? {}).length > 0 || (c.toggle ?? []).length > 0 || !!c.run);
186
436
  }
187
437
  function applyClick(c, state, initial = {}) {
188
438
  let out = { ...state };
@@ -191,12 +441,15 @@ function applyClick(c, state, initial = {}) {
191
441
  for (const k of Object.keys(state)) out[k] = false;
192
442
  Object.assign(out, initial);
193
443
  }
194
- for (const [k, v] of Object.entries(c.set ?? {})) out[k] = v;
195
- for (const k of c.toggle ?? []) out[k] = !(out[k] ?? false);
444
+ const before = { ...out };
445
+ for (const [k, v] of Object.entries(c.set ?? {})) out[k] = clickValue(v, before, before[k]);
446
+ for (const k of c.toggle ?? []) out[k] = !truthy(out[k] ?? false);
196
447
  return out;
197
448
  }
198
- function trim(s) {
199
- return s.replace(/^[ \t ]+|[ \t ]+$/g, "");
449
+ function clickValue(v, state, current) {
450
+ if (typeof v !== "string") return v;
451
+ const e = parseExpr(v);
452
+ return e ? evaluate(e, state) : current ?? false;
200
453
  }
201
454
 
202
455
  // src/theme.ts
@@ -258,12 +511,12 @@ function resolvingPalette(page) {
258
511
  }
259
512
 
260
513
  // src/model.ts
261
- var SUPPORTED_VERSION = 2;
514
+ var SUPPORTED_VERSION = 3;
262
515
  var KINDS = ["rectangle", "ellipse", "diamond", "text", "connector", "freehand", "path", "note", "image", "symbol"];
263
516
  var EASES = ["linear", "easeIn", "easeOut", "easeInOut", "hold", "spring", "bounce", "elastic"];
264
517
  var KNOWN_FIELDS = {
265
518
  file: ["version", "pages", "images"],
266
- page: ["id", "name", "layers", "elements", "theme", "customTheme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
519
+ page: ["id", "name", "layers", "elements", "theme", "customTheme", "logic", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
267
520
  flow: ["id", "from", "to", "every", "speed", "color", "size", "when", "spread", "volume", "overrides"],
268
521
  flowOverride: ["when", "volume"],
269
522
  symbol: ["id", "name", "width", "height", "layers", "elements", "timeline", "button", "params"],
@@ -332,7 +585,7 @@ var KNOWN_FIELDS = {
332
585
  repeat: ["start", "end", "count"],
333
586
  cameraKey: ["t", "x", "y", "width", "height", "ease"],
334
587
  marker: ["t", "name", "loop"],
335
- click: ["scene", "url", "set", "toggle", "reset"],
588
+ click: ["scene", "url", "set", "toggle", "reset", "run"],
336
589
  hover: ["stroke", "fill", "opacity"],
337
590
  override: ["when", "stroke", "fill", "textColor", "opacity", "strokeWidth", "dash", "text", "reroute", "offline", "cost", "capacity", "delay"]
338
591
  };
@@ -346,7 +599,7 @@ var inkOnDark = { r: 0.93, g: 0.93, b: 0.94, a: 1 };
346
599
  var DottieFormatError = class extends Error {
347
600
  };
348
601
  var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
349
- var num = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
602
+ var num2 = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
350
603
  var str = (v) => typeof v === "string" ? v : void 0;
351
604
  var strings = (v) => isObj(v) && Object.values(v).every((x) => typeof x === "string") ? { ...v } : null;
352
605
  var bool = (v) => typeof v === "boolean" ? v : void 0;
@@ -370,9 +623,9 @@ function webLink(url) {
370
623
  }
371
624
  function rgba(v) {
372
625
  if (!isObj(v)) return void 0;
373
- const r = num(v.r), g = num(v.g), b = num(v.b);
626
+ const r = num2(v.r), g = num2(v.g), b = num2(v.b);
374
627
  if (r === void 0 || g === void 0 || b === void 0) return void 0;
375
- return { r, g, b, a: num(v.a) ?? 1 };
628
+ return { r, g, b, a: num2(v.a) ?? 1 };
376
629
  }
377
630
  var Reader = class {
378
631
  constructor() {
@@ -401,15 +654,15 @@ var Reader = class {
401
654
  stroke: rgba(s.stroke) ?? { ...black },
402
655
  fill: rgba(s.fill) ?? { ...clear },
403
656
  fillStyle: ["solid", "hachure", "crossHatch", "grid"].includes(fillStyle) ? fillStyle : "solid",
404
- strokeWidth: num(s.strokeWidth) ?? 2,
657
+ strokeWidth: num2(s.strokeWidth) ?? 2,
405
658
  dash: ["solid", "dashed", "dotted"].includes(dash) ? dash : "solid",
406
- roughness: num(s.roughness) ?? 1,
407
- bowing: num(s.bowing) ?? 1,
408
- fontSize: num(s.fontSize) ?? 18,
659
+ roughness: num2(s.roughness) ?? 1,
660
+ bowing: num2(s.bowing) ?? 1,
661
+ fontSize: num2(s.fontSize) ?? 18,
409
662
  font: str(s.font) || null,
410
- gridSize: num(s.gridSize) ?? null,
411
- opacity: num(s.opacity) ?? null,
412
- dashOffset: num(s.dashOffset) ?? null,
663
+ gridSize: num2(s.gridSize) ?? null,
664
+ opacity: num2(s.opacity) ?? null,
665
+ dashOffset: num2(s.dashOffset) ?? null,
413
666
  textColor: rgba(s.textColor) ?? null,
414
667
  named: this.colorNames(s.named)
415
668
  };
@@ -443,13 +696,13 @@ var Reader = class {
443
696
  endpoint(v) {
444
697
  const e = isObj(v) ? v : {};
445
698
  const port = str(e.port);
446
- const portIndex = num(e.portIndex);
699
+ const portIndex = num2(e.portIndex);
447
700
  return {
448
701
  elementID: uuid(e.elementID) ?? null,
449
702
  port: port && ["top", "right", "bottom", "left"].includes(port) ? port : null,
450
703
  portIndex: portIndex !== void 0 && Number.isInteger(portIndex) && portIndex >= 0 ? portIndex : null,
451
- x: num(e.x) ?? 0,
452
- y: num(e.y) ?? 0
704
+ x: num2(e.x) ?? 0,
705
+ y: num2(e.y) ?? 0
453
706
  };
454
707
  }
455
708
  connector(v) {
@@ -468,7 +721,7 @@ var Reader = class {
468
721
  endHead: head(v.endHead, "arrow"),
469
722
  waypoints: Array.isArray(v.waypoints) ? v.waypoints.filter(isObj).map((w) => {
470
723
  this.fields(w, "waypoint");
471
- return { x: num(w.x) ?? 0, y: num(w.y) ?? 0 };
724
+ return { x: num2(w.x) ?? 0, y: num2(w.y) ?? 0 };
472
725
  }) : null,
473
726
  hops: typeof v.hops === "boolean" ? v.hops : null,
474
727
  avoid: typeof v.avoid === "boolean" ? v.avoid : null,
@@ -504,20 +757,20 @@ var Reader = class {
504
757
  id,
505
758
  kind,
506
759
  layerID,
507
- x: num(v.x) ?? 0,
508
- y: num(v.y) ?? 0,
509
- width: num(v.width) ?? 0,
510
- height: num(v.height) ?? 0,
760
+ x: num2(v.x) ?? 0,
761
+ y: num2(v.y) ?? 0,
762
+ width: num2(v.width) ?? 0,
763
+ height: num2(v.height) ?? 0,
511
764
  style: this.style(v.style),
512
- seed: (num(v.seed) ?? 1) >>> 0,
765
+ seed: (num2(v.seed) ?? 1) >>> 0,
513
766
  text: str(v.text) ?? null,
514
767
  connector: this.connector(v.connector),
515
768
  groupID: uuid(v.groupID) ?? null,
516
- points: Array.isArray(v.points) ? v.points.filter(isObj).map((p) => ({ x: num(p.x) ?? 0, y: num(p.y) ?? 0 })) : null,
769
+ points: Array.isArray(v.points) ? v.points.filter(isObj).map((p) => ({ x: num2(p.x) ?? 0, y: num2(p.y) ?? 0 })) : null,
517
770
  path: Array.isArray(v.path) ? v.path.filter((c) => typeof c === "number") : null,
518
771
  subpaths,
519
772
  evenOdd: bool(v.evenOdd) ?? null,
520
- rotation: num(v.rotation) ?? null,
773
+ rotation: num2(v.rotation) ?? null,
521
774
  link: uuid(v.link) ?? null,
522
775
  url: str(v.url) ?? null,
523
776
  anchor: str(v.anchor) ?? null,
@@ -527,18 +780,18 @@ var Reader = class {
527
780
  overrides: this.overrides(v.overrides),
528
781
  symbol: uuid(v.symbol) ?? null,
529
782
  playback: this.playback(v.playback),
530
- offset: num(v.offset) ?? null,
783
+ offset: num2(v.offset) ?? null,
531
784
  args: strings(v.args),
532
785
  image: this.image(v.image, images),
533
- reveal: num(v.reveal) ?? null,
786
+ reveal: num2(v.reveal) ?? null,
534
787
  ports: Array.isArray(v.ports) ? v.ports.map((p) => {
535
788
  const o = isObj(p) ? p : {};
536
- return { x: num(o.x) ?? 0, y: num(o.y) ?? 0 };
789
+ return { x: num2(o.x) ?? 0, y: num2(o.y) ?? 0 };
537
790
  }) : null,
538
791
  labelRect: this.labelRect(v.labelRect),
539
792
  extension: this.extension(v.extension),
540
- capacity: num(v.capacity) ?? null,
541
- delay: num(v.delay) ?? null,
793
+ capacity: num2(v.capacity) ?? null,
794
+ delay: num2(v.delay) ?? null,
542
795
  queue: v.queue === true ? true : null,
543
796
  gauge: this.gauge(v.gauge),
544
797
  containerID: uuid(v.containerID) ?? null,
@@ -563,7 +816,7 @@ var Reader = class {
563
816
  labelRect(v) {
564
817
  if (!isObj(v)) return null;
565
818
  this.fields(v, "normalizedRect");
566
- return { x: num(v.x) ?? 0, y: num(v.y) ?? 0, width: num(v.width) ?? 0, height: num(v.height) ?? 0 };
819
+ return { x: num2(v.x) ?? 0, y: num2(v.y) ?? 0, width: num2(v.width) ?? 0, height: num2(v.height) ?? 0 };
567
820
  }
568
821
  extension(v) {
569
822
  if (!isObj(v)) return null;
@@ -584,7 +837,7 @@ var Reader = class {
584
837
  variables(v) {
585
838
  if (!isObj(v)) return null;
586
839
  const out = {};
587
- for (const [k, b] of Object.entries(v)) if (typeof b === "boolean") out[k] = b;
840
+ for (const [k, b] of Object.entries(v)) if (typeof b === "boolean" || typeof b === "number" && Number.isFinite(b)) out[k] = b;
588
841
  return Object.keys(out).length > 0 ? out : null;
589
842
  }
590
843
  click(v) {
@@ -596,12 +849,22 @@ var Reader = class {
596
849
  let set = null;
597
850
  if (isObj(v.set)) {
598
851
  set = {};
599
- for (const [k, b] of Object.entries(v.set)) if (typeof b === "boolean" && isName(k)) set[k] = b;
852
+ for (const [k, b] of Object.entries(v.set)) {
853
+ if (isName(k) && (typeof b === "boolean" || typeof b === "string" || typeof b === "number" && Number.isFinite(b))) set[k] = b;
854
+ }
600
855
  if (Object.keys(set).length === 0) set = null;
601
856
  }
602
857
  const raw = typeof v.toggle === "string" ? [v.toggle] : Array.isArray(v.toggle) && v.toggle.every((x) => typeof x === "string") ? v.toggle : null;
603
858
  const toggle = raw ? raw.filter(isName) : null;
604
- return { scene: str(v.scene) ?? null, url: safe, set, toggle: toggle && toggle.length > 0 ? toggle : null, reset: v.reset === true ? true : null };
859
+ const run = str(v.run);
860
+ return {
861
+ scene: str(v.scene) ?? null,
862
+ url: safe,
863
+ set,
864
+ toggle: toggle && toggle.length > 0 ? toggle : null,
865
+ reset: v.reset === true ? true : null,
866
+ run: run !== void 0 && isName(run) ? run : null
867
+ };
605
868
  }
606
869
  playback(v) {
607
870
  const s = str(v);
@@ -617,7 +880,7 @@ var Reader = class {
617
880
  return null;
618
881
  }
619
882
  const size = (x) => {
620
- const n = num(x);
883
+ const n = num2(x);
621
884
  return Math.max(1, n ?? 100);
622
885
  };
623
886
  const layers = (Array.isArray(v.layers) ? v.layers : []).filter(isObj).flatMap((l) => {
@@ -654,8 +917,8 @@ var Reader = class {
654
917
  stroke: rgba(o.stroke) ?? null,
655
918
  fill: rgba(o.fill) ?? null,
656
919
  textColor: rgba(o.textColor) ?? null,
657
- opacity: num(o.opacity) ?? null,
658
- strokeWidth: num(o.strokeWidth) ?? null,
920
+ opacity: num2(o.opacity) ?? null,
921
+ strokeWidth: num2(o.strokeWidth) ?? null,
659
922
  dash: dash !== void 0 && ["solid", "dashed", "dotted"].includes(dash) ? dash : null,
660
923
  text: str(o.text) ?? null,
661
924
  reroute,
@@ -669,7 +932,7 @@ var Reader = class {
669
932
  hover(v) {
670
933
  if (!isObj(v)) return null;
671
934
  this.fields(v, "hover");
672
- return { stroke: rgba(v.stroke) ?? null, fill: rgba(v.fill) ?? null, opacity: num(v.opacity) ?? null };
935
+ return { stroke: rgba(v.stroke) ?? null, fill: rgba(v.fill) ?? null, opacity: num2(v.opacity) ?? null };
673
936
  }
674
937
  ease(v) {
675
938
  const s = str(v);
@@ -683,11 +946,11 @@ var Reader = class {
683
946
  keyframe(v) {
684
947
  if (!isObj(v)) return null;
685
948
  this.fields(v, "keyframe");
686
- const t = num(v.t);
949
+ const t = num2(v.t);
687
950
  if (t === void 0) return null;
688
951
  const k = { t };
689
952
  for (const p of ["x", "y", "width", "height", "rotation", "strokeWidth", "reveal", "opacity"]) {
690
- const n = num(v[p]);
953
+ const n = num2(v[p]);
691
954
  if (n !== void 0) k[p] = n;
692
955
  }
693
956
  const stroke = rgba(v.stroke), fill = rgba(v.fill), visible = bool(v.visible), ease = this.ease(v.ease);
@@ -705,39 +968,39 @@ var Reader = class {
705
968
  const keys = (Array.isArray(v.keys) ? v.keys : []).map((k) => this.keyframe(k)).filter((k) => k !== null && k.t >= 0 && k.t <= MAX_DURATION);
706
969
  stableSortBy(keys, (k) => k.t);
707
970
  const follow = Array.isArray(v.follow) ? v.follow.filter(isObj).flatMap((f) => {
708
- const path = uuid(f.path), start2 = num(f.start), end = num(f.end);
971
+ const path = uuid(f.path), start2 = num2(f.start), end = num2(f.end);
709
972
  if (!path || start2 === void 0 || end === void 0 || start2 < 0 || end > MAX_DURATION) return [];
710
- return [{ path, start: start2, end, ease: this.ease(f.ease), reverse: bool(f.reverse) ?? null, orient: bool(f.orient) ?? null, laps: num(f.laps) ?? null }];
973
+ return [{ path, start: start2, end, ease: this.ease(f.ease), reverse: bool(f.reverse) ?? null, orient: bool(f.orient) ?? null, laps: num2(f.laps) ?? null }];
711
974
  }) : null;
712
975
  const repeats = Array.isArray(v.repeats) ? v.repeats.filter(isObj).flatMap((r) => {
713
- const start2 = num(r.start), end = num(r.end);
976
+ const start2 = num2(r.start), end = num2(r.end);
714
977
  if (start2 === void 0 || end === void 0) return [];
715
- const count = num(r.count);
978
+ const count = num2(r.count);
716
979
  const rep = { start: start2, end, count: count === void 0 ? null : Math.trunc(count) };
717
980
  return repeatIsValid(rep) ? [rep] : [];
718
981
  }) : null;
719
- return { element, keys, boil: bool(v.boil) ?? null, follow, repeats, march: clampMarch(num(v.march)) };
982
+ return { element, keys, boil: bool(v.boil) ?? null, follow, repeats, march: clampMarch(num2(v.march)) };
720
983
  }
721
984
  timeline(v) {
722
985
  if (!isObj(v)) return null;
723
986
  this.fields(v, "timeline");
724
- const boil = num(v.boil);
987
+ const boil = num2(v.boil);
725
988
  const camera = Array.isArray(v.camera) ? v.camera.filter(isObj).flatMap((c) => {
726
- const t = num(c.t), x = num(c.x), y = num(c.y), width = num(c.width), height = num(c.height);
989
+ const t = num2(c.t), x = num2(c.x), y = num2(c.y), width = num2(c.width), height = num2(c.height);
727
990
  if (t === void 0 || x === void 0 || y === void 0 || width === void 0 || height === void 0) return [];
728
991
  if (!(width > 1 && height > 1 && t >= 0)) return [];
729
992
  return [{ t, x, y, width, height, ease: this.ease(c.ease) }];
730
993
  }) : null;
731
994
  if (camera) stableSortBy(camera, (c) => c.t);
732
995
  const markers = Array.isArray(v.markers) ? v.markers.filter(isObj).flatMap((m) => {
733
- const t = num(m.t);
996
+ const t = num2(m.t);
734
997
  return t !== void 0 && t >= 0 ? [{ t, name: str(m.name) ?? "", loop: bool(m.loop) ?? null }] : [];
735
998
  }) : null;
736
999
  if (markers) stableSortBy(markers, (m) => m.t);
737
- const poster = num(v.poster);
1000
+ const poster = num2(v.poster);
738
1001
  return {
739
- fps: clampFPS(num(v.fps) ?? 12),
740
- duration: clampTime(num(v.duration) ?? 0),
1002
+ fps: clampFPS(num2(v.fps) ?? 12),
1003
+ duration: clampTime(num2(v.duration) ?? 0),
741
1004
  boil: boil !== void 0 && Number.isInteger(boil) && boil > 0 ? Math.min(boil, 1e4) : null,
742
1005
  settle: bool(v.settle) ?? null,
743
1006
  poster: poster === void 0 ? null : clampTime(poster),
@@ -764,6 +1027,7 @@ var Reader = class {
764
1027
  elements: (Array.isArray(v.elements) ? v.elements : []).map((e) => this.element(e, images)).filter((e) => e !== null),
765
1028
  theme: str(v.theme) ?? null,
766
1029
  customTheme: this.customTheme(v.customTheme),
1030
+ logic: typeof v.logic === "string" && v.logic.length > 0 ? v.logic : null,
767
1031
  timeline: this.timeline(v.timeline),
768
1032
  symbols: Array.isArray(v.symbols) ? v.symbols.map((x) => this.symbol(x, images)).filter((x) => x !== null) : null,
769
1033
  variables: this.variables(v.variables),
@@ -775,7 +1039,7 @@ var Reader = class {
775
1039
  this.fields(f, "flow");
776
1040
  const id = (x) => typeof x === "string" && UUID.test(x) ? x.toUpperCase() : NO_ID;
777
1041
  const finite = (x) => {
778
- const n = num(x);
1042
+ const n = num2(x);
779
1043
  return n !== void 0 && Number.isFinite(n) ? n : null;
780
1044
  };
781
1045
  return {
@@ -815,7 +1079,7 @@ function parseDottie(source) {
815
1079
  }
816
1080
  }
817
1081
  if (!isObj(json)) throw new DottieFormatError("Not a Dottie drawing");
818
- const version = num(json.version);
1082
+ const version = num2(json.version);
819
1083
  if (version === void 0) throw new DottieFormatError("Not a Dottie drawing (no version)");
820
1084
  if (!Array.isArray(json.pages) || json.pages.length === 0) throw new DottieFormatError("A drawing needs at least one page");
821
1085
  const reader = new Reader();
@@ -3063,7 +3327,7 @@ function hopCrossings(e, r, page, index) {
3063
3327
  for (const samples of segments) {
3064
3328
  const along = runningLengths(samples);
3065
3329
  const length = along[along.length - 1];
3066
- const found = [];
3330
+ const found2 = [];
3067
3331
  const near = [];
3068
3332
  const whole = boxOf(samples);
3069
3333
  for (let n = 0; n < count; n++) if (touching(whole, lines[n].box)) near.push(lines[n]);
@@ -3080,12 +3344,12 @@ function hopCrossings(e, r, page, index) {
3080
3344
  if (Math.abs(det) < 1e-9) continue;
3081
3345
  const wx = a.x - p.x, wy = a.y - p.y;
3082
3346
  const t = (wx * ey - wy * ex) / det, s = (wx * dy - wy * dx) / det;
3083
- if (t > 0 && t < 1 && s >= 0 && s <= 1) found.push(along[i] + t * (along[i + 1] - along[i]));
3347
+ if (t > 0 && t < 1 && s >= 0 && s <= 1) found2.push(along[i] + t * (along[i + 1] - along[i]));
3084
3348
  }
3085
3349
  }
3086
3350
  }
3087
3351
  const kept = [];
3088
- for (const at of found.sort((x, y) => x - y)) {
3352
+ for (const at of found2.sort((x, y) => x - y)) {
3089
3353
  if (at < rad + 2 || at > length - rad - 2) continue;
3090
3354
  if (kept.length > 0 && at - kept[kept.length - 1] < 2 * rad + 2) continue;
3091
3355
  kept.push(at);
@@ -3299,7 +3563,7 @@ var lerpColor = (a, b, u) => ({
3299
3563
  b: mix01(a.b, b.b, u),
3300
3564
  a: mix01(a.a, b.a, u)
3301
3565
  });
3302
- function num2(track, t, p, base2) {
3566
+ function num3(track, t, p, base2) {
3303
3567
  return value(track, t, (k) => k[p], base2, lerpNum);
3304
3568
  }
3305
3569
  function isChanging(track, t) {
@@ -3325,20 +3589,20 @@ function isVisible(track, t) {
3325
3589
  function applyTrack(track, e, t) {
3326
3590
  e = cloneElement(e);
3327
3591
  if (track.keys.some((k) => k.reveal !== void 0)) {
3328
- const r = num2(track, t, "reveal", e.reveal ?? 1);
3592
+ const r = num3(track, t, "reveal", e.reveal ?? 1);
3329
3593
  e.reveal = r >= 1 ? null : Math.max(0, r);
3330
3594
  }
3331
3595
  if (track.keys.some((k) => k.opacity !== void 0)) {
3332
- const o = Math.min(Math.max(num2(track, t, "opacity", e.style.opacity ?? 1), 0), 1);
3596
+ const o = Math.min(Math.max(num3(track, t, "opacity", e.style.opacity ?? 1), 0), 1);
3333
3597
  e.style.opacity = o >= 1 ? null : o;
3334
3598
  }
3335
3599
  if (e.kind === "connector") return e;
3336
- e.x = num2(track, t, "x", e.x);
3337
- e.y = num2(track, t, "y", e.y);
3338
- e.width = Math.max(0, num2(track, t, "width", e.width));
3339
- e.height = Math.max(0, num2(track, t, "height", e.height));
3340
- if (track.keys.some((k) => k.rotation !== void 0)) e.rotation = num2(track, t, "rotation", angle(e));
3341
- e.style.strokeWidth = Math.max(0, num2(track, t, "strokeWidth", e.style.strokeWidth));
3600
+ e.x = num3(track, t, "x", e.x);
3601
+ e.y = num3(track, t, "y", e.y);
3602
+ e.width = Math.max(0, num3(track, t, "width", e.width));
3603
+ e.height = Math.max(0, num3(track, t, "height", e.height));
3604
+ if (track.keys.some((k) => k.rotation !== void 0)) e.rotation = num3(track, t, "rotation", angle(e));
3605
+ e.style.strokeWidth = Math.max(0, num3(track, t, "strokeWidth", e.style.strokeWidth));
3342
3606
  e.style.stroke = value(track, t, (k) => k.stroke, e.style.stroke, lerpColor);
3343
3607
  e.style.fill = value(track, t, (k) => k.fill, e.style.fill, lerpColor);
3344
3608
  return e;
@@ -3414,7 +3678,8 @@ function posedWithMetrics(page, t, state = "initial", since = null, carried = {}
3414
3678
  }
3415
3679
  const flowing = (page.flows ?? []).length > 0;
3416
3680
  const measuring = flowing || page.elements.some((e) => e.gauge || (e.overrides ?? []).some((o) => mentionsMetric(o.when)));
3417
- const timeline = page.timeline ?? (off.size === 0 && active.size === 0 && !measuring ? null : EMPTY_TIMELINE);
3681
+ const fills = values !== null && Object.keys(values).length > 0 && page.elements.some((e) => e.text?.includes("{") || (e.overrides ?? []).some((o) => o.text?.includes("{")));
3682
+ const timeline = page.timeline ?? (off.size === 0 && active.size === 0 && !measuring && !fills ? null : EMPTY_TIMELINE);
3418
3683
  if (!timeline) return { frame: page, metrics: emptyMetrics() };
3419
3684
  t = clampTime(t);
3420
3685
  const tracks = trackMap(timeline);
@@ -3450,6 +3715,10 @@ function posedWithMetrics(page, t, state = "initial", since = null, carried = {}
3450
3715
  const track = tracks.get(e.id);
3451
3716
  let out = track ? applyTrack(track, e, t) : e;
3452
3717
  for (const o of active.get(e.id) ?? []) out = applyOverride(o, out);
3718
+ if (fills && values && out.text) {
3719
+ const text = filling(out.text, values);
3720
+ if (text !== out.text) out = { ...out, text };
3721
+ }
3453
3722
  const list = active.get(e.id);
3454
3723
  if (list) {
3455
3724
  const caps = list.map((o) => o.capacity).filter((c) => c !== null && Number.isFinite(c));
@@ -3767,7 +4036,12 @@ function clickTargets(page, file) {
3767
4036
  let pageOf = null;
3768
4037
  for (const e of page.elements) {
3769
4038
  const c = e.click;
3770
- const state = c && changesState(c) ? { ...c.set ? { set: c.set } : {}, ...c.toggle ? { toggle: c.toggle } : {}, ...c.reset ? { reset: true } : {} } : null;
4039
+ const state = c && changesState(c) ? {
4040
+ ...c.set ? { set: c.set } : {},
4041
+ ...c.toggle ? { toggle: c.toggle } : {},
4042
+ ...c.reset ? { reset: true } : {},
4043
+ ...c.run ? { run: c.run } : {}
4044
+ } : null;
3771
4045
  if (c?.scene) {
3772
4046
  const i = sceneNamed(c.scene, markers);
3773
4047
  if (i >= 0) {
@@ -4805,6 +5079,40 @@ function servePlans() {
4805
5079
  });
4806
5080
  }
4807
5081
 
5082
+ // src/logic-loader.ts
5083
+ var scriptSrc = typeof document !== "undefined" ? document.currentScript?.src ?? null : null;
5084
+ var found = null;
5085
+ var present = () => globalThis.DottieLogic;
5086
+ function logicEngine() {
5087
+ found ?? (found = (async () => {
5088
+ if (!present()) {
5089
+ const here = import.meta.url;
5090
+ const base2 = here ?? scriptSrc;
5091
+ if (!base2) throw new Error("No dottie-logic.min.js on the page, and no address to find it from");
5092
+ const url = new URL("./dottie-logic.min.js", base2).href;
5093
+ if (here) await import(
5094
+ /* @vite-ignore */
5095
+ url
5096
+ );
5097
+ else await new Promise((resolve2, reject) => {
5098
+ const s = document.createElement("script");
5099
+ s.src = url;
5100
+ s.onload = () => resolve2();
5101
+ s.onerror = () => reject(new Error(`Couldn't load ${url}`));
5102
+ document.head.append(s);
5103
+ });
5104
+ }
5105
+ const engine = present();
5106
+ if (!engine) throw new Error("dottie-logic.min.js didn't load");
5107
+ await engine.loadLogic();
5108
+ return engine;
5109
+ })());
5110
+ found.catch(() => {
5111
+ found = null;
5112
+ });
5113
+ return found;
5114
+ }
5115
+
4808
5116
  // src/player.ts
4809
5117
  var WHITE = { r: 1, g: 1, b: 1, a: 1 };
4810
5118
  function pageIndex(file, spec) {
@@ -5146,6 +5454,9 @@ var DottiePlayer = class extends ElementBase {
5146
5454
  __publicField(this, "stillTime", null);
5147
5455
  __publicField(this, "visible", true);
5148
5456
  __publicField(this, "observer", null);
5457
+ /** Runs handler `handler` from the page's logic for a click on `id` (DottieDocument.clicked). Clicks take turns, so
5458
+ * each handler sees the state the one before left. */
5459
+ __publicField(this, "logicQueue", Promise.resolve());
5149
5460
  this.root = this.attachShadow({ mode: "open" });
5150
5461
  this.root.innerHTML = `<style>${STYLE}</style><div class="stage" part="stage" role="img"></div>
5151
5462
  <div class="bar" part="controls" hidden>
@@ -5372,7 +5683,9 @@ var DottiePlayer = class extends ElementBase {
5372
5683
  this.scheduleReplay();
5373
5684
  }
5374
5685
  if (!click) return;
5375
- if (click.set || click.toggle || click.reset) {
5686
+ if (click.run && p.page.logic && this.hasAttribute("allow-logic")) {
5687
+ this.runLogic(click.run, id, click.reset === true);
5688
+ } else if (click.set || click.toggle || click.reset) {
5376
5689
  this.setState(applyClick(
5377
5690
  { scene: null, url: null, set: click.set ?? null, toggle: click.toggle ?? null, reset: click.reset ?? null },
5378
5691
  p.state,
@@ -5394,6 +5707,35 @@ var DottiePlayer = class extends ElementBase {
5394
5707
  }
5395
5708
  }
5396
5709
  }
5710
+ runLogic(handler, id, reset) {
5711
+ const p = this.playback;
5712
+ if (!p) return;
5713
+ const e = p.page.elements.find((x) => x.id === id);
5714
+ const s = p.sceneAt(p.frame);
5715
+ const event = {
5716
+ id,
5717
+ anchor: e?.anchor ?? null,
5718
+ text: e?.text?.split("\n")[0] ?? null,
5719
+ time: this.currentTime,
5720
+ scene: s < 0 ? null : p.sceneNames[s]
5721
+ };
5722
+ this.logicQueue = this.logicQueue.then(async () => {
5723
+ const engine = await logicEngine();
5724
+ const now = this.playback;
5725
+ if (!now || now !== p || !now.page.logic) return;
5726
+ let start2 = now.state;
5727
+ if (reset) {
5728
+ start2 = {};
5729
+ for (const k of Object.keys(now.state)) start2[k] = false;
5730
+ Object.assign(start2, now.page.variables ?? {});
5731
+ }
5732
+ const r = engine.runLogic(now.page.logic, handler, start2, event);
5733
+ if (r.ok) this.setState({ ...start2, ...r.set });
5734
+ else this.dispatchEvent(new CustomEvent("logicerror", { detail: { element: id, handler, error: r.error } }));
5735
+ }).catch((err) => {
5736
+ this.dispatchEvent(new CustomEvent("logicerror", { detail: { element: id, handler, error: err.message } }));
5737
+ });
5738
+ }
5397
5739
  /** The page's variables now. */
5398
5740
  get variables() {
5399
5741
  return { ...this.playback?.state ?? {} };
@@ -5500,7 +5842,7 @@ var DottiePlayer = class extends ElementBase {
5500
5842
  if (handled) e.preventDefault();
5501
5843
  }
5502
5844
  };
5503
- __publicField(DottiePlayer, "observedAttributes", ["src", "page", "at", "clean", "no-controls", "label"]);
5845
+ __publicField(DottiePlayer, "observedAttributes", ["src", "page", "at", "clean", "no-controls", "label", "allow-logic"]);
5504
5846
  function clickable(target) {
5505
5847
  const el = target;
5506
5848
  return el && typeof el.closest === "function" ? el.closest(".dottie-a") : null;
@@ -5605,7 +5947,7 @@ function render(source, options = {}) {
5605
5947
  function isFile(v) {
5606
5948
  return typeof v === "object" && v !== null && Array.isArray(v.pages) && Array.isArray(v.warnings);
5607
5949
  }
5608
- var VERSION = "0.10.0";
5950
+ var VERSION = "0.11.0";
5609
5951
 
5610
5952
  // src/player-entry.ts
5611
5953
  servePlans();