@phin-tech/dottie 0.3.0 → 0.5.1
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 +6 -2
- package/README.md +9 -2
- package/dist/compile.js +99 -5
- package/dist/dottie-compile.mjs +100 -6
- package/dist/dottie-player.js +1167 -653
- package/dist/dottie-player.min.js +61 -41
- package/dist/dottie.js +1166 -653
- package/dist/types/clicks.d.ts +30 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/model.d.ts +35 -1
- package/dist/types/player.d.ts +35 -0
- package/dist/types/symbols.d.ts +20 -0
- package/dist/types/timeline.d.ts +4 -1
- package/package.json +1 -1
package/PARITY.md
CHANGED
|
@@ -38,6 +38,10 @@ fixture, so the gap is visible rather than silent.
|
|
|
38
38
|
| Damaged timelines (clamped, filtered, sorted) | Supported | [edge/timeline](../fixtures/edge/timeline.dottie) | Read the way DottieKit's decoders read them |
|
|
39
39
|
| 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 |
|
|
40
40
|
| Text fonts | Partial | | Positions use Helvetica Neue's metrics; browsers without Helvetica Neue draw Helvetica or Arial in the same places, so runs of mixed styles may sit slightly apart |
|
|
41
|
-
|
|
|
42
|
-
|
|
|
41
|
+
| 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)) |
|
|
42
|
+
| Button symbols (up, over, down, hit) and clickable copies | Supported | [edge/buttons](../fixtures/edge/buttons.dottie) | As the HTML export draws them |
|
|
43
|
+
| Copies that play when clicked | Supported | [edge/buttons](../fixtures/edge/buttons.dottie) | `<dottie-player>` only: the HTML export is drawn ahead of time and shows them at rest |
|
|
44
|
+
| Clicks: play a scene, open a link, hover looks, keyboard | Supported | [edge/clicks](../fixtures/edge/clicks.dottie) | As the HTML export does; only http, https and mailto links are followed |
|
|
45
|
+
| 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 |
|
|
46
|
+
| Editing | Missing | | |
|
|
43
47
|
| Ticking task boxes in notes | Missing | | Drawn, not clickable |
|
package/README.md
CHANGED
|
@@ -29,8 +29,15 @@ prefer reduced motion. A still page is just the drawing.
|
|
|
29
29
|
| `no-controls`, `no-autoplay`, `no-loop` | |
|
|
30
30
|
| `label` | The accessible name; the page name by default |
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
Elements the drawing makes clickable work with the mouse and the keyboard (Tab, then Enter or Space). A click plays
|
|
33
|
+
a named scene on to the next one, opens a link in a new tab (only `http`, `https` and `mailto`), or shows the page a
|
|
34
|
+
shape's link points at. Each shows its hover look under the pointer; button symbols show their over and down looks
|
|
35
|
+
and take clicks on their hit area, and a symbol's copy set to play when clicked plays its animation through. Every
|
|
36
|
+
click first fires a cancelable `action` event whose `detail` is `{element, scene | url | page, replay?}`; call
|
|
37
|
+
`preventDefault()` to handle it yourself.
|
|
38
|
+
|
|
39
|
+
The element has `play()`, `pause()`, `nextScene()`, `prevScene()`, `activate(elementId)`, `currentTime`
|
|
40
|
+
(settable), `duration`, `paused`, and fires `load`, `frame`, `action` and `error` events. Its page color comes from the drawing's theme; set
|
|
34
41
|
`--dottie-radius` to round it, and style its parts with `::part(stage)` and `::part(controls)`.
|
|
35
42
|
|
|
36
43
|
Without modules, `dist/dottie-player.min.js` is a classic script that registers the element and sets
|
package/dist/compile.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
/*! dottie.js 0.
|
|
1
|
+
/*! dottie.js 0.5.1 | 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);
|
|
5
5
|
|
|
6
6
|
// src/model.ts
|
|
7
7
|
var SUPPORTED_VERSION = 2;
|
|
8
|
-
var KINDS = ["rectangle", "ellipse", "diamond", "text", "connector", "freehand", "path", "note", "image"];
|
|
8
|
+
var KINDS = ["rectangle", "ellipse", "diamond", "text", "connector", "freehand", "path", "note", "image", "symbol"];
|
|
9
9
|
var EASES = ["linear", "easeIn", "easeOut", "easeInOut", "hold", "spring", "bounce", "elastic"];
|
|
10
10
|
var KNOWN_FIELDS = {
|
|
11
11
|
file: ["version", "pages", "images"],
|
|
12
|
-
page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline"],
|
|
12
|
+
page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols"],
|
|
13
|
+
symbol: ["id", "name", "width", "height", "layers", "elements", "timeline", "button"],
|
|
13
14
|
layer: ["id", "name", "visible", "locked"],
|
|
14
15
|
rgba: ["r", "g", "b", "a"],
|
|
15
16
|
style: ["stroke", "fill", "fillStyle", "strokeWidth", "dash", "roughness", "bowing", "fontSize", "gridSize", "opacity", "dashOffset"],
|
|
@@ -33,6 +34,11 @@ var KNOWN_FIELDS = {
|
|
|
33
34
|
"rotation",
|
|
34
35
|
"link",
|
|
35
36
|
"anchor",
|
|
37
|
+
"click",
|
|
38
|
+
"hover",
|
|
39
|
+
"symbol",
|
|
40
|
+
"playback",
|
|
41
|
+
"offset",
|
|
36
42
|
"image",
|
|
37
43
|
"reveal"
|
|
38
44
|
],
|
|
@@ -47,7 +53,9 @@ var KNOWN_FIELDS = {
|
|
|
47
53
|
follow: ["path", "start", "end", "ease", "reverse", "orient", "laps"],
|
|
48
54
|
repeat: ["start", "end", "count"],
|
|
49
55
|
cameraKey: ["t", "x", "y", "width", "height", "ease"],
|
|
50
|
-
marker: ["t", "name"]
|
|
56
|
+
marker: ["t", "name"],
|
|
57
|
+
click: ["scene", "url"],
|
|
58
|
+
hover: ["stroke", "fill", "opacity"]
|
|
51
59
|
};
|
|
52
60
|
var MAX_DURATION = 3600;
|
|
53
61
|
var MAX_MARCH = 1e4;
|
|
@@ -68,6 +76,11 @@ function clampTime(t) {
|
|
|
68
76
|
function clampFPS(f) {
|
|
69
77
|
return Number.isFinite(f) ? Math.min(Math.max(f, 1), 60) : 12;
|
|
70
78
|
}
|
|
79
|
+
function allowedURL(url) {
|
|
80
|
+
const u = url.trim();
|
|
81
|
+
if (!/^(https?:\/\/|mailto:)/i.test(u) || [...u].length <= 7 || /[\u0000-\u001f\u007f-\u009f]/.test(u)) return null;
|
|
82
|
+
return u;
|
|
83
|
+
}
|
|
71
84
|
function rgba(v) {
|
|
72
85
|
if (!isObj(v)) return void 0;
|
|
73
86
|
const r = num(v.r), g = num(v.g), b = num(v.b);
|
|
@@ -182,10 +195,61 @@ var Reader = class {
|
|
|
182
195
|
rotation: num(v.rotation) ?? null,
|
|
183
196
|
link: uuid(v.link) ?? null,
|
|
184
197
|
anchor: str(v.anchor) ?? null,
|
|
198
|
+
click: this.click(v.click),
|
|
199
|
+
hover: this.hover(v.hover),
|
|
200
|
+
symbol: uuid(v.symbol) ?? null,
|
|
201
|
+
playback: this.playback(v.playback),
|
|
202
|
+
offset: num(v.offset) ?? null,
|
|
185
203
|
image: this.image(v.image, images),
|
|
186
204
|
reveal: num(v.reveal) ?? null
|
|
187
205
|
};
|
|
188
206
|
}
|
|
207
|
+
click(v) {
|
|
208
|
+
if (!isObj(v)) return null;
|
|
209
|
+
this.fields(v, "click");
|
|
210
|
+
const url = str(v.url);
|
|
211
|
+
const safe = url === void 0 ? null : allowedURL(url);
|
|
212
|
+
if (url !== void 0 && safe === null) this.warn("Skipped a click link that isn't http, https or mailto");
|
|
213
|
+
return { scene: str(v.scene) ?? null, url: safe };
|
|
214
|
+
}
|
|
215
|
+
playback(v) {
|
|
216
|
+
const s = str(v);
|
|
217
|
+
if (s === void 0) return null;
|
|
218
|
+
return ["loop", "once", "still", "click"].includes(s) ? s : "loop";
|
|
219
|
+
}
|
|
220
|
+
symbol(v, images) {
|
|
221
|
+
if (!isObj(v)) return null;
|
|
222
|
+
this.fields(v, "symbol");
|
|
223
|
+
const id = uuid(v.id);
|
|
224
|
+
if (!id) {
|
|
225
|
+
this.warn("Skipped a symbol without an id");
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
const size = (x) => {
|
|
229
|
+
const n = num(x);
|
|
230
|
+
return Math.max(1, n ?? 100);
|
|
231
|
+
};
|
|
232
|
+
const layers = (Array.isArray(v.layers) ? v.layers : []).filter(isObj).flatMap((l) => {
|
|
233
|
+
const lid = uuid(l.id);
|
|
234
|
+
return lid ? [{ id: lid, name: str(l.name) ?? "", visible: bool(l.visible) ?? true, locked: bool(l.locked) ?? false }] : [];
|
|
235
|
+
});
|
|
236
|
+
if (layers.length === 0) layers.push({ id: `${id}-LAYER`, name: "Layer 1", visible: true, locked: false });
|
|
237
|
+
return {
|
|
238
|
+
id,
|
|
239
|
+
name: str(v.name) ?? "Symbol",
|
|
240
|
+
width: size(v.width),
|
|
241
|
+
height: size(v.height),
|
|
242
|
+
layers,
|
|
243
|
+
elements: (Array.isArray(v.elements) ? v.elements : []).map((e) => this.element(e, images)).filter((e) => e !== null),
|
|
244
|
+
timeline: this.timeline(v.timeline),
|
|
245
|
+
button: bool(v.button) ?? null
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
hover(v) {
|
|
249
|
+
if (!isObj(v)) return null;
|
|
250
|
+
this.fields(v, "hover");
|
|
251
|
+
return { stroke: rgba(v.stroke) ?? null, fill: rgba(v.fill) ?? null, opacity: num(v.opacity) ?? null };
|
|
252
|
+
}
|
|
189
253
|
ease(v) {
|
|
190
254
|
const s = str(v);
|
|
191
255
|
if (s === void 0) return null;
|
|
@@ -278,7 +342,8 @@ var Reader = class {
|
|
|
278
342
|
layers,
|
|
279
343
|
elements: (Array.isArray(v.elements) ? v.elements : []).map((e) => this.element(e, images)).filter((e) => e !== null),
|
|
280
344
|
theme: str(v.theme) ?? null,
|
|
281
|
-
timeline: this.timeline(v.timeline)
|
|
345
|
+
timeline: this.timeline(v.timeline),
|
|
346
|
+
symbols: Array.isArray(v.symbols) ? v.symbols.map((x) => this.symbol(x, images)).filter((x) => x !== null) : null
|
|
282
347
|
};
|
|
283
348
|
}
|
|
284
349
|
};
|
|
@@ -318,6 +383,19 @@ function parseDottie(source) {
|
|
|
318
383
|
return { version, pages, warnings: reader.warnings };
|
|
319
384
|
}
|
|
320
385
|
|
|
386
|
+
// src/clicks.ts
|
|
387
|
+
var CLICK_STYLE = `
|
|
388
|
+
.dottie-a { cursor: pointer; outline: none; }
|
|
389
|
+
.dottie-a .dottie-h { display: none; }
|
|
390
|
+
.dottie-a:hover .dottie-h, .dottie-a.dottie-hover .dottie-h, .dottie-a:focus-visible .dottie-h { display: inline; }
|
|
391
|
+
.dottie-a:hover .dottie-n, .dottie-a.dottie-hover .dottie-n, .dottie-a:focus-visible .dottie-n { display: none; }
|
|
392
|
+
.dottie-a:focus-visible { filter: drop-shadow(0 0 3px var(--dottie-focus, #3b82f6)); }
|
|
393
|
+
.dottie-a:not(.dottie-b):active, .dottie-a.dottie-press:not(.dottie-b) { transform: translate(1px, 1px); }
|
|
394
|
+
.dottie-a .dottie-d { display: none; }
|
|
395
|
+
.dottie-b:active .dottie-n, .dottie-b:active .dottie-h, .dottie-b.dottie-press .dottie-n, .dottie-b.dottie-press .dottie-h { display: none; }
|
|
396
|
+
.dottie-b:active .dottie-d, .dottie-b.dottie-press .dottie-d { display: inline; }
|
|
397
|
+
`;
|
|
398
|
+
|
|
321
399
|
// src/player.ts
|
|
322
400
|
function pageIndex(file, spec) {
|
|
323
401
|
const s = (spec ?? "").trim();
|
|
@@ -327,6 +405,22 @@ function pageIndex(file, spec) {
|
|
|
327
405
|
const n = Number(s);
|
|
328
406
|
return Number.isInteger(n) && n >= 1 && n <= file.pages.length ? n - 1 : 0;
|
|
329
407
|
}
|
|
408
|
+
var STYLE = `
|
|
409
|
+
:host { display: block; position: relative; color: var(--dottie-ink); background: var(--dottie-page);
|
|
410
|
+
font: 14px -apple-system, system-ui, sans-serif; border-radius: var(--dottie-radius, 0); }
|
|
411
|
+
:host([hidden]) { display: none; }
|
|
412
|
+
.stage { display: block; width: 100%; height: auto; }
|
|
413
|
+
.stage svg { display: block; width: 100%; height: auto; margin: 0 auto; }
|
|
414
|
+
.bar { display: flex; align-items: center; gap: 12px; padding: 8px 12px 12px; max-width: 560px; margin: 0 auto; box-sizing: border-box; }
|
|
415
|
+
.bar[hidden] { display: none; }
|
|
416
|
+
button { font: inherit; color: inherit; background: none; border: 1.5px solid currentColor; border-radius: 6px;
|
|
417
|
+
width: 34px; height: 30px; cursor: pointer; flex: none; padding: 0; }
|
|
418
|
+
button:focus-visible, input:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
|
|
419
|
+
input[type=range] { flex: 1; min-width: 60px; accent-color: currentColor; }
|
|
420
|
+
output { font-variant-numeric: tabular-nums; min-width: 4.5em; text-align: right; }
|
|
421
|
+
.scene { min-width: 0; flex: 0 1 auto; text-align: center; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
422
|
+
.error { padding: 16px; font-family: ui-monospace, Menlo, monospace; white-space: pre-wrap; }
|
|
423
|
+
${CLICK_STYLE}`;
|
|
330
424
|
|
|
331
425
|
// src/compile.ts
|
|
332
426
|
var LOADER = `;(function () {
|
package/dist/dottie-compile.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/*! dottie.js 0.
|
|
2
|
+
/*! dottie.js 0.5.1 | 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);
|
|
@@ -10,11 +10,12 @@ import { basename } from "node:path";
|
|
|
10
10
|
|
|
11
11
|
// src/model.ts
|
|
12
12
|
var SUPPORTED_VERSION = 2;
|
|
13
|
-
var KINDS = ["rectangle", "ellipse", "diamond", "text", "connector", "freehand", "path", "note", "image"];
|
|
13
|
+
var KINDS = ["rectangle", "ellipse", "diamond", "text", "connector", "freehand", "path", "note", "image", "symbol"];
|
|
14
14
|
var EASES = ["linear", "easeIn", "easeOut", "easeInOut", "hold", "spring", "bounce", "elastic"];
|
|
15
15
|
var KNOWN_FIELDS = {
|
|
16
16
|
file: ["version", "pages", "images"],
|
|
17
|
-
page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline"],
|
|
17
|
+
page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols"],
|
|
18
|
+
symbol: ["id", "name", "width", "height", "layers", "elements", "timeline", "button"],
|
|
18
19
|
layer: ["id", "name", "visible", "locked"],
|
|
19
20
|
rgba: ["r", "g", "b", "a"],
|
|
20
21
|
style: ["stroke", "fill", "fillStyle", "strokeWidth", "dash", "roughness", "bowing", "fontSize", "gridSize", "opacity", "dashOffset"],
|
|
@@ -38,6 +39,11 @@ var KNOWN_FIELDS = {
|
|
|
38
39
|
"rotation",
|
|
39
40
|
"link",
|
|
40
41
|
"anchor",
|
|
42
|
+
"click",
|
|
43
|
+
"hover",
|
|
44
|
+
"symbol",
|
|
45
|
+
"playback",
|
|
46
|
+
"offset",
|
|
41
47
|
"image",
|
|
42
48
|
"reveal"
|
|
43
49
|
],
|
|
@@ -52,7 +58,9 @@ var KNOWN_FIELDS = {
|
|
|
52
58
|
follow: ["path", "start", "end", "ease", "reverse", "orient", "laps"],
|
|
53
59
|
repeat: ["start", "end", "count"],
|
|
54
60
|
cameraKey: ["t", "x", "y", "width", "height", "ease"],
|
|
55
|
-
marker: ["t", "name"]
|
|
61
|
+
marker: ["t", "name"],
|
|
62
|
+
click: ["scene", "url"],
|
|
63
|
+
hover: ["stroke", "fill", "opacity"]
|
|
56
64
|
};
|
|
57
65
|
var MAX_DURATION = 3600;
|
|
58
66
|
var MAX_MARCH = 1e4;
|
|
@@ -73,6 +81,11 @@ function clampTime(t) {
|
|
|
73
81
|
function clampFPS(f) {
|
|
74
82
|
return Number.isFinite(f) ? Math.min(Math.max(f, 1), 60) : 12;
|
|
75
83
|
}
|
|
84
|
+
function allowedURL(url) {
|
|
85
|
+
const u = url.trim();
|
|
86
|
+
if (!/^(https?:\/\/|mailto:)/i.test(u) || [...u].length <= 7 || /[\u0000-\u001f\u007f-\u009f]/.test(u)) return null;
|
|
87
|
+
return u;
|
|
88
|
+
}
|
|
76
89
|
function rgba(v) {
|
|
77
90
|
if (!isObj(v)) return void 0;
|
|
78
91
|
const r = num(v.r), g = num(v.g), b = num(v.b);
|
|
@@ -187,10 +200,61 @@ var Reader = class {
|
|
|
187
200
|
rotation: num(v.rotation) ?? null,
|
|
188
201
|
link: uuid(v.link) ?? null,
|
|
189
202
|
anchor: str(v.anchor) ?? null,
|
|
203
|
+
click: this.click(v.click),
|
|
204
|
+
hover: this.hover(v.hover),
|
|
205
|
+
symbol: uuid(v.symbol) ?? null,
|
|
206
|
+
playback: this.playback(v.playback),
|
|
207
|
+
offset: num(v.offset) ?? null,
|
|
190
208
|
image: this.image(v.image, images),
|
|
191
209
|
reveal: num(v.reveal) ?? null
|
|
192
210
|
};
|
|
193
211
|
}
|
|
212
|
+
click(v) {
|
|
213
|
+
if (!isObj(v)) return null;
|
|
214
|
+
this.fields(v, "click");
|
|
215
|
+
const url = str(v.url);
|
|
216
|
+
const safe = url === void 0 ? null : allowedURL(url);
|
|
217
|
+
if (url !== void 0 && safe === null) this.warn("Skipped a click link that isn't http, https or mailto");
|
|
218
|
+
return { scene: str(v.scene) ?? null, url: safe };
|
|
219
|
+
}
|
|
220
|
+
playback(v) {
|
|
221
|
+
const s = str(v);
|
|
222
|
+
if (s === void 0) return null;
|
|
223
|
+
return ["loop", "once", "still", "click"].includes(s) ? s : "loop";
|
|
224
|
+
}
|
|
225
|
+
symbol(v, images) {
|
|
226
|
+
if (!isObj(v)) return null;
|
|
227
|
+
this.fields(v, "symbol");
|
|
228
|
+
const id = uuid(v.id);
|
|
229
|
+
if (!id) {
|
|
230
|
+
this.warn("Skipped a symbol without an id");
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
const size = (x) => {
|
|
234
|
+
const n = num(x);
|
|
235
|
+
return Math.max(1, n ?? 100);
|
|
236
|
+
};
|
|
237
|
+
const layers = (Array.isArray(v.layers) ? v.layers : []).filter(isObj).flatMap((l) => {
|
|
238
|
+
const lid = uuid(l.id);
|
|
239
|
+
return lid ? [{ id: lid, name: str(l.name) ?? "", visible: bool(l.visible) ?? true, locked: bool(l.locked) ?? false }] : [];
|
|
240
|
+
});
|
|
241
|
+
if (layers.length === 0) layers.push({ id: `${id}-LAYER`, name: "Layer 1", visible: true, locked: false });
|
|
242
|
+
return {
|
|
243
|
+
id,
|
|
244
|
+
name: str(v.name) ?? "Symbol",
|
|
245
|
+
width: size(v.width),
|
|
246
|
+
height: size(v.height),
|
|
247
|
+
layers,
|
|
248
|
+
elements: (Array.isArray(v.elements) ? v.elements : []).map((e) => this.element(e, images)).filter((e) => e !== null),
|
|
249
|
+
timeline: this.timeline(v.timeline),
|
|
250
|
+
button: bool(v.button) ?? null
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
hover(v) {
|
|
254
|
+
if (!isObj(v)) return null;
|
|
255
|
+
this.fields(v, "hover");
|
|
256
|
+
return { stroke: rgba(v.stroke) ?? null, fill: rgba(v.fill) ?? null, opacity: num(v.opacity) ?? null };
|
|
257
|
+
}
|
|
194
258
|
ease(v) {
|
|
195
259
|
const s = str(v);
|
|
196
260
|
if (s === void 0) return null;
|
|
@@ -283,7 +347,8 @@ var Reader = class {
|
|
|
283
347
|
layers,
|
|
284
348
|
elements: (Array.isArray(v.elements) ? v.elements : []).map((e) => this.element(e, images)).filter((e) => e !== null),
|
|
285
349
|
theme: str(v.theme) ?? null,
|
|
286
|
-
timeline: this.timeline(v.timeline)
|
|
350
|
+
timeline: this.timeline(v.timeline),
|
|
351
|
+
symbols: Array.isArray(v.symbols) ? v.symbols.map((x) => this.symbol(x, images)).filter((x) => x !== null) : null
|
|
287
352
|
};
|
|
288
353
|
}
|
|
289
354
|
};
|
|
@@ -323,6 +388,19 @@ function parseDottie(source2) {
|
|
|
323
388
|
return { version, pages, warnings: reader.warnings };
|
|
324
389
|
}
|
|
325
390
|
|
|
391
|
+
// src/clicks.ts
|
|
392
|
+
var CLICK_STYLE = `
|
|
393
|
+
.dottie-a { cursor: pointer; outline: none; }
|
|
394
|
+
.dottie-a .dottie-h { display: none; }
|
|
395
|
+
.dottie-a:hover .dottie-h, .dottie-a.dottie-hover .dottie-h, .dottie-a:focus-visible .dottie-h { display: inline; }
|
|
396
|
+
.dottie-a:hover .dottie-n, .dottie-a.dottie-hover .dottie-n, .dottie-a:focus-visible .dottie-n { display: none; }
|
|
397
|
+
.dottie-a:focus-visible { filter: drop-shadow(0 0 3px var(--dottie-focus, #3b82f6)); }
|
|
398
|
+
.dottie-a:not(.dottie-b):active, .dottie-a.dottie-press:not(.dottie-b) { transform: translate(1px, 1px); }
|
|
399
|
+
.dottie-a .dottie-d { display: none; }
|
|
400
|
+
.dottie-b:active .dottie-n, .dottie-b:active .dottie-h, .dottie-b.dottie-press .dottie-n, .dottie-b.dottie-press .dottie-h { display: none; }
|
|
401
|
+
.dottie-b:active .dottie-d, .dottie-b.dottie-press .dottie-d { display: inline; }
|
|
402
|
+
`;
|
|
403
|
+
|
|
326
404
|
// src/player.ts
|
|
327
405
|
function pageIndex(file, spec) {
|
|
328
406
|
const s = (spec ?? "").trim();
|
|
@@ -332,6 +410,22 @@ function pageIndex(file, spec) {
|
|
|
332
410
|
const n = Number(s);
|
|
333
411
|
return Number.isInteger(n) && n >= 1 && n <= file.pages.length ? n - 1 : 0;
|
|
334
412
|
}
|
|
413
|
+
var STYLE = `
|
|
414
|
+
:host { display: block; position: relative; color: var(--dottie-ink); background: var(--dottie-page);
|
|
415
|
+
font: 14px -apple-system, system-ui, sans-serif; border-radius: var(--dottie-radius, 0); }
|
|
416
|
+
:host([hidden]) { display: none; }
|
|
417
|
+
.stage { display: block; width: 100%; height: auto; }
|
|
418
|
+
.stage svg { display: block; width: 100%; height: auto; margin: 0 auto; }
|
|
419
|
+
.bar { display: flex; align-items: center; gap: 12px; padding: 8px 12px 12px; max-width: 560px; margin: 0 auto; box-sizing: border-box; }
|
|
420
|
+
.bar[hidden] { display: none; }
|
|
421
|
+
button { font: inherit; color: inherit; background: none; border: 1.5px solid currentColor; border-radius: 6px;
|
|
422
|
+
width: 34px; height: 30px; cursor: pointer; flex: none; padding: 0; }
|
|
423
|
+
button:focus-visible, input:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
|
|
424
|
+
input[type=range] { flex: 1; min-width: 60px; accent-color: currentColor; }
|
|
425
|
+
output { font-variant-numeric: tabular-nums; min-width: 4.5em; text-align: right; }
|
|
426
|
+
.scene { min-width: 0; flex: 0 1 auto; text-align: center; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
427
|
+
.error { padding: 16px; font-family: ui-monospace, Menlo, monospace; white-space: pre-wrap; }
|
|
428
|
+
${CLICK_STYLE}`;
|
|
335
429
|
|
|
336
430
|
// src/compile.ts
|
|
337
431
|
var LOADER = `;(function () {
|
|
@@ -393,7 +487,7 @@ function compile(source2, runtime, options2 = {}) {
|
|
|
393
487
|
}
|
|
394
488
|
|
|
395
489
|
// src/index.ts
|
|
396
|
-
var VERSION = "0.
|
|
490
|
+
var VERSION = "0.5.1";
|
|
397
491
|
|
|
398
492
|
// src/cli.ts
|
|
399
493
|
var usage = `dottie-compile ${VERSION}: a Dottie drawing as one script that plays it on any page.
|