@phin-tech/dottie 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PARITY.md +10 -7
- package/README.md +10 -2
- package/dist/compile.js +103 -11
- package/dist/dottie-compile.mjs +104 -12
- package/dist/dottie-player.js +1316 -100
- package/dist/dottie-player.min.js +55 -52
- package/dist/dottie-sim.min.js +4 -0
- package/dist/dottie.js +1300 -100
- package/dist/types/clicks.d.ts +1 -0
- package/dist/types/compile.d.ts +1 -1
- package/dist/types/connector.d.ts +4 -0
- package/dist/types/flows.d.ts +28 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/measure.d.ts +73 -0
- package/dist/types/model.d.ts +66 -0
- package/dist/types/planner.d.ts +12 -0
- package/dist/types/player.d.ts +21 -1
- package/dist/types/sim-entry.d.ts +1 -0
- package/dist/types/state.d.ts +28 -8
- package/dist/types/svg.d.ts +9 -2
- package/dist/types/symbols.d.ts +19 -3
- package/dist/types/timeline.d.ts +14 -4
- package/package.json +1 -1
package/PARITY.md
CHANGED
|
@@ -27,7 +27,7 @@ fixture, so the gap is visible rather than silent.
|
|
|
27
27
|
| Waypoints (bends) on every routing, and hops | Supported | [edge/waypoints](../fixtures/edge/waypoints.dottie), [edge/waypoints-symbol](../fixtures/edge/waypoints-symbol.dottie) | Hops need the page, so `connectorParts` takes it; without one a line draws none. |
|
|
28
28
|
| Arrowheads: arrow, triangle, dot, bar | Supported | [edge/connectors](../fixtures/edge/connectors.dottie) | |
|
|
29
29
|
| Label colors (`textColor`, apart from the stroke) | Supported | [edge/text-colors](../fixtures/edge/text-colors.dottie) | Text boxes and notes ignore it, as in Dottie |
|
|
30
|
-
| Connector labels | Supported | [edge/connectors](../fixtures/edge/connectors.dottie) | Label boxes sized with CoreText's measurements. The player paints them on the page color, like the app
|
|
30
|
+
| Connector labels | Supported | [edge/connectors](../fixtures/edge/connectors.dottie) | Label boxes sized with CoreText's measurements. The player paints them on the page color, like the app |
|
|
31
31
|
| Keys and eases (linear, in, out, in-out, hold, spring, bounce, elastic) | Supported | [edge/timeline](../fixtures/edge/timeline.dottie), [edge/eases](../fixtures/edge/eases.dottie) | Unknown ease names play linear, with a warning |
|
|
32
32
|
| Visibility, reveal (draw-on, typing), opacity | Supported | [edge/timeline](../fixtures/edge/timeline.dottie) | |
|
|
33
33
|
| Transitions | Supported | [edge/transitions](../fixtures/edge/transitions.dottie) | They are ordinary keys in the file |
|
|
@@ -37,19 +37,22 @@ fixture, so the gap is visible rather than silent.
|
|
|
37
37
|
| Repeats (counted and forever) | Supported | [edge/timeline](../fixtures/edge/timeline.dottie) | |
|
|
38
38
|
| Boil (three drawings) and settle | Supported | [edge/timeline](../fixtures/edge/timeline.dottie) | Boiled seeds match bit for bit |
|
|
39
39
|
| Camera views | Supported | [edge/camera](../fixtures/edge/camera.dottie), [design/zoom](../fixtures/design/zoom.dottie) | |
|
|
40
|
-
| Scenes (markers) and click-through | Supported | [design/tour](../fixtures/design/tour.dottie) | Stops at each scene
|
|
40
|
+
| Scenes (markers) and click-through | Supported | [design/tour](../fixtures/design/tour.dottie) | Stops at each scene. The HTML export is this player |
|
|
41
41
|
| Poster frame, reduced motion | Supported | [edge/timeline](../fixtures/edge/timeline.dottie) | |
|
|
42
42
|
| Damaged timelines (clamped, filtered, sorted) | Supported | [edge/timeline](../fixtures/edge/timeline.dottie) | Read the way DottieKit's decoders read them |
|
|
43
43
|
| Unknown kinds, fields and newer versions | Partial | [js-only/future](../fixtures/js-only/future.dottie) | Drawn as labelled placeholders, reported in `warnings`; Dottie refuses such files |
|
|
44
44
|
| Text fonts | Partial | [edge/fonts](../fixtures/edge/fonts.dottie) | Measured with CoreText's metrics for Helvetica Neue and the bundled handwriting fonts (Caveat, Patrick Hand, Architects Daughter), which the player loads from `dist/fonts` and a compiled drawing carries; browsers without Helvetica Neue draw Helvetica or Arial in the same places, so runs of mixed styles may sit slightly apart. A font of one's own is laid out as Helvetica Neue and drawn in that font where the viewer has it |
|
|
45
45
|
| Symbols: instances on their own clocks (loop, once, still, offset), nested, scaled and turned | Supported | [edge/symbols](../fixtures/edge/symbols.dottie) | Expanded as DottieKit expands them, with the same ids, seeds and limits ([js-only/hostile-symbols](../fixtures/js-only/hostile-symbols.dottie)) |
|
|
46
|
-
| Button symbols (up, over, down, hit) and clickable copies | Supported | [edge/buttons](../fixtures/edge/buttons.dottie) |
|
|
46
|
+
| Button symbols (up, over, down, hit) and clickable copies | Supported | [edge/buttons](../fixtures/edge/buttons.dottie) | Up, over, down and hit, in the player and the HTML export alike |
|
|
47
47
|
| Symbol parameters (`{{name}}` in a symbol's text, filled per copy) | Supported | [edge/params](../fixtures/edge/params.dottie) | Defaults, undeclared names left as written, values passed into nested copies, filled before text types out |
|
|
48
|
-
| Copies that play when clicked | Supported | [edge/buttons](../fixtures/edge/buttons.dottie) |
|
|
49
|
-
| Clicks: play a scene, open a link, hover looks, keyboard | Supported | [edge/clicks](../fixtures/edge/clicks.dottie) |
|
|
48
|
+
| Copies that play when clicked | Supported | [edge/buttons](../fixtures/edge/buttons.dottie) | In the player and the HTML export |
|
|
49
|
+
| Clicks: play a scene, open a link, hover looks, keyboard | Supported | [edge/clicks](../fixtures/edge/clicks.dottie) | Only http, https and mailto links are followed |
|
|
50
50
|
| Page variables and conditions (`variables`, `when`) | Supported | [edge/state](../fixtures/edge/state.dottie) | Starting values in every still and export; connectors go with a shape the state hides |
|
|
51
|
-
|
|
|
52
|
-
|
|
|
51
|
+
| Overrides (`overrides`: restyle and reroute under a condition) | Supported | [edge/state](../fixtures/edge/state.dottie) | Opacity multiplies; a reroute or key that isn't an id is dropped as DottieKit drops it |
|
|
52
|
+
| Traffic flows (`flows`) | Supported | [edge/flows](../fixtures/edge/flows.dottie) | Routed each frame over the connectors drawn, cheapest by connector `cost` (ADR 0002); packet ids derive from the flow's |
|
|
53
|
+
| Volume, capacity, delay, metrics, gauges | Supported | [edge/flows](../fixtures/edge/flows.dottie) (Capacity page) | One implementation: Dottie runs `measure.ts` in JavaScriptCore (ADRs 0003, 0004). Assignment in page order, backlog piles, conditions on metrics, gauges expanded to `.path` elements |
|
|
54
|
+
| Clicks that set and toggle variables | Supported | [edge/state](../fixtures/edge/state.dottie) | Change what shows without touching the playhead |
|
|
55
|
+
| Looping scenes (`loop` on a marker) | Supported | [edge/state](../fixtures/edge/state.dottie) | No stop on entering, round from the scene's end to its start |
|
|
53
56
|
| Links out of the drawing (`url`) | Supported | [edge/links](../fixtures/edge/links.dottie) | A web or mail `url` opens when clicked if there is no `click`, and SVG export wraps it in `<a>`; a link to another drawing does nothing on the web |
|
|
54
57
|
| Links between shapes and pages | Partial | [edge/clicks](../fixtures/edge/clicks.dottie) | A link to a shape on another page shows that page; one on the same page does nothing. The HTML export holds one page, so it has neither |
|
|
55
58
|
| Editing | Missing | | |
|
package/README.md
CHANGED
|
@@ -37,8 +37,9 @@ click first fires a cancelable `action` event whose `detail` is `{element, scene
|
|
|
37
37
|
replay?}`; call `preventDefault()` to handle it yourself.
|
|
38
38
|
|
|
39
39
|
A click can also set or toggle the page's variables, which show and hide the elements with a `when` while the
|
|
40
|
-
animation keeps playing: a diagram you leave running that people poke.
|
|
41
|
-
|
|
40
|
+
animation keeps playing: a diagram you leave running that people poke. Elements can restyle themselves under a
|
|
41
|
+
condition (`overrides`), and a page's `flows` send traffic over whatever connectors are drawn, so it goes round a
|
|
42
|
+
region a click took down. A looping scene plays round until a click or next leaves it, instead of stopping.
|
|
42
43
|
|
|
43
44
|
The element has `play()`, `pause()`, `nextScene()`, `prevScene()`, `activate(elementId)`, `currentTime`
|
|
44
45
|
(settable), `duration`, `paused`, `variables` and `setState({name: value})`, and fires `load`, `frame`, `action`,
|
|
@@ -48,6 +49,13 @@ The element has `play()`, `pause()`, `nextScene()`, `prevScene()`, `activate(ele
|
|
|
48
49
|
Without modules, `dist/dottie-player.min.js` is a classic script that registers the element and sets
|
|
49
50
|
`window.Dottie`.
|
|
50
51
|
|
|
52
|
+
**Big animations.** Before it shows an animation without a camera, the player works out the view of every frame,
|
|
53
|
+
which for a long, busy one takes long enough to hold up the page. So it does that in a worker, and the drawing
|
|
54
|
+
appears, exactly as it would have, when the worker is done; `setFile()` returns at once, and the `load` event fires
|
|
55
|
+
when it is showing. The classic script starts the worker from its own source (a `blob:` URL); the module player
|
|
56
|
+
loads `dottie-player.min.js` from beside itself, so host the two together. Where a worker can't start, as under a
|
|
57
|
+
`worker-src` policy that refuses it, the player works it out in place as before. Small drawings always do.
|
|
58
|
+
|
|
51
59
|
**Fonts.** Text in Dottie's handwriting fonts (Caveat, Patrick Hand, Architects Daughter; SIL Open Font License)
|
|
52
60
|
is drawn in them: the player loads the ones a drawing uses from `fonts/` beside its own script, as `dist/fonts` on
|
|
53
61
|
npm and the CDNs. If you host the player yourself, copy that folder with it, or call `Dottie.setFontBase(url)`
|
package/dist/compile.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! dottie.js 0.
|
|
1
|
+
/*! dottie.js 0.9.0 | Apache-2.0 | https://github.com/phin-tech/dottie */
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -56,7 +56,9 @@ var KINDS = ["rectangle", "ellipse", "diamond", "text", "connector", "freehand",
|
|
|
56
56
|
var EASES = ["linear", "easeIn", "easeOut", "easeInOut", "hold", "spring", "bounce", "elastic"];
|
|
57
57
|
var KNOWN_FIELDS = {
|
|
58
58
|
file: ["version", "pages", "images"],
|
|
59
|
-
page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables"],
|
|
59
|
+
page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
|
|
60
|
+
flow: ["id", "from", "to", "every", "speed", "color", "size", "when", "spread", "volume", "overrides"],
|
|
61
|
+
flowOverride: ["when", "volume"],
|
|
60
62
|
symbol: ["id", "name", "width", "height", "layers", "elements", "timeline", "button", "params"],
|
|
61
63
|
layer: ["id", "name", "visible", "locked"],
|
|
62
64
|
rgba: ["r", "g", "b", "a"],
|
|
@@ -85,6 +87,7 @@ var KNOWN_FIELDS = {
|
|
|
85
87
|
"click",
|
|
86
88
|
"hover",
|
|
87
89
|
"when",
|
|
90
|
+
"overrides",
|
|
88
91
|
"symbol",
|
|
89
92
|
"playback",
|
|
90
93
|
"offset",
|
|
@@ -93,8 +96,13 @@ var KNOWN_FIELDS = {
|
|
|
93
96
|
"reveal",
|
|
94
97
|
"ports",
|
|
95
98
|
"labelRect",
|
|
96
|
-
"extension"
|
|
99
|
+
"extension",
|
|
100
|
+
"capacity",
|
|
101
|
+
"delay",
|
|
102
|
+
"queue",
|
|
103
|
+
"gauge"
|
|
97
104
|
],
|
|
105
|
+
gauge: ["metric", "of", "max", "warn", "alarm", "style", "label"],
|
|
98
106
|
strokePoint: ["x", "y"],
|
|
99
107
|
subpath: ["closed", "coords"],
|
|
100
108
|
inlineImage: ["data", "format"],
|
|
@@ -102,7 +110,7 @@ var KNOWN_FIELDS = {
|
|
|
102
110
|
extensionRef: ["id", "shape", "version", "params"],
|
|
103
111
|
normalizedPoint: ["x", "y"],
|
|
104
112
|
normalizedRect: ["x", "y", "width", "height"],
|
|
105
|
-
connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops"],
|
|
113
|
+
connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops", "cost"],
|
|
106
114
|
waypoint: ["x", "y"],
|
|
107
115
|
timeline: ["fps", "duration", "boil", "settle", "poster", "tracks", "camera", "markers"],
|
|
108
116
|
track: ["element", "keys", "boil", "follow", "repeats", "march"],
|
|
@@ -111,8 +119,9 @@ var KNOWN_FIELDS = {
|
|
|
111
119
|
repeat: ["start", "end", "count"],
|
|
112
120
|
cameraKey: ["t", "x", "y", "width", "height", "ease"],
|
|
113
121
|
marker: ["t", "name", "loop"],
|
|
114
|
-
click: ["scene", "url", "set", "toggle"],
|
|
115
|
-
hover: ["stroke", "fill", "opacity"]
|
|
122
|
+
click: ["scene", "url", "set", "toggle", "reset"],
|
|
123
|
+
hover: ["stroke", "fill", "opacity"],
|
|
124
|
+
override: ["when", "stroke", "fill", "textColor", "opacity", "strokeWidth", "dash", "text", "reroute", "offline", "cost", "capacity", "delay"]
|
|
116
125
|
};
|
|
117
126
|
var MAX_DURATION = 3600;
|
|
118
127
|
var MAX_MARCH = 1e4;
|
|
@@ -126,6 +135,8 @@ var num = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
|
126
135
|
var str = (v) => typeof v === "string" ? v : void 0;
|
|
127
136
|
var strings = (v) => isObj(v) && Object.values(v).every((x) => typeof x === "string") ? { ...v } : null;
|
|
128
137
|
var bool = (v) => typeof v === "boolean" ? v : void 0;
|
|
138
|
+
var NO_ID = "00000000-0000-0000-0000-000000000000";
|
|
139
|
+
var UUID = /^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/;
|
|
129
140
|
var uuid = (v) => typeof v === "string" ? v.toUpperCase() : void 0;
|
|
130
141
|
function clampTime(t) {
|
|
131
142
|
if (!Number.isFinite(t)) return t === Infinity ? MAX_DURATION : 0;
|
|
@@ -214,7 +225,8 @@ var Reader = class {
|
|
|
214
225
|
this.fields(w, "waypoint");
|
|
215
226
|
return { x: num(w.x) ?? 0, y: num(w.y) ?? 0 };
|
|
216
227
|
}) : null,
|
|
217
|
-
hops: typeof v.hops === "boolean" ? v.hops : null
|
|
228
|
+
hops: typeof v.hops === "boolean" ? v.hops : null,
|
|
229
|
+
cost: typeof v.cost === "number" && Number.isFinite(v.cost) ? v.cost : null
|
|
218
230
|
};
|
|
219
231
|
}
|
|
220
232
|
image(v, table) {
|
|
@@ -266,6 +278,7 @@ var Reader = class {
|
|
|
266
278
|
click: this.click(v.click),
|
|
267
279
|
hover: this.hover(v.hover),
|
|
268
280
|
when: str(v.when) ?? null,
|
|
281
|
+
overrides: this.overrides(v.overrides),
|
|
269
282
|
symbol: uuid(v.symbol) ?? null,
|
|
270
283
|
playback: this.playback(v.playback),
|
|
271
284
|
offset: num(v.offset) ?? null,
|
|
@@ -277,7 +290,26 @@ var Reader = class {
|
|
|
277
290
|
return { x: num(o.x) ?? 0, y: num(o.y) ?? 0 };
|
|
278
291
|
}) : null,
|
|
279
292
|
labelRect: this.labelRect(v.labelRect),
|
|
280
|
-
extension: this.extension(v.extension)
|
|
293
|
+
extension: this.extension(v.extension),
|
|
294
|
+
capacity: num(v.capacity) ?? null,
|
|
295
|
+
delay: num(v.delay) ?? null,
|
|
296
|
+
queue: v.queue === true ? true : null,
|
|
297
|
+
gauge: this.gauge(v.gauge)
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
gauge(v) {
|
|
301
|
+
if (!isObj(v)) return null;
|
|
302
|
+
this.fields(v, "gauge");
|
|
303
|
+
const finite = (x) => typeof x === "number" && Number.isFinite(x) ? x : null;
|
|
304
|
+
const style = str(v.style);
|
|
305
|
+
return {
|
|
306
|
+
metric: str(v.metric) ?? "",
|
|
307
|
+
of: typeof v.of === "string" && UUID.test(v.of) ? v.of.toUpperCase() : NO_ID,
|
|
308
|
+
max: finite(v.max),
|
|
309
|
+
warn: finite(v.warn),
|
|
310
|
+
alarm: finite(v.alarm),
|
|
311
|
+
style: style === "number" || style === "bar" || style === "dial" ? style : null,
|
|
312
|
+
label: str(v.label) ?? null
|
|
281
313
|
};
|
|
282
314
|
}
|
|
283
315
|
labelRect(v) {
|
|
@@ -321,7 +353,7 @@ var Reader = class {
|
|
|
321
353
|
}
|
|
322
354
|
const raw = typeof v.toggle === "string" ? [v.toggle] : Array.isArray(v.toggle) && v.toggle.every((x) => typeof x === "string") ? v.toggle : null;
|
|
323
355
|
const toggle = raw ? raw.filter(isName) : null;
|
|
324
|
-
return { scene: str(v.scene) ?? null, url: safe, set, toggle: toggle && toggle.length > 0 ? toggle : null };
|
|
356
|
+
return { scene: str(v.scene) ?? null, url: safe, set, toggle: toggle && toggle.length > 0 ? toggle : null, reset: v.reset === true ? true : null };
|
|
325
357
|
}
|
|
326
358
|
playback(v) {
|
|
327
359
|
const s = str(v);
|
|
@@ -357,6 +389,35 @@ var Reader = class {
|
|
|
357
389
|
params: strings(v.params)
|
|
358
390
|
};
|
|
359
391
|
}
|
|
392
|
+
/** As DottieKit reads them: a reroute whose targets aren't all ids is dropped, as are keys that aren't ids. */
|
|
393
|
+
overrides(v) {
|
|
394
|
+
if (!Array.isArray(v)) return null;
|
|
395
|
+
return v.filter(isObj).map((o) => {
|
|
396
|
+
this.fields(o, "override");
|
|
397
|
+
const dash = str(o.dash);
|
|
398
|
+
let reroute = null;
|
|
399
|
+
if (isObj(o.reroute) && Object.values(o.reroute).every((x) => typeof x === "string" && UUID.test(x))) {
|
|
400
|
+
reroute = {};
|
|
401
|
+
for (const [k, x] of Object.entries(o.reroute)) if (UUID.test(k)) reroute[k.toUpperCase()] = x.toUpperCase();
|
|
402
|
+
if (Object.keys(reroute).length === 0) reroute = null;
|
|
403
|
+
}
|
|
404
|
+
return {
|
|
405
|
+
when: str(o.when) ?? "",
|
|
406
|
+
stroke: rgba(o.stroke) ?? null,
|
|
407
|
+
fill: rgba(o.fill) ?? null,
|
|
408
|
+
textColor: rgba(o.textColor) ?? null,
|
|
409
|
+
opacity: num(o.opacity) ?? null,
|
|
410
|
+
strokeWidth: num(o.strokeWidth) ?? null,
|
|
411
|
+
dash: dash !== void 0 && ["solid", "dashed", "dotted"].includes(dash) ? dash : null,
|
|
412
|
+
text: str(o.text) ?? null,
|
|
413
|
+
reroute,
|
|
414
|
+
offline: o.offline === true ? true : null,
|
|
415
|
+
cost: typeof o.cost === "number" && Number.isFinite(o.cost) ? o.cost : null,
|
|
416
|
+
capacity: typeof o.capacity === "number" && Number.isFinite(o.capacity) ? o.capacity : null,
|
|
417
|
+
delay: typeof o.delay === "number" && Number.isFinite(o.delay) ? o.delay : null
|
|
418
|
+
};
|
|
419
|
+
});
|
|
420
|
+
}
|
|
360
421
|
hover(v) {
|
|
361
422
|
if (!isObj(v)) return null;
|
|
362
423
|
this.fields(v, "hover");
|
|
@@ -456,7 +517,33 @@ var Reader = class {
|
|
|
456
517
|
theme: str(v.theme) ?? null,
|
|
457
518
|
timeline: this.timeline(v.timeline),
|
|
458
519
|
symbols: Array.isArray(v.symbols) ? v.symbols.map((x) => this.symbol(x, images)).filter((x) => x !== null) : null,
|
|
459
|
-
variables: this.variables(v.variables)
|
|
520
|
+
variables: this.variables(v.variables),
|
|
521
|
+
flows: Array.isArray(v.flows) ? v.flows.filter(isObj).map((f) => this.flow(f)) : null
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
/** As DottieKit reads one: a missing or bad id, source or destination sends nothing; bad destinations are dropped. */
|
|
525
|
+
flow(f) {
|
|
526
|
+
this.fields(f, "flow");
|
|
527
|
+
const id = (x) => typeof x === "string" && UUID.test(x) ? x.toUpperCase() : NO_ID;
|
|
528
|
+
const finite = (x) => {
|
|
529
|
+
const n = num(x);
|
|
530
|
+
return n !== void 0 && Number.isFinite(n) ? n : null;
|
|
531
|
+
};
|
|
532
|
+
return {
|
|
533
|
+
id: id(f.id),
|
|
534
|
+
from: id(f.from),
|
|
535
|
+
to: Array.isArray(f.to) && f.to.every((x) => typeof x === "string") ? f.to.filter((x) => UUID.test(x)).map((x) => x.toUpperCase()) : [],
|
|
536
|
+
every: finite(f.every),
|
|
537
|
+
speed: finite(f.speed),
|
|
538
|
+
size: finite(f.size),
|
|
539
|
+
color: isObj(f.color) && ["r", "g", "b", "a"].every((k) => typeof f.color[k] === "number") ? rgba(f.color) ?? null : null,
|
|
540
|
+
when: str(f.when) ?? null,
|
|
541
|
+
spread: f.spread === true ? true : null,
|
|
542
|
+
volume: finite(f.volume),
|
|
543
|
+
overrides: Array.isArray(f.overrides) && f.overrides.length > 0 ? f.overrides.filter(isObj).map((o) => {
|
|
544
|
+
this.fields(o, "flowOverride");
|
|
545
|
+
return { when: str(o.when) ?? "", volume: finite(o.volume) };
|
|
546
|
+
}) : null
|
|
460
547
|
};
|
|
461
548
|
}
|
|
462
549
|
};
|
|
@@ -599,7 +686,12 @@ function compile(source, runtime, options = {}) {
|
|
|
599
686
|
if (b64) (fonts[family] ?? (fonts[family] = {}))[face] = b64;
|
|
600
687
|
}
|
|
601
688
|
}
|
|
602
|
-
|
|
689
|
+
const fill = {
|
|
690
|
+
DOTTIE_DATA: () => scriptJSON(data),
|
|
691
|
+
DOTTIE_OPTIONS: () => scriptJSON(playerAttributes(options)),
|
|
692
|
+
DOTTIE_FONTS: () => scriptJSON(fonts)
|
|
693
|
+
};
|
|
694
|
+
return runtime.trimEnd() + "\n" + LOADER.replace(/\bDOTTIE_(?:DATA|OPTIONS|FONTS)\b/g, (m) => fill[m]());
|
|
603
695
|
}
|
|
604
696
|
export {
|
|
605
697
|
LOADER,
|
package/dist/dottie-compile.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/*! dottie.js 0.
|
|
2
|
+
/*! dottie.js 0.9.0 | Apache-2.0 | https://github.com/phin-tech/dottie */
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
5
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -64,7 +64,9 @@ var KINDS = ["rectangle", "ellipse", "diamond", "text", "connector", "freehand",
|
|
|
64
64
|
var EASES = ["linear", "easeIn", "easeOut", "easeInOut", "hold", "spring", "bounce", "elastic"];
|
|
65
65
|
var KNOWN_FIELDS = {
|
|
66
66
|
file: ["version", "pages", "images"],
|
|
67
|
-
page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables"],
|
|
67
|
+
page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
|
|
68
|
+
flow: ["id", "from", "to", "every", "speed", "color", "size", "when", "spread", "volume", "overrides"],
|
|
69
|
+
flowOverride: ["when", "volume"],
|
|
68
70
|
symbol: ["id", "name", "width", "height", "layers", "elements", "timeline", "button", "params"],
|
|
69
71
|
layer: ["id", "name", "visible", "locked"],
|
|
70
72
|
rgba: ["r", "g", "b", "a"],
|
|
@@ -93,6 +95,7 @@ var KNOWN_FIELDS = {
|
|
|
93
95
|
"click",
|
|
94
96
|
"hover",
|
|
95
97
|
"when",
|
|
98
|
+
"overrides",
|
|
96
99
|
"symbol",
|
|
97
100
|
"playback",
|
|
98
101
|
"offset",
|
|
@@ -101,8 +104,13 @@ var KNOWN_FIELDS = {
|
|
|
101
104
|
"reveal",
|
|
102
105
|
"ports",
|
|
103
106
|
"labelRect",
|
|
104
|
-
"extension"
|
|
107
|
+
"extension",
|
|
108
|
+
"capacity",
|
|
109
|
+
"delay",
|
|
110
|
+
"queue",
|
|
111
|
+
"gauge"
|
|
105
112
|
],
|
|
113
|
+
gauge: ["metric", "of", "max", "warn", "alarm", "style", "label"],
|
|
106
114
|
strokePoint: ["x", "y"],
|
|
107
115
|
subpath: ["closed", "coords"],
|
|
108
116
|
inlineImage: ["data", "format"],
|
|
@@ -110,7 +118,7 @@ var KNOWN_FIELDS = {
|
|
|
110
118
|
extensionRef: ["id", "shape", "version", "params"],
|
|
111
119
|
normalizedPoint: ["x", "y"],
|
|
112
120
|
normalizedRect: ["x", "y", "width", "height"],
|
|
113
|
-
connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops"],
|
|
121
|
+
connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops", "cost"],
|
|
114
122
|
waypoint: ["x", "y"],
|
|
115
123
|
timeline: ["fps", "duration", "boil", "settle", "poster", "tracks", "camera", "markers"],
|
|
116
124
|
track: ["element", "keys", "boil", "follow", "repeats", "march"],
|
|
@@ -119,8 +127,9 @@ var KNOWN_FIELDS = {
|
|
|
119
127
|
repeat: ["start", "end", "count"],
|
|
120
128
|
cameraKey: ["t", "x", "y", "width", "height", "ease"],
|
|
121
129
|
marker: ["t", "name", "loop"],
|
|
122
|
-
click: ["scene", "url", "set", "toggle"],
|
|
123
|
-
hover: ["stroke", "fill", "opacity"]
|
|
130
|
+
click: ["scene", "url", "set", "toggle", "reset"],
|
|
131
|
+
hover: ["stroke", "fill", "opacity"],
|
|
132
|
+
override: ["when", "stroke", "fill", "textColor", "opacity", "strokeWidth", "dash", "text", "reroute", "offline", "cost", "capacity", "delay"]
|
|
124
133
|
};
|
|
125
134
|
var MAX_DURATION = 3600;
|
|
126
135
|
var MAX_MARCH = 1e4;
|
|
@@ -134,6 +143,8 @@ var num = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
|
134
143
|
var str = (v) => typeof v === "string" ? v : void 0;
|
|
135
144
|
var strings = (v) => isObj(v) && Object.values(v).every((x) => typeof x === "string") ? { ...v } : null;
|
|
136
145
|
var bool = (v) => typeof v === "boolean" ? v : void 0;
|
|
146
|
+
var NO_ID = "00000000-0000-0000-0000-000000000000";
|
|
147
|
+
var UUID = /^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/;
|
|
137
148
|
var uuid = (v) => typeof v === "string" ? v.toUpperCase() : void 0;
|
|
138
149
|
function clampTime(t) {
|
|
139
150
|
if (!Number.isFinite(t)) return t === Infinity ? MAX_DURATION : 0;
|
|
@@ -222,7 +233,8 @@ var Reader = class {
|
|
|
222
233
|
this.fields(w, "waypoint");
|
|
223
234
|
return { x: num(w.x) ?? 0, y: num(w.y) ?? 0 };
|
|
224
235
|
}) : null,
|
|
225
|
-
hops: typeof v.hops === "boolean" ? v.hops : null
|
|
236
|
+
hops: typeof v.hops === "boolean" ? v.hops : null,
|
|
237
|
+
cost: typeof v.cost === "number" && Number.isFinite(v.cost) ? v.cost : null
|
|
226
238
|
};
|
|
227
239
|
}
|
|
228
240
|
image(v, table) {
|
|
@@ -274,6 +286,7 @@ var Reader = class {
|
|
|
274
286
|
click: this.click(v.click),
|
|
275
287
|
hover: this.hover(v.hover),
|
|
276
288
|
when: str(v.when) ?? null,
|
|
289
|
+
overrides: this.overrides(v.overrides),
|
|
277
290
|
symbol: uuid(v.symbol) ?? null,
|
|
278
291
|
playback: this.playback(v.playback),
|
|
279
292
|
offset: num(v.offset) ?? null,
|
|
@@ -285,7 +298,26 @@ var Reader = class {
|
|
|
285
298
|
return { x: num(o.x) ?? 0, y: num(o.y) ?? 0 };
|
|
286
299
|
}) : null,
|
|
287
300
|
labelRect: this.labelRect(v.labelRect),
|
|
288
|
-
extension: this.extension(v.extension)
|
|
301
|
+
extension: this.extension(v.extension),
|
|
302
|
+
capacity: num(v.capacity) ?? null,
|
|
303
|
+
delay: num(v.delay) ?? null,
|
|
304
|
+
queue: v.queue === true ? true : null,
|
|
305
|
+
gauge: this.gauge(v.gauge)
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
gauge(v) {
|
|
309
|
+
if (!isObj(v)) return null;
|
|
310
|
+
this.fields(v, "gauge");
|
|
311
|
+
const finite = (x) => typeof x === "number" && Number.isFinite(x) ? x : null;
|
|
312
|
+
const style = str(v.style);
|
|
313
|
+
return {
|
|
314
|
+
metric: str(v.metric) ?? "",
|
|
315
|
+
of: typeof v.of === "string" && UUID.test(v.of) ? v.of.toUpperCase() : NO_ID,
|
|
316
|
+
max: finite(v.max),
|
|
317
|
+
warn: finite(v.warn),
|
|
318
|
+
alarm: finite(v.alarm),
|
|
319
|
+
style: style === "number" || style === "bar" || style === "dial" ? style : null,
|
|
320
|
+
label: str(v.label) ?? null
|
|
289
321
|
};
|
|
290
322
|
}
|
|
291
323
|
labelRect(v) {
|
|
@@ -329,7 +361,7 @@ var Reader = class {
|
|
|
329
361
|
}
|
|
330
362
|
const raw = typeof v.toggle === "string" ? [v.toggle] : Array.isArray(v.toggle) && v.toggle.every((x) => typeof x === "string") ? v.toggle : null;
|
|
331
363
|
const toggle = raw ? raw.filter(isName) : null;
|
|
332
|
-
return { scene: str(v.scene) ?? null, url: safe, set, toggle: toggle && toggle.length > 0 ? toggle : null };
|
|
364
|
+
return { scene: str(v.scene) ?? null, url: safe, set, toggle: toggle && toggle.length > 0 ? toggle : null, reset: v.reset === true ? true : null };
|
|
333
365
|
}
|
|
334
366
|
playback(v) {
|
|
335
367
|
const s = str(v);
|
|
@@ -365,6 +397,35 @@ var Reader = class {
|
|
|
365
397
|
params: strings(v.params)
|
|
366
398
|
};
|
|
367
399
|
}
|
|
400
|
+
/** As DottieKit reads them: a reroute whose targets aren't all ids is dropped, as are keys that aren't ids. */
|
|
401
|
+
overrides(v) {
|
|
402
|
+
if (!Array.isArray(v)) return null;
|
|
403
|
+
return v.filter(isObj).map((o) => {
|
|
404
|
+
this.fields(o, "override");
|
|
405
|
+
const dash = str(o.dash);
|
|
406
|
+
let reroute = null;
|
|
407
|
+
if (isObj(o.reroute) && Object.values(o.reroute).every((x) => typeof x === "string" && UUID.test(x))) {
|
|
408
|
+
reroute = {};
|
|
409
|
+
for (const [k, x] of Object.entries(o.reroute)) if (UUID.test(k)) reroute[k.toUpperCase()] = x.toUpperCase();
|
|
410
|
+
if (Object.keys(reroute).length === 0) reroute = null;
|
|
411
|
+
}
|
|
412
|
+
return {
|
|
413
|
+
when: str(o.when) ?? "",
|
|
414
|
+
stroke: rgba(o.stroke) ?? null,
|
|
415
|
+
fill: rgba(o.fill) ?? null,
|
|
416
|
+
textColor: rgba(o.textColor) ?? null,
|
|
417
|
+
opacity: num(o.opacity) ?? null,
|
|
418
|
+
strokeWidth: num(o.strokeWidth) ?? null,
|
|
419
|
+
dash: dash !== void 0 && ["solid", "dashed", "dotted"].includes(dash) ? dash : null,
|
|
420
|
+
text: str(o.text) ?? null,
|
|
421
|
+
reroute,
|
|
422
|
+
offline: o.offline === true ? true : null,
|
|
423
|
+
cost: typeof o.cost === "number" && Number.isFinite(o.cost) ? o.cost : null,
|
|
424
|
+
capacity: typeof o.capacity === "number" && Number.isFinite(o.capacity) ? o.capacity : null,
|
|
425
|
+
delay: typeof o.delay === "number" && Number.isFinite(o.delay) ? o.delay : null
|
|
426
|
+
};
|
|
427
|
+
});
|
|
428
|
+
}
|
|
368
429
|
hover(v) {
|
|
369
430
|
if (!isObj(v)) return null;
|
|
370
431
|
this.fields(v, "hover");
|
|
@@ -464,7 +525,33 @@ var Reader = class {
|
|
|
464
525
|
theme: str(v.theme) ?? null,
|
|
465
526
|
timeline: this.timeline(v.timeline),
|
|
466
527
|
symbols: Array.isArray(v.symbols) ? v.symbols.map((x) => this.symbol(x, images)).filter((x) => x !== null) : null,
|
|
467
|
-
variables: this.variables(v.variables)
|
|
528
|
+
variables: this.variables(v.variables),
|
|
529
|
+
flows: Array.isArray(v.flows) ? v.flows.filter(isObj).map((f) => this.flow(f)) : null
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
/** As DottieKit reads one: a missing or bad id, source or destination sends nothing; bad destinations are dropped. */
|
|
533
|
+
flow(f) {
|
|
534
|
+
this.fields(f, "flow");
|
|
535
|
+
const id = (x) => typeof x === "string" && UUID.test(x) ? x.toUpperCase() : NO_ID;
|
|
536
|
+
const finite = (x) => {
|
|
537
|
+
const n = num(x);
|
|
538
|
+
return n !== void 0 && Number.isFinite(n) ? n : null;
|
|
539
|
+
};
|
|
540
|
+
return {
|
|
541
|
+
id: id(f.id),
|
|
542
|
+
from: id(f.from),
|
|
543
|
+
to: Array.isArray(f.to) && f.to.every((x) => typeof x === "string") ? f.to.filter((x) => UUID.test(x)).map((x) => x.toUpperCase()) : [],
|
|
544
|
+
every: finite(f.every),
|
|
545
|
+
speed: finite(f.speed),
|
|
546
|
+
size: finite(f.size),
|
|
547
|
+
color: isObj(f.color) && ["r", "g", "b", "a"].every((k) => typeof f.color[k] === "number") ? rgba(f.color) ?? null : null,
|
|
548
|
+
when: str(f.when) ?? null,
|
|
549
|
+
spread: f.spread === true ? true : null,
|
|
550
|
+
volume: finite(f.volume),
|
|
551
|
+
overrides: Array.isArray(f.overrides) && f.overrides.length > 0 ? f.overrides.filter(isObj).map((o) => {
|
|
552
|
+
this.fields(o, "flowOverride");
|
|
553
|
+
return { when: str(o.when) ?? "", volume: finite(o.volume) };
|
|
554
|
+
}) : null
|
|
468
555
|
};
|
|
469
556
|
}
|
|
470
557
|
};
|
|
@@ -607,11 +694,16 @@ function compile(source2, runtime, options2 = {}) {
|
|
|
607
694
|
if (b64) (fonts[family] ?? (fonts[family] = {}))[face] = b64;
|
|
608
695
|
}
|
|
609
696
|
}
|
|
610
|
-
|
|
697
|
+
const fill = {
|
|
698
|
+
DOTTIE_DATA: () => scriptJSON(data),
|
|
699
|
+
DOTTIE_OPTIONS: () => scriptJSON(playerAttributes(options2)),
|
|
700
|
+
DOTTIE_FONTS: () => scriptJSON(fonts)
|
|
701
|
+
};
|
|
702
|
+
return runtime.trimEnd() + "\n" + LOADER.replace(/\bDOTTIE_(?:DATA|OPTIONS|FONTS)\b/g, (m) => fill[m]());
|
|
611
703
|
}
|
|
612
704
|
|
|
613
705
|
// src/index.ts
|
|
614
|
-
var VERSION = "0.
|
|
706
|
+
var VERSION = "0.9.0";
|
|
615
707
|
|
|
616
708
|
// src/cli.ts
|
|
617
709
|
var usage = `dottie-compile ${VERSION}: a Dottie drawing as one script that plays it on any page.
|