volito 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +200 -9
  2. package/dist/browser.d.ts +50 -1
  3. package/dist/browser.js +352 -43
  4. package/dist/chunks/{chunk-CFDFWZAC.js → chunk-CUQY6YI3.js} +1032 -404
  5. package/dist/chunks/chunk-PM3PLI3X.js +71 -0
  6. package/dist/chunks/chunk-QA4SEJCZ.js +601 -0
  7. package/dist/chunks/chunk-ZFG3X3DU.js +67 -0
  8. package/dist/chunks/chunk-ZHMWEZ4C.js +186 -0
  9. package/dist/chunks/init-JX2BYRKT.js +189 -0
  10. package/dist/chunks/review-RBH5EUZN.js +18 -0
  11. package/dist/cli.js +232 -32
  12. package/dist/index.d.ts +314 -2
  13. package/dist/index.js +75 -21
  14. package/dist/mcp.js +129 -22
  15. package/dist/player.d.ts +643 -0
  16. package/dist/player.js +6320 -0
  17. package/dist/registry.json +1 -1
  18. package/examples/player.html +93 -0
  19. package/examples/states.html +73 -0
  20. package/examples/volito-intro/DESIGN.md +23 -0
  21. package/examples/volito-intro/frame.js +187 -0
  22. package/examples/volito-intro/item.json +43 -0
  23. package/package.json +15 -7
  24. package/packs/3d/pack.json +1 -1
  25. package/packs/annotate/emphasis/frame.js +8 -0
  26. package/packs/annotate/pack.json +1 -1
  27. package/packs/annotate/reactions/frame.js +12 -0
  28. package/packs/backdrops/gradient/frame.js +5 -0
  29. package/packs/backdrops/pack.json +1 -1
  30. package/packs/broadcast/pack.json +1 -1
  31. package/packs/data/pack.json +1 -1
  32. package/packs/effects/chromatic/frame.js +17 -0
  33. package/packs/effects/chromatic/item.json +15 -0
  34. package/packs/effects/glass/frame.js +44 -0
  35. package/packs/effects/glass/item.json +16 -0
  36. package/packs/effects/grain/frame.js +20 -0
  37. package/packs/effects/grain/item.json +16 -0
  38. package/packs/effects/light-leak/frame.js +24 -0
  39. package/packs/effects/light-leak/item.json +15 -0
  40. package/packs/effects/neon/frame.js +28 -0
  41. package/packs/effects/neon/item.json +15 -0
  42. package/packs/effects/pack.json +13 -0
  43. package/packs/effects/shared.js +23 -0
  44. package/packs/effects/warp/frame.js +13 -0
  45. package/packs/effects/warp/item.json +15 -0
  46. package/packs/essentials/pack.json +1 -1
  47. package/packs/essentials/wipe/frame.js +13 -0
  48. package/packs/promo/pack.json +1 -1
  49. package/packs/social/pack.json +1 -1
  50. package/packs/transitions/glitch/frame.js +14 -0
  51. package/packs/transitions/pack.json +1 -1
  52. package/packs/transitions/shared.js +12 -0
  53. package/packs/type/pack.json +1 -1
  54. package/packs/type/word-by-word/frame.js +10 -0
  55. package/packs/ui/bell/frame.js +24 -0
  56. package/packs/ui/bell/item.json +21 -0
  57. package/packs/ui/button/frame.js +55 -0
  58. package/packs/ui/button/item.json +26 -0
  59. package/packs/ui/like/frame.js +34 -0
  60. package/packs/ui/like/item.json +21 -0
  61. package/packs/ui/loader/frame.js +34 -0
  62. package/packs/ui/loader/item.json +23 -0
  63. package/packs/ui/pack.json +13 -0
  64. package/packs/ui/shared.js +54 -0
  65. package/packs/ui/toggle/frame.js +30 -0
  66. package/packs/ui/toggle/item.json +22 -0
  67. package/{skill → skills/volito}/SKILL.md +43 -3
  68. package/skills/volito/references/art-direction.md +58 -0
  69. package/skills/volito/references/brand.md +59 -0
  70. package/skills/volito/references/delivery.md +40 -0
  71. package/skills/volito/references/matching-a-reference.md +39 -0
  72. package/skills/volito/references/motion-craft.md +56 -0
  73. package/skills/volito/references/self-review.md +44 -0
  74. package/skills/volito/references/type-and-layout.md +44 -0
  75. package/skills/volito/references/voice-and-timing.md +37 -0
  76. package/skills/volito/references/writing-items.md +44 -0
  77. /package/{skill/template → templates/item}/frame.js +0 -0
  78. /package/{skill/template → templates/item}/item.json +0 -0
package/README.md CHANGED
@@ -1,12 +1,32 @@
1
- # Volito
2
-
3
- **Brand-aware, voice-synced motion graphics as code — for developers and AI agents.**
1
+ <p align="center">
2
+ <a href="https://volito.dev"><img src=".github/assets/banner.jpg" alt="Volito: motion graphics, from one sentence. Motion graphics as code for developers and AI agents, by MONARC PRO." width="100%"></a>
3
+ </p>
4
+
5
+ <h1 align="center">Volito</h1>
6
+
7
+ <p align="center"><strong>Brand-aware, voice-synced motion graphics as code — for developers and AI agents.</strong></p>
8
+
9
+ <p align="center">
10
+ <a href="https://www.npmjs.com/package/volito"><img src="https://img.shields.io/npm/v/volito?color=2433e8&label=npm" alt="npm version"></a>
11
+ <a href="https://github.com/monarcpro/volito/actions/workflows/ci.yml"><img src="https://github.com/monarcpro/volito/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
12
+ <a href="LICENSE"><img src="https://img.shields.io/badge/engine-MIT-dfff4f?labelColor=15140f" alt="Engine licence: MIT"></a>
13
+ <a href="https://volito.dev/docs"><img src="https://img.shields.io/badge/docs-volito.dev-ff6a3d?labelColor=15140f" alt="Docs on volito.dev"></a>
14
+ </p>
15
+
16
+ <p align="center">
17
+ <a href="https://volito.dev">Website</a> ·
18
+ <a href="https://volito.dev/docs">Docs</a> ·
19
+ <a href="https://volito.dev/docs/packs">Packs</a> ·
20
+ <a href="https://volito.dev/docs/agents">For agents</a> ·
21
+ <a href="https://www.npmjs.com/package/volito">npm</a> ·
22
+ <a href="CHANGELOG.md">Changelog</a>
23
+ </p>
4
24
 
5
25
  By [MONARC STUDIOS](https://monarcpro.app), the team behind MONARC PRO. Volito is the motion graphics engine
6
26
  inside the [MONARC PRO](https://monarcpro.app) video editor, opened up; the name is Latin for “to flutter”.
7
27
  Every graphic is a small program — `function frame(t, $)` returns the SVG of one frame — so it is
8
28
  readable, diffable, seekable to any frame, and something an AI agent can write and fix. It ships with
9
- 96 ready-made graphics in ten packs (3D, maps, transitions and kinetic type among them), 36 brand styles,
29
+ 107 ready-made graphics in twelve packs (3D, maps, transitions, kinetic type, interactive UI and filter effects among them), 36 brand styles,
10
30
  sixteen animated patterns, a CLI, a Node API, a browser player and an MCP server, and renders to ProRes 4444 or HEVC with alpha, WebM, MP4, GIF, PNG frames or SVG.
11
31
 
12
32
  - **One design, every brand.** Items draw with colour roles and faces, not fixed colours: pass one of 36
@@ -16,10 +36,18 @@ sixteen animated patterns, a CLI, a Node API, a browser player and an MCP server
16
36
  - **On the voice.** Give a transcript and text lands on the words that say it.
17
37
  - **Drops onto footage.** Overlays render with real alpha for Premiere, Resolve, Final Cut, After
18
38
  Effects and CapCut.
39
+ - **Sounds like it moves.** `--sound` gives any render a sound track Volito synthesises itself — a pop for
40
+ every spring, a whoosh for every move across the frame, ticks for letters, a hit for a slam, a bed in a
41
+ key — and a program can design its own cues beside its frames.
19
42
  - **Agent-native.** An MCP server gives Claude Code, Cursor and other agents tools to find, preview (as an
20
43
  image they can see), check and render graphics — or to write their own.
21
44
  - **Many scripts.** Latin, Latin Extended, Vietnamese, Cyrillic, Greek and Devanagari (Hindi), shaped properly.
22
45
 
46
+ <p align="center">
47
+ <img src=".github/assets/intro.gif" alt="A 10-second Volito intro: kinetic type, the logo dropping in, an extruded 3D wordmark and an end card" width="420"><br>
48
+ <sub>This intro is a Volito program: kinetic type, a 3D wordmark and an end card, rendered in Node.</sub>
49
+ </p>
50
+
23
51
  ```bash
24
52
  npx volito render lower-third \
25
53
  --prop name="Priya Sharma" --prop role="Product designer" \
@@ -39,7 +67,9 @@ stills, contact sheets and PNG frames do not. WebM needs an ffmpeg built with li
39
67
 
40
68
  ## The packs
41
69
 
42
- 96 graphics in ten packs. Every one takes any brand style and any aspect, and every part of it takes any move.
70
+ <img src=".github/assets/packs.jpg" alt="96 graphics in 10 packs: a render from each of Essentials, Broadcast, Social, Data, 3D, Transitions, Annotate, Type, Backdrops and Promo" width="100%">
71
+
72
+ 107 graphics in twelve packs. Every one takes any brand style and any aspect, and every part of it takes any move.
43
73
 
44
74
  | Pack | Items |
45
75
  | --- | --- |
@@ -53,6 +83,8 @@ stills, contact sheets and PNG frames do not. WebM needs an ffmpeg built with li
53
83
  | **Type** (10) | Kinetic type: `typewriter` · `word-swap` (a word that keeps changing) · `split-flap` · `marquee` (tilted scrolling bands) · `echo` · `liquid-fill` · `decode` · `word-by-word` · `key-phrase` (marker on *marked* words) · `stack` (editorial) |
54
84
  | **Backdrops** (9) | Moving grounds: `pattern` (any of the sixteen) · `aurora` · `tiles` (Bauhaus field) · `retro-grid` (synthwave) · `blobs` (lava goo) · `gradient` · `starfield` · `bokeh` · `topo` |
55
85
  | **Promo** (8) | `sale-badge` (starburst) · `price-card` (counts down, strike, click) · `coupon` (copy the code) · `offer-countdown` (D:H:M:S) · `features` (checklist) · `cta` (button and cursor) · `launch` · `ribbon` (crossing tapes) |
86
+ | **UI** (5) | Interactive states (see *Interactive states*): `button` (idle, hover, press, loading, done) · `toggle` · `like` (rolling count) · `loader` (success or failure) · `bell` (badge, read) |
87
+ | **Effects** (6) | SVG filters, no GPU: `grain` (film grain, re-rolled every film frame) · `light-leak` · `glass` (frosted card over drifting colour) · `chromatic` (channels split and snap) · `warp` (liquid ripple settling) · `neon` (flickers on) |
56
88
 
57
89
  `volito info <item>` lists every prop. To see them all live, serve this package's folder and
58
90
  open `examples/gallery.html`.
@@ -103,6 +135,50 @@ Maps use Natural Earth's countries (177, packed into 30 KB): `worldMap($, { cent
103
135
  flat (Equal Earth), `worldGlobe(S, …)` puts them on a 3D globe, and `worldFind("UK")` finds one by name,
104
136
  short name or ISO number. `volito api` documents both.
105
137
 
138
+ ## Sound design
139
+
140
+ Every render can carry sound, and Volito makes it the way it makes pictures: from code, from nothing. No
141
+ sample library, no files to find. `--sound` reads the graphic's own motion — every part's move leaves a
142
+ mark — and gives each its sound: a spring pops, a move across the frame whooshes (louder the further it
143
+ travels), letters tick, a typewriter types, a slam hits, a glitch zaps, a burst sparkles. `--bed Dm` lays
144
+ a pad under it in a key, and it steps back under every hit on its own.
145
+
146
+ ```bash
147
+ volito render logo-sting --prop wordmark=VOLITO --sound --bed Dm --format mp4 --out sting.mp4
148
+ volito sound lower-third --prop name="Priya Sharma" --out priya.wav # the track alone, with its cue list
149
+ ```
150
+
151
+ A program designs its own sound beside its frames — `function sound($)` runs once with the same `$`
152
+ (`$.dur`, `$.beat`, `$.at(word)`, `$.data`), so cues land on the same beats the picture uses:
153
+
154
+ ```js
155
+ function sound($) {
156
+ return {
157
+ cues: [
158
+ { at: 0.2, kind: "riser", dur: 1.1 },
159
+ { at: $.beat("in", 1.3), kind: "hit", level: 1.1 },
160
+ { at: 1.5, kind: "shimmer", dur: 1.2, pan: 0.3 },
161
+ { at: -0.6, kind: "ding", note: "A5", level: 0.6 }, // negative counts from the end
162
+ ],
163
+ bed: { key: "D", mode: "minor", from: 0.8, to: -0.4, level: 0.5 },
164
+ auto: false, // true adds the motion's own cues on top
165
+ };
166
+ }
167
+ ```
168
+
169
+ | Kind | |
170
+ | --- | --- |
171
+ | `whoosh` `swell` `riser` `fall` | air past, soft air rising, a climb into a moment, the fall after it |
172
+ | `hit` `stamp` `sub` `pop` | an impact, a heavy slam, a low drop, a bubble pop |
173
+ | `tick` `click` `type` `scratch` | one letter or step, a UI click, keys for a while, pencil on paper |
174
+ | `shimmer` `ding` `zap` | sparkle, a bell (`note: "A5"`), a glitch |
175
+ | `tone` `chord` | a note, the bed's chord — for a sting that resolves |
176
+
177
+ Each cue takes `at`, `dur`, `level` (0–2), `pitch` (semitones), `pan` (-1…1) and `seed`. The track is
178
+ stereo 48 kHz, limited, with a room; `--sound-out track.wav` writes it alone for an editor's timeline
179
+ beside a ProRes overlay. MP4 and HEVC carry AAC, ProRes carries PCM, WebM carries Opus; PNG and GIF carry
180
+ none. `volito api` prints the whole sound reference.
181
+
106
182
  ## CLI
107
183
 
108
184
  ```bash
@@ -117,6 +193,49 @@ volito render banner --prop headline="Doors open at 9" --format webm --out banne
117
193
  volito check ./my-graphic.js # run it at every aspect, report problems
118
194
  ```
119
195
 
196
+ ### Graphic specs
197
+
198
+ Any set of options can be saved as a spec: one JSON file for one graphic that every command takes in place
199
+ of an item. Keep it in your repo, review it, hand it to an agent; options on the command line win over it.
200
+
201
+ ```bash
202
+ volito spec lower-third --prop name="Priya Sharma" --style ember --aspect 9:16 --out priya.volito.json
203
+ volito validate priya.volito.json # its props, parts, files and aspect against the item
204
+ volito render priya.volito.json --prop role="Founder"
205
+ volito schema # the JSON Schema (also at https://volito.dev/schema/graphic.v1.json)
206
+ ```
207
+
208
+ ```json
209
+ {
210
+ "$schema": "https://volito.dev/schema/graphic.v1.json",
211
+ "volito": 1,
212
+ "item": "essentials/lower-third",
213
+ "props": { "name": "Priya Sharma", "role": "Product designer" },
214
+ "style": "./DESIGN.md",
215
+ "aspect": "9:16",
216
+ "motion": { "name": { "in": "typewriter" } },
217
+ "mood": "elegant",
218
+ "seed": 4,
219
+ "sound": { "bed": "Dm" },
220
+ "render": { "format": "mov", "out": "renders/priya.mov" }
221
+ }
222
+ ```
223
+
224
+ Paths inside a spec (a DESIGN.md, a `program`, a transcript, image props) are relative to the spec file.
225
+ `program` points at your own `frame(t, $)` file, or `code` holds it inline. `volito bundle priya.volito.json`
226
+ packs the spec and those files into one `priya.volito` that every command takes, anywhere.
227
+
228
+ ### Review before you render
229
+
230
+ ```bash
231
+ volito review lower-third --prop name="Priya Sharma" --aspect 9:16
232
+ ```
233
+
234
+ The check at each aspect, then what the frames show: when the graphic settles, how long it holds still and
235
+ when it leaves (with a warning when the entrance is slow or the hold too short for its words), how much of
236
+ an overlay sits under Reels', Shorts' and TikTok's interface at 9:16, and a contact sheet per aspect in
237
+ `volito-review/<item>/` with a `review.md`.
238
+
120
239
  | Option | |
121
240
  | --- | --- |
122
241
  | `--prop name=value` | a prop (repeat). Lists: `"a; b; c"`. Chart rows: `"Label: 42; Other: 17"` |
@@ -130,6 +249,7 @@ volito check ./my-graphic.js # run it at every aspect, report p
130
249
  | `--motion part.setting=value` | how a part moves (repeat; `*` for every part) — see *Motion without limits* |
131
250
  | `--mood m` · `--seed n` · `--speed x` | a choreography, a new take per seed, faster or slower |
132
251
  | `--beat in=0.4 --beat out=-0.6` | move the entrance and exit (negative counts from the end) |
252
+ | `--sound` · `--bed Dm` · `--sound-level x` · `--sound-out file.wav` | a sound track synthesised by Volito (see *Sound design*), a pad in a key, its level, the track alone |
133
253
  | `--packs <dir>` | more packs (also `VOLITO_PACKS`) |
134
254
  | `--format mov\|webm\|mp4\|hevc\|gif\|png` | for `render`; `png`/`svg` for `still` |
135
255
 
@@ -144,10 +264,14 @@ volito check ./my-graphic.js # run it at every aspect, report p
144
264
 
145
265
  ## AI agents (MCP)
146
266
 
267
+ <img src=".github/assets/agents.jpg" alt="An agent adds the Volito MCP server, then calls motion_list, motion_preview, motion_check and motion_render to make a lower third in 16:9 and 9:16" width="100%">
268
+
147
269
  ```bash
148
- claude mcp add volito -- npx -y volito mcp
270
+ npx volito init # adds the server for Claude Code, Cursor and VS Code, and the skill
271
+ npx volito doctor # what is ready: Node, FFmpeg formats, fonts, each agent's setup
149
272
  ```
150
273
 
274
+ Or by hand: `claude mcp add volito -- npx -y volito mcp`, `codex mcp add volito -- npx -y volito mcp`, and for
151
275
  Cursor, Windsurf and other MCP clients:
152
276
 
153
277
  ```json
@@ -162,11 +286,14 @@ Cursor, Windsurf and other MCP clients:
162
286
  | `motion_preview` | a contact sheet as an image — the agent sees how it moves and whether text fits |
163
287
  | `motion_still` | one frame as an image |
164
288
  | `motion_check` | errors and warnings at every aspect |
165
- | `motion_render` | render to a file and return its path |
289
+ | `motion_render` | render to a file and return its path (`sound: true` muxes a synthesised track, `bed: "Dm"` a pad) |
290
+ | `motion_sound` | the graphic's sound alone as a .wav, with its cue list |
166
291
  | `motion_moves` | every move, ease, idle, hit and mood the `motion` settings take |
292
+ | `motion_validate` | check a Graphic spec (inline or a file) against its item before rendering |
293
+ | `motion_review` | timing, 9:16 platform safe zones and a contact sheet per aspect, measured before rendering |
167
294
  | `motion_api` | the program API and the motion kit, for writing new graphics |
168
295
 
169
- Every tool takes an `item` or your own `code`, plus `motion`, `mood`, `seed` and `speed`. A ready-made agent skill is in `skill/SKILL.md` — copy it
296
+ Every tool takes an `item`, your own `code` or a `spec` file, plus `motion`, `mood`, `seed` and `speed`. A ready-made agent skill is in `skills/volito/SKILL.md` — `npx volito init` installs it for Claude Code, `npx skills add monarcpro/volito` for other agents, or copy it
170
297
  to `~/.claude/skills/volito/` for Claude Code.
171
298
 
172
299
  ## Node API
@@ -203,6 +330,64 @@ The player runs each program in a sandboxed Web Worker and draws through the sam
203
330
  renderer, so what plays on the page is what renders. Fonts load from `base` (the package's own
204
331
  `fonts/` on jsDelivr by default); serve the package's `fonts/` and `dist/registry.json` to stay offline.
205
332
 
333
+ ### `<volito-player>`
334
+
335
+ The same player as an HTML element, with controls and aspect tabs. One script, no build step:
336
+
337
+ ```html
338
+ <script type="module" src="https://cdn.jsdelivr.net/npm/volito/dist/player.js"></script>
339
+
340
+ <volito-player item="essentials/lower-third"
341
+ props='{"name":"Ada Lovelace","role":"First programmer"}'
342
+ brand="cobalt" aspects="all" controls autoplay loop></volito-player>
343
+ ```
344
+
345
+ Or `import "volito/player"` in a bundled app. Each tab lays the item out again for that aspect, not a
346
+ crop. It loads when it nears the screen, pauses off screen and in a hidden tab, and does not autoplay
347
+ for readers who prefer reduced motion.
348
+
349
+ | Attribute | What it does |
350
+ | --- | --- |
351
+ | `item` | `pack/id` or an id (or set the `program` property to your own `frame(t, $)` code) |
352
+ | `props` | the item's props as JSON |
353
+ | `brand` | a built-in style; the `brand` property also takes DESIGN.md text. `accent`, `accent2`, `ink`, `paper`, `mode` override colours |
354
+ | `aspect` · `aspects` | the aspect shown (`16:9`, `9:16`, `1:1`, `4:5`, `WIDTHxHEIGHT`) · the tabs to offer (`all` or a list) |
355
+ | `duration` `speed` `mood` `seed` `motion` `beats` | as on the CLI; `motion` takes `part.setting=value` separated by `;` |
356
+ | `controls` `autoplay` `loop` | play/pause, a scrubber and the time; start when shown; play again at the end |
357
+ | `playback-rate` · `range-start` `range-end` | play faster or slower · play only `[start, end)` seconds |
358
+ | `poster` · `posters` | an image until the first frame · per-aspect images as JSON |
359
+ | `ground` | behind a transparent graphic: `footage` (default), `checker`, `none` or a colour |
360
+ | `background` | a colour drawn into the frame itself |
361
+ | `base` · `loading` · `resolution` | where `fonts/` and `dist/registry.json` live · `eager` to load at once · the canvas's longest side (1920) |
362
+
363
+ Properties and methods: `play()`, `pause()`, `seek(t)`, `load()`, `currentTime`, `duration`, `paused`,
364
+ `ended`, `ready`, `playbackRate`, `props`, `brand`, `aspect`, `options` (anything else a build takes:
365
+ `words`, `media`, `beats`), `program`, `warnings` and `player` (the `MotionPlayer` underneath). Events,
366
+ none of which bubble: `ready`, `play`, `pause`, `ended`, `timeupdate` (about ten a second),
367
+ `durationchange`, `aspectchange`, `warnings` and `error`. Style it with CSS custom properties
368
+ (`--volito-accent`, `--volito-stage`, `--volito-max-height`, …) or `::part()`; Space, ←/→ (a frame,
369
+ Shift for a second), Home and End work when it has focus. `examples/player.html` shows each of these.
370
+
371
+
372
+ #### Interactive states
373
+
374
+ A graphic can be a live UI element: its timeline cut into named states that page events and your code
375
+ switch between. Every item in the `ui` pack declares its own, so this works with no setup:
376
+
377
+ ```html
378
+ <volito-player item="ui/button" aspect="1000x500" ground="none" props='{"label":"Get started"}'></volito-player>
379
+ <script type="module">
380
+ const button = document.querySelector("volito-player");
381
+ button.addEventListener("statechange", (e) => console.log(e.detail.to)); // enter → idle → hover → press → loading
382
+ await fetch("/api/signup", { method: "POST" });
383
+ button.state = "done"; // lands on the check
384
+ </script>
385
+ ```
386
+
387
+ Any graphic can have states: `states='{"idle":{"from":"idle","to":"hover","play":"loop"},…}'` (times are seconds or
388
+ beat names; `play` is `once`, `loop` or `hold`; `next` hands a finished `once` on), and
389
+ `on="pointerenter(idle): hover; pointerleave(hover): idle; click: press"` maps page events to them.
390
+
206
391
  ## Brand styles
207
392
 
208
393
  36 built in. MONARC PRO's: `ember`, `cream`, `mono`, `neon`, `pop`, `studio`, and the explainer art
@@ -338,6 +523,12 @@ faces (`src/fonts-extra.ts`), styles (`src/styles-extra.ts`) and patterns (`src/
338
523
  - The engine: [MIT](LICENSE).
339
524
  - The MONARC packs: the [MONARC Packs License](PACKS-LICENSE.md). Use them in any video, personal or
340
525
  commercial, with no attribution required. Don't resell them as templates.
341
- - The fonts: each family's SIL Open Font License, in `fonts/licenses/`.
526
+ - The fonts: each family's SIL Open Font License, in `fonts/licenses/` of the installed package
527
+ (`pnpm build` writes that folder in a checkout).
528
+
529
+ ## Contributing
530
+
531
+ Issues and pull requests are welcome: [CONTRIBUTING.md](CONTRIBUTING.md) covers the setup, the tests and
532
+ how items and packs are written. Report security problems privately, as [SECURITY.md](SECURITY.md) says.
342
533
 
343
534
  Made by [MONARC STUDIOS](https://monarcpro.app), the team behind [MONARC PRO](https://monarcpro.app).
package/dist/browser.d.ts CHANGED
@@ -215,6 +215,33 @@ interface MotionConfig {
215
215
  /** "name.in=pop", "in=pop" (every part), "*.ease=bouncy", or a JSON object → overrides. */
216
216
  declare function parseMotionArgs(args: string[]): MotionInput;
217
217
 
218
+ /**
219
+ * Interactive states for <volito-player>: a graphic's timeline cut into named stretches — idle, hover,
220
+ * press, loading, success — that page events and code switch between. Each state plays its stretch once
221
+ * (then stays on its last frame, or moves on to `next`), loops it, or holds one frame. Times are seconds or
222
+ * the item's beat names, so an item that names its beats ("hover", "press") declares its states in
223
+ * item.json and works with no setup:
224
+ *
225
+ * "states": { "idle": { "from": "idle", "to": "hover", "play": "loop" },
226
+ * "hover": { "from": "hover", "to": "press", "play": "once" },
227
+ * "press": { "from": "press", "to": "loading", "play": "once", "next": "loading" } },
228
+ * "on": "pointerenter(idle): hover; pointerleave(hover): idle; click: press"
229
+ *
230
+ * Pure functions: parsed and resolved here, played by the element.
231
+ */
232
+ declare const STATE_PLAYS: readonly ["once", "loop", "hold"];
233
+ type StatePlay = (typeof STATE_PLAYS)[number];
234
+ interface StateDef {
235
+ /** Where the stretch starts: seconds, a beat name, "start" or "end". Default: the start. */
236
+ from?: number | string;
237
+ /** Where it ends: seconds, a beat name, "start" or "end". Default: the end. */
238
+ to?: number | string;
239
+ /** once: play it and stay on its last frame (or go to `next`); loop: repeat it; hold: show `from` and stay. */
240
+ play?: StatePlay;
241
+ /** The state to go to when a `once` stretch finishes. */
242
+ next?: string;
243
+ }
244
+
218
245
  /**
219
246
  * Packs and items: the library format. A pack is a folder of items that share a look and a
220
247
  * helper file; an item is one motion graphic — `item.json` (what it is, the props it takes,
@@ -292,6 +319,13 @@ interface ItemManifest {
292
319
  libs?: LibraryName[];
293
320
  /** Faces whose glyphs 3D text is built from: brand roles ("display") or specs ("Anton:400"). Default: display. */
294
321
  faces3d?: string[];
322
+ /**
323
+ * Interactive states for <volito-player>: named stretches of the timeline (beat names or seconds), each
324
+ * played once, looped or held — { "idle": { "from": "idle", "to": "hover", "play": "loop" }, … }.
325
+ */
326
+ states?: Record<string, StateDef>;
327
+ /** The page events that switch states by default: "pointerenter(idle): hover; click: press". */
328
+ on?: string;
295
329
  }
296
330
  interface PackManifest {
297
331
  format: number;
@@ -488,7 +522,14 @@ declare class MotionPlayer {
488
522
  private opts;
489
523
  private built;
490
524
  private worker;
491
- private css;
525
+ private env;
526
+ /** Every face the package has (fonts/faces.json), and the files the worker has loaded. */
527
+ private all;
528
+ private loaded;
529
+ private readonly css;
530
+ private widening;
531
+ private gone;
532
+ private lastT;
492
533
  private raf;
493
534
  private started;
494
535
  private offset;
@@ -503,7 +544,15 @@ declare class MotionPlayer {
503
544
  /** The time shown now, seconds. */
504
545
  get time(): number;
505
546
  get program(): TitleProgram;
547
+ private get base();
506
548
  private load;
549
+ private startWorker;
550
+ /** The faces a frame draws with. */
551
+ private facesOf;
552
+ /** The @font-face rules for a set of faces, as data: URLs; one string per set, made once. */
553
+ private cssOf;
554
+ /** A frame drew with a face the worker lacks (so measured without it): restart it with that face, then redraw. */
555
+ private widen;
507
556
  private report;
508
557
  /** Change props, style, aspect or duration; the frame redraws. */
509
558
  update(opts: Partial<PlayerOptions>): Promise<void>;