@jokerized/decksmith 0.8.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.
Files changed (40) hide show
  1. package/README.md +121 -4
  2. package/dist/cli.js +4101 -651
  3. package/dist/deck-runtime.js +70 -2
  4. package/dist/index.js +4134 -651
  5. package/dist/mcp.js +3642 -515
  6. package/dist/types/build/files.d.ts +13 -1
  7. package/dist/types/deck/motion.d.ts +64 -0
  8. package/dist/types/deck/playback.d.ts +206 -0
  9. package/dist/types/deck/repack.d.ts +10 -0
  10. package/dist/types/deck/runtime.d.ts +96 -1
  11. package/dist/types/deck/subtitles.d.ts +29 -1
  12. package/dist/types/emit/archetypes/annotated-figure.d.ts +1 -1
  13. package/dist/types/emit/archetypes/bar-compare.d.ts +0 -28
  14. package/dist/types/emit/archetypes/callout.d.ts +0 -5
  15. package/dist/types/emit/archetypes/claim-figure.d.ts +15 -0
  16. package/dist/types/emit/archetypes/grid.d.ts +0 -14
  17. package/dist/types/emit/archetypes/line-chart.d.ts +0 -8
  18. package/dist/types/emit/archetypes/pipeline.d.ts +15 -1
  19. package/dist/types/emit/archetypes/stack.d.ts +1 -1
  20. package/dist/types/emit/composition.d.ts +47 -2
  21. package/dist/types/emit/faces.d.ts +22 -0
  22. package/dist/types/emit/fit.d.ts +127 -0
  23. package/dist/types/emit/kit.d.ts +104 -2
  24. package/dist/types/emit/look.d.ts +138 -0
  25. package/dist/types/emit/motion.d.ts +244 -0
  26. package/dist/types/emit/svg.d.ts +54 -16
  27. package/dist/types/emit/theme.d.ts +1 -1
  28. package/dist/types/emit/themes/index.d.ts +19 -1
  29. package/dist/types/emit/themes/packs.d.ts +15 -0
  30. package/dist/types/emit/themes/pick.d.ts +104 -0
  31. package/dist/types/emit/type.d.ts +111 -0
  32. package/dist/types/index.d.ts +35 -1
  33. package/dist/types/plan/direct.d.ts +66 -0
  34. package/dist/types/prefs.d.ts +15 -1
  35. package/dist/types/source/fonts.d.ts +11 -1
  36. package/dist/types/types.d.ts +38 -0
  37. package/dist/types/verify/fidelity.d.ts +34 -0
  38. package/dist/types/verify/fill.d.ts +205 -0
  39. package/dist/types/verify/motion.d.ts +33 -0
  40. package/package.json +4 -1
package/README.md CHANGED
@@ -220,6 +220,49 @@ Arrow keys, Space and PageUp/PageDown step; clicking the left or right third doe
220
220
  notes; `f` is fullscreen; `m` mutes the voice and `s` hides the subtitles. Every step is
221
221
  deep-linkable (`#3` is slide 3, `#3.2` its second reveal).
222
222
 
223
+ ### The v2 player (`--design v2`)
224
+
225
+ `build --design v2` (or `"design": "v2"` in the storyboard or config) gives `deck.html` the
226
+ v2 player; everything else about the build is unchanged. A deck that is already built
227
+ gets it without rebuilding:
228
+
229
+ ```bash
230
+ decksmith repack out/ # writes out/deck2.html beside deck.html, never over it
231
+ ```
232
+
233
+ `repack` swaps the inlined runtime, marks the page and checks that every JSON island is
234
+ byte-identical — no Chrome, no TTS, no re-render.
235
+
236
+ - **One control bar**: play/pause, the counter, narration speed (0.75–2×), `CC`, caption
237
+ size (S/M/L/XL) and fullscreen — or, in a window too narrow for those beside a caption,
238
+ play and one settings menu. **It never covers text.** It docks under the slide in spare
239
+ letterbox (a portrait phone); over the slide's empty bottom padding when that holds a
240
+ 40px target (a slide about 720px tall or more), where it hides 2.5s after the last
241
+ pointer move while the deck plays; otherwise in a band under the slide that it shares
242
+ side by side with the captions, whose text is padded in past the buttons.
243
+ `test/deck-page.test.ts` measures controls against caption text and against every glyph
244
+ the slide draws, at six viewports.
245
+ - **Play/pause** pauses the voice where it is and carries on from the same word. A deck
246
+ opens paused; stepping while paused moves the slide silently.
247
+ - **Speed** sets the narration's `playbackRate` live, on the sentence already playing, and
248
+ divides the reveal glides and every autoplay wait by the same factor so they keep pace.
249
+ A stop with no narration holds for its reveal and 1.5s at 1×, not the author's gap.
250
+ - **Captions** are sized from the slide (3% of its height, 13px floor; L and XL keep floors
251
+ of 16 and 19px so the size control works on a phone) and the slide gives up only one
252
+ two-line strip for them: 84% of the frame at 1080p, 83% in an 800×450 embed (v0.8.0: 77%
253
+ and 69%), 100% in a portrait letterbox. Long cues are cut to two lines of the strip's
254
+ actual width, which also splits Japanese and Chinese.
255
+ - **Keys:** Space steps forward (Space is the presenter's key, not play); `Enter` plays and
256
+ pauses; `c` (or `s`) captions; `<`/`>` speed; `+`/`-` caption size. Letter keys fall back
257
+ to the physical key under a Korean or Japanese IME. Anything held with Cmd, Ctrl or Alt
258
+ is left to the browser.
259
+ - **Preferences** — speed, captions on/off, size — come from `?speed=1.25&cc=0&ccsize=l`
260
+ (this visit only), else from `localStorage` (`decksmith.prefs.v1`), else the defaults.
261
+ When the viewer changes one, the deck posts
262
+ `{ type: "decksmith:prefs", speed, cc, ccsize }` to its parent so an embedding site can
263
+ keep it per user (a cross-site iframe's storage is partitioned), and it applies the same
264
+ message when the parent sends it. Check `event.origin` on your side.
265
+
223
266
  Stepping forward *plays* the reveal rather than cutting to it — the step layer sweeps the
224
267
  composition's timelines across frames instead of seeking once. Backward steps, `Home`/`End`
225
268
  and deep links cut, because entrance tweens run in reverse look like elements un-drawing
@@ -784,8 +827,11 @@ invalidates a storyboard you have already edited.
784
827
  | `lang` | the source's | plan | BCP-47. Drives the copy, the voice, and the font subset |
785
828
  | `tone` | `plain` | plan | `plain` · `academic` · `conversational` · `punchy` |
786
829
  | `density` | `normal` | plan | `sparse` · `normal` · `dense` — how much text a slide may carry |
787
- | `theme` | `ink` | emit | `ink` · `paper` · `mono` |
830
+ | `theme` | `ink` | emit | `ink` · `paper` · `mono`, or a v2 style pack by name (see Themes) |
831
+ | `design` | `classic` | narrate, emit | `classic` is the v0.8.0 look byte for byte · `v2` is the redesign: the v2 player (see "The v2 player") and a style pack per deck when no theme is named |
832
+ | `packSeed` | the source id | narrate, emit | what `design: v2` hashes to pick a pack; pass a paper id so its languages share one |
788
833
  | `animationSpeed` | `1` | emit | multiplies every duration, hold and beat length. Below 1 is faster |
834
+ | `design` | `classic` | emit | `classic` (the 0.8 look, byte-identical) · `v2` (the redesign — see [v2 motion](#v2-motion)) |
789
835
  | `narration.voice` | picked for `lang`+`tone` | narrate | an explicit edge-tts voice id |
790
836
  | `narration.rate` | `+0%` | narrate | edge-tts prosody |
791
837
  | `narration.pitch` | `+0Hz` | narrate | edge-tts prosody |
@@ -832,8 +878,8 @@ why `slideCount` did nothing.
832
878
  decksmith.config.json: unknown preference "narration.speed". Valid: enabled, voice, rate, pitch, subtitles.
833
879
  ```
834
880
 
835
- On the command line: `--slides --lang --tone --density` on `plan`, `--theme --speed` on
836
- `build`, `--voice --rate --pitch --no-subtitles` on `narrate`, `--images --image-provider
881
+ On the command line: `--slides --lang --tone --density` on `plan`, `--theme --design
882
+ --pack-seed --speed` on `build` (`--design --pack-seed` on `narrate` too), `--voice --rate --pitch --no-subtitles` on `narrate`, `--images --image-provider
837
883
  --image-model --image-style --image-max` on `plan` and `illustrate`, and all but the image
838
884
  flags on `pack`, which records the preferences the deck was made under — whether it was
839
885
  illustrated is read off the storyboard itself, the way `narration.enabled` is read off the
@@ -841,9 +887,43 @@ narration beside it.
841
887
 
842
888
  A preference sitting at its default says nothing, so a stored artifact wins over it and
843
889
  loses to anything you type. `plan` stamps `lang` and `theme` into the storyboard it
844
- writes; `build` then uses the storyboard's unless `--theme` or a config file restates one.
890
+ writes (and `design`, only when one was asked for); `build` then uses the storyboard's
891
+ unless `--theme`/`--design` or a config file restates one.
845
892
  Language is never overridden at build time — it describes copy that is already written.
846
893
 
894
+ `--design v2` (or `"design": "v2"` in the config file) lets the build vary each beat's
895
+ layout: bars as rows or columns, a pipeline as a row, a stair or a column, a claim beside,
896
+ mirrored against or above its figure, a comparison as columns or rows, and the headline on
897
+ top, in a left rail or under the body. The choice is made by code, deterministically, per
898
+ paper — never by the planner — and it never moves a stop, so narration stays aligned.
899
+ `build` writes the choices to `out/look.json`. Without the flag the deck is the classic one,
900
+ byte for byte. See `.planning/2026-10-07-v2-layout-director.md`.
901
+
902
+ ## v2 motion
903
+
904
+ `--design v2` replaces the 0.8 deck's single motion — every scene fading up the same
905
+ eyebrow and headline, every seam the same 0.4s dissolve, nothing moving once a slide has
906
+ built — with a grammar planned per deck (`src/emit/motion.ts`):
907
+
908
+ - **Entrances.** Six verbs — `rise`, `slide`, `snap`, `focus`, `wipe`, `mask` — one per
909
+ scene, chosen from the source id and beat id, never the same twice in a row, with the
910
+ stock `rise` capped at a quarter of the deck.
911
+ - **Seams.** `dissolve`, `push`, `lift`, `wipe`, `zoom`, picked from how two neighbouring
912
+ beats relate (same family → push, a role boundary → zoom, a title → lift, into the close
913
+ → dissolve), never repeated back to back, and at least three kinds in a deck of ten or
914
+ more beats. A beat `inside` the one before keeps the camera dive.
915
+ - **Emphasis while the narrator talks.** The part a sentence is about pulses, glows or is
916
+ underlined, starting on a cue boundary of that sentence inside the quiet stretch after
917
+ its stop, and is back at rest before the next reveal — so every frame a gate captures
918
+ at a stop is unchanged.
919
+
920
+ All of it is `fromTo` tweens with no callbacks, seeded rather than random, and keeps every
921
+ hold, every scene window and `timing.json` exactly as `classic` writes them. In `deck.html`
922
+ a v2 deck also glides through the seam into the next slide (0.8 cut to its first stop,
923
+ already built) and, while a stop's audio plays, seeks the scene through that stop's quiet
924
+ stretch on the audio clock so the emphasis lands on the same word as in the video. Both
925
+ are off under `prefers-reduced-motion`.
926
+
847
927
  ## Themes
848
928
 
849
929
  Three, each a position rather than a hue.
@@ -862,6 +942,41 @@ naming a family the deck does not declare falls back silently.
862
942
  A theme is a name and a palette, and that is the whole extension point: a new one is a
863
943
  file in `src/emit/themes/` plus a line in `THEMES`. No archetype learns it exists.
864
944
 
945
+ ### v2 style packs
946
+
947
+ Six more, each a whole look rather than a palette: its own typeface pairing and type
948
+ scale, ground and accent, eyebrow treatment, figure framing and surface.
949
+
950
+ | Pack | Ground | Headline / body | Title | Lists | Bars | Leans to |
951
+ |---|---|---|---|---|---|---|
952
+ | `signal` | violet-black, Magma accent | Space Grotesk / Inter | glowing headline | ticks | pills | foot headlines |
953
+ | `blueprint` | navy, cyan | IBM Plex Sans / IBM Plex Sans | drawing frame with corner marks | numbers | square, on dashed tracks | rail headlines |
954
+ | `atlas` | espresso, amber | Source Serif 4 / Inter | centred, frontispiece rule | dots | slightly rounded | top headlines |
955
+ | `folio` | cream, oxblood | Source Serif 4 / Source Serif 4 | masthead rules | numbers | square, no tracks | top headlines, versus |
956
+ | `chalk` | cool white, ultramarine | Space Grotesk / IBM Plex Sans | highlighter under each word | cards | rounded, outlined | foot headlines, tables |
957
+ | `journal` | sage, forest | IBM Plex Sans / Source Serif 4 | side bar down the title | ruled rows | slightly rounded, outlined tracks | rail headlines |
958
+
959
+ The forms are the pack's `forms` (list marks, Director affinity) and its `skin` (title,
960
+ bars), which may set only paint: colours, shadows, radii, outlines and SVG stroke/fill
961
+ opacity, never a box. In a Korean, Japanese or Chinese deck a pack's serif roles are set
962
+ in Noto Serif KR/JP/SC, bundled beside the sans.
963
+
964
+ `--theme <pack>` forces one. `--design v2` picks one when nobody named a theme (a
965
+ storyboard's default `ink` counts as nobody): a weighted, deterministic hash of the
966
+ source id (or `--pack-seed`), leaning mildly toward packs that suit the deck's mix of
967
+ archetypes. Over the 176 HypePaper storyboards on disk the busiest pack carries 20.5% of
968
+ decks. With narration on disk, a pack that would stage a beat with a different stop count
969
+ than the narration was recorded at, or that would leave out a beat the storyboard's own
970
+ theme draws, is skipped for the next one; if none fits, the storyboard's own theme is kept.
971
+ So `--design v2` never breaks a narrated rebuild and never costs a slide.
972
+
973
+ Each pack's faces ship beside a Latin deck, vendored from `@fontsource-variable/*` like
974
+ Inter, and are measured by their own width tables (`src/emit/faces.ts`, written by
975
+ `node scripts/measure-faces.mjs --write`). A CJK deck keeps its Noto bundle first in every
976
+ stack — Noto Serif for a role the pack sets in a serif, Noto Sans otherwise — so the glyph
977
+ shapes change with the pack in every language.
978
+ The packs' interfaces are written up in `.planning/2026-10-07-v2-style-packs.md`.
979
+
865
980
  ## Narration
866
981
 
867
982
  ```sh
@@ -1278,6 +1393,8 @@ src/prefs.ts the three-layer preference resolver
1278
1393
  src/emit/kit.ts the seam between the deck shell and the archetype emitters
1279
1394
  src/emit/archetypes/ one emitter per archetype
1280
1395
  src/emit/themes/ one palette per file; the registry is the extension point
1396
+ src/emit/type.ts type specs: the v2 packs' faces and chrome scale, read by chromeHeight and chromeCss
1397
+ src/emit/faces.ts measured width tables for the packs' Latin faces (generated)
1281
1398
  src/images/ the three rungs a brief is drawn through, and the illustrate step
1282
1399
  src/narrate/ edge-tts, one segment per stop
1283
1400
  src/pack/ the .deck container and its bake/link/embed policy