stagecraft 0.1.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/AGENT.md +792 -0
- package/LICENSE +21 -0
- package/README.md +210 -0
- package/bin/cli.js +51 -0
- package/bin/export.js +137 -0
- package/bin/init.js +52 -0
- package/bin/lib/edit-ops.js +405 -0
- package/bin/serve.js +278 -0
- package/dist/stagecraft.bundle.css +4443 -0
- package/dist/stagecraft.bundle.js +7621 -0
- package/dist/themes/brand.bundle.css +5262 -0
- package/dist/themes/neon.bundle.css +5289 -0
- package/dist/themes/paper.bundle.css +5276 -0
- package/dist/themes/phosphor.bundle.css +4443 -0
- package/dist/themes/shopware.bundle.css +5850 -0
- package/examples/closing-card.js +74 -0
- package/examples/orchestration-graph.js +156 -0
- package/examples/terminal-log.js +109 -0
- package/examples/token-stream.js +96 -0
- package/examples/whoami.js +90 -0
- package/package.json +41 -0
- package/src/components/activity-list.js +75 -0
- package/src/components/agenda.js +79 -0
- package/src/components/bar-chart.js +162 -0
- package/src/components/before-after.js +135 -0
- package/src/components/bento.js +73 -0
- package/src/components/big-number.js +87 -0
- package/src/components/callout.js +75 -0
- package/src/components/checklist.js +81 -0
- package/src/components/code-block.js +141 -0
- package/src/components/code-diff.js +98 -0
- package/src/components/compare.js +85 -0
- package/src/components/counter.js +80 -0
- package/src/components/cta.js +69 -0
- package/src/components/cycle.js +146 -0
- package/src/components/definition.js +96 -0
- package/src/components/donut-chart.js +179 -0
- package/src/components/full-image.js +82 -0
- package/src/components/funnel.js +111 -0
- package/src/components/gauge.js +147 -0
- package/src/components/heatmap.js +141 -0
- package/src/components/image-grid.js +80 -0
- package/src/components/image-text.js +96 -0
- package/src/components/kinetic-text.js +72 -0
- package/src/components/kpi.js +106 -0
- package/src/components/line-chart.js +215 -0
- package/src/components/manifesto.js +104 -0
- package/src/components/marquee.js +63 -0
- package/src/components/matrix2x2.js +151 -0
- package/src/components/pillars.js +80 -0
- package/src/components/pricing.js +90 -0
- package/src/components/process-flow.js +133 -0
- package/src/components/progress.js +136 -0
- package/src/components/punchline.js +82 -0
- package/src/components/pyramid.js +107 -0
- package/src/components/qanda.js +60 -0
- package/src/components/quote.js +70 -0
- package/src/components/roadmap.js +130 -0
- package/src/components/section-card.js +45 -0
- package/src/components/shift-arrow.js +41 -0
- package/src/components/spark-line.js +147 -0
- package/src/components/spotlight.js +85 -0
- package/src/components/statement.js +106 -0
- package/src/components/stats.js +91 -0
- package/src/components/steps.js +83 -0
- package/src/components/swot.js +110 -0
- package/src/components/team-grid.js +87 -0
- package/src/components/testimonial.js +99 -0
- package/src/components/timeline.js +91 -0
- package/src/components/tip.js +63 -0
- package/src/components/venn.js +198 -0
- package/src/edit-mode.js +1256 -0
- package/src/engine.js +823 -0
- package/src/helpers.js +169 -0
- package/src/transitions.js +101 -0
- package/starter/index.html +40 -0
- package/starter/slides/00-title.js +12 -0
- package/starter/stagecraft.config.js +8 -0
- package/themes/brand/base.css +4 -0
- package/themes/brand/components-business.css +173 -0
- package/themes/brand/components-chart.css +65 -0
- package/themes/brand/components-content.css +126 -0
- package/themes/brand/components-data.css +162 -0
- package/themes/brand/components-diagram.css +115 -0
- package/themes/brand/components-layout.css +112 -0
- package/themes/brand/components.css +46 -0
- package/themes/brand/manifest.json +20 -0
- package/themes/brand/tokens.css +20 -0
- package/themes/brand/transitions.css +4 -0
- package/themes/neon/base.css +10 -0
- package/themes/neon/components-business.css +189 -0
- package/themes/neon/components-chart.css +70 -0
- package/themes/neon/components-content.css +112 -0
- package/themes/neon/components-data.css +160 -0
- package/themes/neon/components-diagram.css +109 -0
- package/themes/neon/components-layout.css +87 -0
- package/themes/neon/components.css +87 -0
- package/themes/neon/manifest.json +21 -0
- package/themes/neon/tokens.css +17 -0
- package/themes/neon/transitions.css +13 -0
- package/themes/paper/base.css +9 -0
- package/themes/paper/components-business.css +196 -0
- package/themes/paper/components-chart.css +74 -0
- package/themes/paper/components-content.css +108 -0
- package/themes/paper/components-data.css +168 -0
- package/themes/paper/components-diagram.css +89 -0
- package/themes/paper/components-layout.css +105 -0
- package/themes/paper/components.css +60 -0
- package/themes/paper/manifest.json +10 -0
- package/themes/paper/tokens.css +21 -0
- package/themes/paper/transitions.css +11 -0
- package/themes/phosphor/base.css +511 -0
- package/themes/phosphor/components-business.css +818 -0
- package/themes/phosphor/components-chart.css +415 -0
- package/themes/phosphor/components-content.css +530 -0
- package/themes/phosphor/components-data.css +824 -0
- package/themes/phosphor/components-diagram.css +427 -0
- package/themes/phosphor/components-layout.css +450 -0
- package/themes/phosphor/components.css +223 -0
- package/themes/phosphor/manifest.json +11 -0
- package/themes/phosphor/tokens.css +17 -0
- package/themes/phosphor/transitions.css +213 -0
- package/themes/shopware/base.css +94 -0
- package/themes/shopware/components-business.css +344 -0
- package/themes/shopware/components-chart.css +121 -0
- package/themes/shopware/components-content.css +169 -0
- package/themes/shopware/components-data.css +219 -0
- package/themes/shopware/components-diagram.css +129 -0
- package/themes/shopware/components-layout.css +166 -0
- package/themes/shopware/components.css +83 -0
- package/themes/shopware/manifest.json +21 -0
- package/themes/shopware/tokens.css +68 -0
- package/themes/shopware/transitions.css +22 -0
package/AGENT.md
ADDED
|
@@ -0,0 +1,792 @@
|
|
|
1
|
+
# Stagecraft — Slides for Creative Directors
|
|
2
|
+
|
|
3
|
+
You're not filling a template. You're directing a scene.
|
|
4
|
+
|
|
5
|
+
If your slide is fewer than three lines, it's probably boring. The components below are anchors, not cages. Take them apart. Add particles, typewriters, glitch transitions, SVG. The Web Animations API is your friend.
|
|
6
|
+
|
|
7
|
+
## 1. The rule
|
|
8
|
+
|
|
9
|
+
- A deck is a collection of `.js` files registered via `Stage.register({...})`.
|
|
10
|
+
- Each slide owns its DOM, its animation, its lifecycle.
|
|
11
|
+
- The engine handles navigation, the storyboard, and transitions.
|
|
12
|
+
- If you copy-paste a component call and don't customize it, you've wasted the opportunity.
|
|
13
|
+
|
|
14
|
+
## 2. The toolbox (Layer-2 components)
|
|
15
|
+
|
|
16
|
+
Components have spare defaults on purpose. Adding animation is opt-in.
|
|
17
|
+
|
|
18
|
+
### Stage.KineticText — multi-line staggered reveal (workhorse, ~50% of slides)
|
|
19
|
+
```js
|
|
20
|
+
Stage.register(Stage.KineticText({
|
|
21
|
+
section: 2,
|
|
22
|
+
title: '02 · The shift',
|
|
23
|
+
pace: 800,
|
|
24
|
+
lines: [
|
|
25
|
+
{ text: 'You start with a sentence.', color: 'fg' },
|
|
26
|
+
{ text: 'You end with the sentence', color: 'dim' },
|
|
27
|
+
{ text: 'rewritten.', color: 'accent', pause: 800 }
|
|
28
|
+
]
|
|
29
|
+
}));
|
|
30
|
+
```
|
|
31
|
+
Colors: `fg` `dim` `accent` `amber` `blue`. `pause` is extra ms before that line.
|
|
32
|
+
|
|
33
|
+
### Stage.SectionCard — section divider
|
|
34
|
+
```js
|
|
35
|
+
Stage.register(Stage.SectionCard({
|
|
36
|
+
section: 3, number: '03',
|
|
37
|
+
title: 'Where the work goes',
|
|
38
|
+
tag: 'time and attention'
|
|
39
|
+
}));
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Stage.ActivityList — numbered items (num · name · description)
|
|
43
|
+
```js
|
|
44
|
+
Stage.register(Stage.ActivityList({
|
|
45
|
+
section: 3,
|
|
46
|
+
items: [
|
|
47
|
+
{ num: '01', name: 'Problem framing', desc: 'understand the actual ask' },
|
|
48
|
+
{ num: '02', name: 'Architecture', desc: 'pick the shape' }
|
|
49
|
+
],
|
|
50
|
+
reveal: 'staggered' // 'staggered' | 'per-click' | 'instant'
|
|
51
|
+
}));
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Stage.Compare — two-column comparison
|
|
55
|
+
```js
|
|
56
|
+
Stage.register(Stage.Compare({
|
|
57
|
+
section: 4,
|
|
58
|
+
left: { heading: 'OLD', items: ['type', 'compile'], style: 'strikethrough' },
|
|
59
|
+
right: { heading: 'NEW', items: ['describe', 'review'], style: 'accent' },
|
|
60
|
+
reveal: 'staggered'
|
|
61
|
+
}));
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Stage.Counter — live numeric counters
|
|
65
|
+
```js
|
|
66
|
+
Stage.register(Stage.Counter({
|
|
67
|
+
section: 4,
|
|
68
|
+
blocks: [
|
|
69
|
+
{ label: 'Lines written', start: 0, perSecond: 47, color: 'accent' },
|
|
70
|
+
{ label: 'Bugs introduced', start: 0, perSecond: 3, color: 'amber' }
|
|
71
|
+
],
|
|
72
|
+
footer: 'Both numbers are wrong.'
|
|
73
|
+
}));
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Stage.ShiftArrow — `from → to` mental model
|
|
77
|
+
```js
|
|
78
|
+
Stage.register(Stage.ShiftArrow({
|
|
79
|
+
section: 6, from: 'writing code', to: 'reviewing code'
|
|
80
|
+
}));
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Layout family
|
|
84
|
+
|
|
85
|
+
#### Stage.ImageText — image one side, text the other
|
|
86
|
+
```js
|
|
87
|
+
Stage.register(Stage.ImageText({
|
|
88
|
+
section: 3,
|
|
89
|
+
image: { src: 'assets/photo.jpg', alt: '...' },
|
|
90
|
+
side: 'left', // or 'right'
|
|
91
|
+
heading: 'The thing',
|
|
92
|
+
body: 'First sentence.\nSecond sentence.', // \n staggers per line
|
|
93
|
+
caption: 'optional small dim line',
|
|
94
|
+
reveal: 'staggered'
|
|
95
|
+
}));
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### Stage.FullImage — full-bleed image with optional overlay
|
|
99
|
+
```js
|
|
100
|
+
Stage.register(Stage.FullImage({
|
|
101
|
+
section: 4,
|
|
102
|
+
image: { src: 'assets/landscape.jpg', alt: '...' },
|
|
103
|
+
overlay: { position: 'bottom-left', headline: 'BIG IDEA', body: 'small subtitle' }
|
|
104
|
+
}));
|
|
105
|
+
```
|
|
106
|
+
Without `overlay`: subtle ken-burns drift. Positions: `center`, `top`, `bottom-left`, `bottom-right`.
|
|
107
|
+
|
|
108
|
+
#### Stage.Quote — large quote with attribution
|
|
109
|
+
```js
|
|
110
|
+
Stage.register(Stage.Quote({
|
|
111
|
+
section: 2,
|
|
112
|
+
quote: 'The best way to predict the future is to invent it.',
|
|
113
|
+
author: 'Alan Kay',
|
|
114
|
+
role: 'computer scientist',
|
|
115
|
+
source: '1971'
|
|
116
|
+
}));
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### Stage.BigNumber — one huge number + label
|
|
120
|
+
```js
|
|
121
|
+
Stage.register(Stage.BigNumber({
|
|
122
|
+
section: 4,
|
|
123
|
+
number: 47, unit: 'x',
|
|
124
|
+
label: 'productivity multiplier',
|
|
125
|
+
caption: 'observed on a focused refactor'
|
|
126
|
+
}));
|
|
127
|
+
```
|
|
128
|
+
Counts up from 0 to target on init.
|
|
129
|
+
|
|
130
|
+
#### Stage.Stats — grid of statistic cards
|
|
131
|
+
```js
|
|
132
|
+
Stage.register(Stage.Stats({
|
|
133
|
+
section: 4,
|
|
134
|
+
blocks: [
|
|
135
|
+
{ number: 12, unit: 'k', label: 'commits', color: 'accent' },
|
|
136
|
+
{ number: 47, unit: 'x', label: 'speedup', color: 'amber' },
|
|
137
|
+
{ number: 99, unit: '%', label: 'caffeine', color: 'blue' }
|
|
138
|
+
],
|
|
139
|
+
columns: 3
|
|
140
|
+
}));
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### Stage.Bento — 2026 modular grid
|
|
144
|
+
```js
|
|
145
|
+
Stage.register(Stage.Bento({
|
|
146
|
+
section: 5,
|
|
147
|
+
cells: [
|
|
148
|
+
{ span: 2, heading: 'Hero', body: 'wide cell', color: 'accent' },
|
|
149
|
+
{ heading: 'Stat', body: '...', image: { src: 'a.jpg' } },
|
|
150
|
+
{ heading: 'Quote', body: '...' },
|
|
151
|
+
{ span: 2, heading: 'Note', body: 'wide cell' }
|
|
152
|
+
]
|
|
153
|
+
}));
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Diagram family
|
|
157
|
+
|
|
158
|
+
#### Stage.Pillars — N columns with material icons
|
|
159
|
+
```js
|
|
160
|
+
Stage.register(Stage.Pillars({
|
|
161
|
+
section: 5,
|
|
162
|
+
intro: 'Three pillars',
|
|
163
|
+
pillars: [
|
|
164
|
+
{ icon: 'bolt', heading: 'Speed', body: 'iterate fast' },
|
|
165
|
+
{ icon: 'shield', heading: 'Safety', body: 'never break prod' },
|
|
166
|
+
{ icon: 'visibility', heading: 'Clarity', body: 'see what you ship' }
|
|
167
|
+
],
|
|
168
|
+
reveal: 'staggered' // | 'per-click' | 'instant'
|
|
169
|
+
}));
|
|
170
|
+
```
|
|
171
|
+
Icons are Material Symbols Outlined names. See https://fonts.google.com/icons.
|
|
172
|
+
|
|
173
|
+
#### Stage.Timeline — milestones along a line
|
|
174
|
+
```js
|
|
175
|
+
Stage.register(Stage.Timeline({
|
|
176
|
+
section: 5,
|
|
177
|
+
orientation: 'horizontal', // or 'vertical'
|
|
178
|
+
events: [
|
|
179
|
+
{ date: '2024 Q1', heading: 'idea', icon: 'lightbulb' },
|
|
180
|
+
{ date: '2024 Q3', heading: 'prototype', icon: 'science' },
|
|
181
|
+
{ date: '2025 Q1', heading: 'launch', icon: 'rocket_launch', color: 'accent' }
|
|
182
|
+
],
|
|
183
|
+
reveal: 'per-click'
|
|
184
|
+
}));
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### Stage.Pyramid — stacked tiers
|
|
188
|
+
```js
|
|
189
|
+
Stage.register(Stage.Pyramid({
|
|
190
|
+
section: 6,
|
|
191
|
+
layers: [
|
|
192
|
+
{ label: 'Vision', body: 'where to' },
|
|
193
|
+
{ label: 'Strategy', body: 'how to' },
|
|
194
|
+
{ label: 'Tactics', body: 'do what' }
|
|
195
|
+
],
|
|
196
|
+
orientation: 'up', // narrowest layer on top
|
|
197
|
+
reveal: 'staggered'
|
|
198
|
+
}));
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### Stage.Cycle — circular arrangement
|
|
202
|
+
```js
|
|
203
|
+
Stage.register(Stage.Cycle({
|
|
204
|
+
section: 6,
|
|
205
|
+
items: [
|
|
206
|
+
{ label: 'Plan', icon: 'edit_note' },
|
|
207
|
+
{ label: 'Build', icon: 'construction' },
|
|
208
|
+
{ label: 'Measure', icon: 'monitor_heart' },
|
|
209
|
+
{ label: 'Learn', icon: 'school' }
|
|
210
|
+
],
|
|
211
|
+
reveal: 'rotate' // spins in on entry
|
|
212
|
+
}));
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
#### Stage.Funnel — narrowing stages
|
|
216
|
+
```js
|
|
217
|
+
Stage.register(Stage.Funnel({
|
|
218
|
+
section: 6,
|
|
219
|
+
stages: [
|
|
220
|
+
{ label: 'Visitors', value: '10,000' },
|
|
221
|
+
{ label: 'Trials', value: '1,200' },
|
|
222
|
+
{ label: 'Customers', value: '180', color: 'accent' }
|
|
223
|
+
],
|
|
224
|
+
reveal: 'staggered'
|
|
225
|
+
}));
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Chart family
|
|
229
|
+
|
|
230
|
+
#### Stage.Matrix2x2 — quadrant chart (Eisenhower-style)
|
|
231
|
+
```js
|
|
232
|
+
Stage.register(Stage.Matrix2x2({
|
|
233
|
+
section: 7,
|
|
234
|
+
axes: {
|
|
235
|
+
x: { label: 'Effort', low: 'low', high: 'high' },
|
|
236
|
+
y: { label: 'Impact', low: 'low', high: 'high' }
|
|
237
|
+
},
|
|
238
|
+
quadrants: [
|
|
239
|
+
{ x: 'low', y: 'high', label: 'Quick wins', color: 'accent' },
|
|
240
|
+
{ x: 'high', y: 'high', label: 'Big bets', color: 'blue' },
|
|
241
|
+
{ x: 'low', y: 'low', label: 'Fill-ins' },
|
|
242
|
+
{ x: 'high', y: 'low', label: 'Time sinks', color: 'red' }
|
|
243
|
+
],
|
|
244
|
+
reveal: 'per-click'
|
|
245
|
+
}));
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### Stage.BarChart — simple bars
|
|
249
|
+
```js
|
|
250
|
+
Stage.register(Stage.BarChart({
|
|
251
|
+
section: 7,
|
|
252
|
+
orientation: 'horizontal', // or 'vertical'
|
|
253
|
+
bars: [
|
|
254
|
+
{ label: 'A', value: 42, color: 'accent' },
|
|
255
|
+
{ label: 'B', value: 78, color: 'amber' },
|
|
256
|
+
{ label: 'C', value: 31 }
|
|
257
|
+
],
|
|
258
|
+
unit: 'h',
|
|
259
|
+
reveal: 'animated' // 0 → value tween
|
|
260
|
+
}));
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
#### Stage.Progress — stacked progress bars
|
|
264
|
+
```js
|
|
265
|
+
Stage.register(Stage.Progress({
|
|
266
|
+
section: 7,
|
|
267
|
+
items: [
|
|
268
|
+
{ label: 'Coverage', value: 87 }, // /100
|
|
269
|
+
{ label: 'Refactor', value: 3, total: 5 }, // /5
|
|
270
|
+
{ label: 'Migration', value: 42, total: 100, color: 'amber' }
|
|
271
|
+
],
|
|
272
|
+
reveal: 'animated'
|
|
273
|
+
}));
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
#### Stage.ProcessFlow — N → N → N with arrows
|
|
277
|
+
```js
|
|
278
|
+
Stage.register(Stage.ProcessFlow({
|
|
279
|
+
section: 7,
|
|
280
|
+
orientation: 'horizontal', // or 'vertical'
|
|
281
|
+
steps: [
|
|
282
|
+
{ icon: 'edit', label: 'Draft' },
|
|
283
|
+
{ icon: 'visibility', label: 'Review' },
|
|
284
|
+
{ icon: 'check', label: 'Ship', color: 'accent' }
|
|
285
|
+
],
|
|
286
|
+
reveal: 'per-click'
|
|
287
|
+
}));
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
#### Stage.Venn — 2 or 3 overlapping circles
|
|
291
|
+
```js
|
|
292
|
+
Stage.register(Stage.Venn({
|
|
293
|
+
section: 7,
|
|
294
|
+
sets: [
|
|
295
|
+
{ label: 'speed', color: 'accent' },
|
|
296
|
+
{ label: 'quality', color: 'amber' },
|
|
297
|
+
{ label: 'cost', color: 'blue' }
|
|
298
|
+
],
|
|
299
|
+
overlaps: [
|
|
300
|
+
{ ids: [0, 1], label: 'real eng' },
|
|
301
|
+
{ ids: [0, 2], label: 'hack' },
|
|
302
|
+
{ ids: [1, 2], label: 'craft' },
|
|
303
|
+
{ ids: [0, 1, 2], label: 'unicorn' }
|
|
304
|
+
],
|
|
305
|
+
reveal: 'staggered'
|
|
306
|
+
}));
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Data-viz family (10)
|
|
310
|
+
|
|
311
|
+
#### Stage.KPI — hero metric card
|
|
312
|
+
```js
|
|
313
|
+
Stage.register(Stage.KPI({
|
|
314
|
+
section: 8, value: 42_300, unit: '€',
|
|
315
|
+
label: 'monthly recurring revenue',
|
|
316
|
+
change: { value: 18, direction: 'up', period: 'QoQ' },
|
|
317
|
+
color: 'accent', icon: 'trending_up'
|
|
318
|
+
}));
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
#### Stage.DonutChart — pie/donut with segments
|
|
322
|
+
```js
|
|
323
|
+
Stage.register(Stage.DonutChart({
|
|
324
|
+
section: 8,
|
|
325
|
+
segments: [
|
|
326
|
+
{ label: 'Engineering', value: 12, color: 'accent' },
|
|
327
|
+
{ label: 'Sales', value: 7, color: 'amber' },
|
|
328
|
+
{ label: 'Ops', value: 3, color: 'blue' }
|
|
329
|
+
],
|
|
330
|
+
centerLabel: 'headcount',
|
|
331
|
+
reveal: 'animated'
|
|
332
|
+
}));
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
#### Stage.LineChart — multi-series line/area chart
|
|
336
|
+
```js
|
|
337
|
+
Stage.register(Stage.LineChart({
|
|
338
|
+
section: 8,
|
|
339
|
+
xLabels: ['Q1','Q2','Q3','Q4'],
|
|
340
|
+
series: [
|
|
341
|
+
{ label: 'Revenue', color: 'accent', points: [12, 18, 24, 32] },
|
|
342
|
+
{ label: 'Cost', color: 'amber', points: [8, 11, 14, 17] }
|
|
343
|
+
],
|
|
344
|
+
area: true,
|
|
345
|
+
reveal: 'animated'
|
|
346
|
+
}));
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
#### Stage.Gauge — semi-circular progress meter
|
|
350
|
+
```js
|
|
351
|
+
Stage.register(Stage.Gauge({
|
|
352
|
+
section: 8, value: 73, max: 100,
|
|
353
|
+
label: 'capacity used', color: 'amber', ticks: 5
|
|
354
|
+
}));
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### Stage.SparkLine — number + tiny inline trend
|
|
358
|
+
```js
|
|
359
|
+
Stage.register(Stage.SparkLine({
|
|
360
|
+
section: 8, value: 1247, label: 'daily signups',
|
|
361
|
+
points: [820, 880, 910, 1050, 1100, 1180, 1247],
|
|
362
|
+
color: 'accent', period: 'past 7 days'
|
|
363
|
+
}));
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
#### Stage.Heatmap — calendar-style intensity grid
|
|
367
|
+
```js
|
|
368
|
+
Stage.register(Stage.Heatmap({
|
|
369
|
+
section: 8, rows: 7, cols: 12,
|
|
370
|
+
data: [[1,3,5,...], [2,4,6,...], ...],
|
|
371
|
+
color: 'accent',
|
|
372
|
+
xLabels: ['Jan','Feb','Mar', ...],
|
|
373
|
+
yLabels: ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']
|
|
374
|
+
}));
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
#### Stage.Roadmap — quarterly swimlanes
|
|
378
|
+
```js
|
|
379
|
+
Stage.register(Stage.Roadmap({
|
|
380
|
+
section: 8,
|
|
381
|
+
months: ['Q1','Q2','Q3','Q4'],
|
|
382
|
+
lanes: [
|
|
383
|
+
{ label: 'Platform', color: 'accent', bars: [{start:0, end:2, label:'auth'}, {start:2, end:4, label:'billing'}] },
|
|
384
|
+
{ label: 'Growth', color: 'amber', bars: [{start:1, end:3, label:'onboarding'}] }
|
|
385
|
+
],
|
|
386
|
+
reveal: 'staggered'
|
|
387
|
+
}));
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
#### Stage.SWOT — strengths/weaknesses/opportunities/threats
|
|
391
|
+
```js
|
|
392
|
+
Stage.register(Stage.SWOT({
|
|
393
|
+
section: 8,
|
|
394
|
+
strengths: ['fast iteration', 'small team'],
|
|
395
|
+
weaknesses: ['no enterprise sales'],
|
|
396
|
+
opportunities: ['LLM tailwind', 'market shift'],
|
|
397
|
+
threats: ['incumbents catching up'],
|
|
398
|
+
reveal: 'per-click'
|
|
399
|
+
}));
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
#### Stage.CodeBlock — syntax-highlighted code
|
|
403
|
+
```js
|
|
404
|
+
Stage.register(Stage.CodeBlock({
|
|
405
|
+
section: 8,
|
|
406
|
+
language: 'javascript',
|
|
407
|
+
fileName: 'engine.js',
|
|
408
|
+
code: `function go(idx) {\n if (idx < 0) return;\n current = idx;\n}`,
|
|
409
|
+
highlight: [2],
|
|
410
|
+
reveal: 'typewriter'
|
|
411
|
+
}));
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
#### Stage.CodeDiff — unified diff with +/- lines
|
|
415
|
+
```js
|
|
416
|
+
Stage.register(Stage.CodeDiff({
|
|
417
|
+
section: 8, fileName: 'engine.js',
|
|
418
|
+
lines: [
|
|
419
|
+
{ type: 'context', text: 'function go(idx) {' },
|
|
420
|
+
{ type: 'remove', text: ' if (idx < 0) return;' },
|
|
421
|
+
{ type: 'add', text: ' if (idx < 0 || idx >= slides.length) return;' },
|
|
422
|
+
{ type: 'context', text: ' current = idx;' },
|
|
423
|
+
{ type: 'context', text: '}' }
|
|
424
|
+
],
|
|
425
|
+
reveal: 'staggered'
|
|
426
|
+
}));
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Business family (10)
|
|
430
|
+
|
|
431
|
+
#### Stage.Pricing — N tiers with features
|
|
432
|
+
```js
|
|
433
|
+
Stage.register(Stage.Pricing({
|
|
434
|
+
section: 9,
|
|
435
|
+
tiers: [
|
|
436
|
+
{ name: 'Free', price: '$0', period: '/mo', features: ['1 deck', 'public sharing'] },
|
|
437
|
+
{ name: 'Pro', price: '$12', period: '/mo', features: ['unlimited decks', 'edit mode', 'all themes'], featured: true, ctaLabel: 'Start trial' },
|
|
438
|
+
{ name: 'Team', price: '$48', period: '/mo', features: ['everything Pro', '5 seats', 'analytics'] }
|
|
439
|
+
],
|
|
440
|
+
reveal: 'staggered'
|
|
441
|
+
}));
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
#### Stage.Testimonial — quote with photo + logo
|
|
445
|
+
```js
|
|
446
|
+
Stage.register(Stage.Testimonial({
|
|
447
|
+
section: 9,
|
|
448
|
+
quote: 'It cut our deck-prep time by 80%.',
|
|
449
|
+
author: { name: 'Jane Doe', role: 'VP Product', company: 'Acme', photo: 'photo.jpg', logo: 'logo.svg' }
|
|
450
|
+
}));
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
#### Stage.TeamGrid — N people cards
|
|
454
|
+
```js
|
|
455
|
+
Stage.register(Stage.TeamGrid({
|
|
456
|
+
section: 9, columns: 3,
|
|
457
|
+
people: [
|
|
458
|
+
{ name: 'Ada Lovelace', role: 'Founder', photo: 'ada.jpg', bio: 'wrote the first program' },
|
|
459
|
+
{ name: 'Alan Turing', role: 'CTO', photo: 'alan.jpg', social: { linkedin: '…' } }
|
|
460
|
+
]
|
|
461
|
+
}));
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
#### Stage.Agenda — timed schedule
|
|
465
|
+
```js
|
|
466
|
+
Stage.register(Stage.Agenda({
|
|
467
|
+
section: 9,
|
|
468
|
+
items: [
|
|
469
|
+
{ time: '09:00', label: 'Kickoff', duration: '30m', icon: 'flag' },
|
|
470
|
+
{ time: '09:30', label: 'Deep dive', duration: '90m', icon: 'psychology' },
|
|
471
|
+
{ time: '11:00', label: 'Demo', duration: '20m', icon: 'play_arrow' }
|
|
472
|
+
],
|
|
473
|
+
reveal: 'per-click'
|
|
474
|
+
}));
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
#### Stage.Checklist — checked/unchecked items
|
|
478
|
+
```js
|
|
479
|
+
Stage.register(Stage.Checklist({
|
|
480
|
+
section: 9,
|
|
481
|
+
items: [
|
|
482
|
+
{ text: 'set up project', done: true },
|
|
483
|
+
{ text: 'wire up auth', done: true },
|
|
484
|
+
{ text: 'write tests', done: false, body: 'integration first' },
|
|
485
|
+
{ text: 'ship it' }
|
|
486
|
+
],
|
|
487
|
+
reveal: 'staggered'
|
|
488
|
+
}));
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
#### Stage.Steps — numbered tutorial steps
|
|
492
|
+
```js
|
|
493
|
+
Stage.register(Stage.Steps({
|
|
494
|
+
section: 9,
|
|
495
|
+
steps: [
|
|
496
|
+
{ number: 1, label: 'install', icon: 'download', body: 'npm i stagecraft' },
|
|
497
|
+
{ number: 2, label: 'init', icon: 'create', body: 'npx stagecraft init' },
|
|
498
|
+
{ number: 3, label: 'present', icon: 'play_arrow', body: 'open index.html' }
|
|
499
|
+
],
|
|
500
|
+
orientation: 'horizontal',
|
|
501
|
+
reveal: 'per-click'
|
|
502
|
+
}));
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
#### Stage.CTA — call to action
|
|
506
|
+
```js
|
|
507
|
+
Stage.register(Stage.CTA({
|
|
508
|
+
section: 9,
|
|
509
|
+
headline: 'Start building today',
|
|
510
|
+
body: 'No credit card required.',
|
|
511
|
+
action: { label: 'Sign up', hint: '→' },
|
|
512
|
+
accent: true
|
|
513
|
+
}));
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
#### Stage.Callout — colored sidebar box
|
|
517
|
+
```js
|
|
518
|
+
Stage.register(Stage.Callout({
|
|
519
|
+
section: 9,
|
|
520
|
+
kind: 'warning', // 'info' | 'tip' | 'warning' | 'danger' | 'success'
|
|
521
|
+
icon: 'warning',
|
|
522
|
+
heading: 'Heads up',
|
|
523
|
+
body: 'Don\'t run this in production without backing up the database.'
|
|
524
|
+
}));
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
#### Stage.Tip — compact emphasis box
|
|
528
|
+
```js
|
|
529
|
+
Stage.register(Stage.Tip({
|
|
530
|
+
section: 9, kind: 'tip',
|
|
531
|
+
icon: 'lightbulb',
|
|
532
|
+
body: 'Combining BarChart with reveal: per-click makes a great explainer.'
|
|
533
|
+
}));
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
#### Stage.BeforeAfter — split comparison
|
|
537
|
+
```js
|
|
538
|
+
Stage.register(Stage.BeforeAfter({
|
|
539
|
+
section: 9,
|
|
540
|
+
before: { label: 'BEFORE', image: { src: 'old.jpg' } },
|
|
541
|
+
after: { label: 'AFTER', image: { src: 'new.jpg' } },
|
|
542
|
+
reveal: 'slider' // 'slider' animates the divider from 0 → 50%
|
|
543
|
+
}));
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### Content / typography family (8)
|
|
547
|
+
|
|
548
|
+
#### Stage.Statement — single massive declarative
|
|
549
|
+
```js
|
|
550
|
+
Stage.register(Stage.Statement({
|
|
551
|
+
section: 10,
|
|
552
|
+
text: 'We are not in the widget business. We are in the trust business.',
|
|
553
|
+
emphasis: ['trust']
|
|
554
|
+
}));
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
#### Stage.QandA — question + answer
|
|
558
|
+
```js
|
|
559
|
+
Stage.register(Stage.QandA({
|
|
560
|
+
section: 10,
|
|
561
|
+
question: 'What slows teams down most?',
|
|
562
|
+
answer: 'Unclear ownership.',
|
|
563
|
+
attribution: 'observed across 47 projects'
|
|
564
|
+
}));
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
#### Stage.Manifesto — numbered "We believe…"
|
|
568
|
+
```js
|
|
569
|
+
Stage.register(Stage.Manifesto({
|
|
570
|
+
section: 10,
|
|
571
|
+
intro: 'We believe...',
|
|
572
|
+
declarations: [
|
|
573
|
+
{ text: 'Software should be honest.', emphasis: ['honest'] },
|
|
574
|
+
{ text: 'Defaults should be excellent.', emphasis: ['excellent'] },
|
|
575
|
+
{ text: 'Customers should never wait.', emphasis: ['never wait'] }
|
|
576
|
+
],
|
|
577
|
+
reveal: 'per-click'
|
|
578
|
+
}));
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
#### Stage.Punchline — buildup + payoff
|
|
582
|
+
```js
|
|
583
|
+
Stage.register(Stage.Punchline({
|
|
584
|
+
section: 10,
|
|
585
|
+
buildup: [
|
|
586
|
+
'We tried scaling the team.',
|
|
587
|
+
'We tried adding tools.',
|
|
588
|
+
'We tried more meetings.'
|
|
589
|
+
],
|
|
590
|
+
payoff: 'What worked was deleting code.',
|
|
591
|
+
reveal: 'manual'
|
|
592
|
+
}));
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
#### Stage.Definition — dictionary-style entry
|
|
596
|
+
```js
|
|
597
|
+
Stage.register(Stage.Definition({
|
|
598
|
+
section: 10,
|
|
599
|
+
term: 'stagecraft',
|
|
600
|
+
definition: 'a small JavaScript library for cinematic, agent-authored presentations.',
|
|
601
|
+
etymology: 'from "stage" + "-craft"',
|
|
602
|
+
examples: ['Stagecraft handled the keynote deck beautifully.']
|
|
603
|
+
}));
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
#### Stage.ImageGrid — gallery
|
|
607
|
+
```js
|
|
608
|
+
Stage.register(Stage.ImageGrid({
|
|
609
|
+
section: 10, columns: 3,
|
|
610
|
+
images: [
|
|
611
|
+
{ src: 'a.jpg', caption: 'one' },
|
|
612
|
+
{ src: 'b.jpg', caption: 'two' },
|
|
613
|
+
{ src: 'c.jpg' }
|
|
614
|
+
],
|
|
615
|
+
reveal: 'cascade'
|
|
616
|
+
}));
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
#### Stage.Spotlight — focus + context strip
|
|
620
|
+
```js
|
|
621
|
+
Stage.register(Stage.Spotlight({
|
|
622
|
+
section: 10,
|
|
623
|
+
focus: { heading: 'The big one', body: 'this is what matters', icon: 'star' },
|
|
624
|
+
context: ['supporting fact 1', 'supporting fact 2', 'supporting fact 3'],
|
|
625
|
+
reveal: 'staggered'
|
|
626
|
+
}));
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
#### Stage.Marquee — scrolling ticker
|
|
630
|
+
```js
|
|
631
|
+
Stage.register(Stage.Marquee({
|
|
632
|
+
section: 10,
|
|
633
|
+
items: ['shipped 2024-01', 'shipped 2024-02', 'shipped 2024-03', 'shipped 2024-04'],
|
|
634
|
+
direction: 'left', speed: 'medium', double: true
|
|
635
|
+
}));
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
## 3. The toolbox (Layer-1 primitives)
|
|
639
|
+
|
|
640
|
+
Available globally as `Stage.<name>`. Use them in any slide's `init()` to build bespoke motion.
|
|
641
|
+
|
|
642
|
+
| Primitive | Signature | What |
|
|
643
|
+
|---|---|---|
|
|
644
|
+
| `staggerIn` | `(nodes, step=200, initial=100) → cleanup` | Add `.in` class to nodes one after another. Pairs with `.stagger > *` CSS. |
|
|
645
|
+
| `typewriter` | `(el, text, {speed, jitter, onDone}) → cleanup` | Character-by-character text reveal. |
|
|
646
|
+
| `emitParticle` | `(parent, x1, y1, x2, y2, dur=800) → cleanup` | SVG particle traveling between two points. |
|
|
647
|
+
| `revealByDataStep` | `(el, step)` | Show `[data-step=N]` elements where N ≤ step. Pass as `onStep`. |
|
|
648
|
+
| `blinkCaret` | `(el) → cleanup` | Attach a blinking caret. |
|
|
649
|
+
| `sessionElapsedClock` | `({start}) → {el, stop}` | Live MM:SS clock element. |
|
|
650
|
+
| `assignStageKeys` | `(root)` | Auto-assigns `data-stage-key` for edit-mode pins (engine calls this). |
|
|
651
|
+
|
|
652
|
+
## 4. The cookbook
|
|
653
|
+
|
|
654
|
+
When you need motion that the components don't cover, **read these first** — they're the ceiling, not the floor. All in `examples/`:
|
|
655
|
+
|
|
656
|
+
- `examples/token-stream.js` — interleaved word-fill across a split panel, particle emit.
|
|
657
|
+
- `examples/orchestration-graph.js` — SVG hex-graph with particles flowing from satellites to center.
|
|
658
|
+
- `examples/terminal-log.js` — streaming colored log lines with a human realization reveal.
|
|
659
|
+
- `examples/whoami.js` — terminal prompt cycling through identity strings.
|
|
660
|
+
- `examples/closing-card.js` — QR + dedication + underline.
|
|
661
|
+
|
|
662
|
+
Don't copy them verbatim. Take the technique (the interleaved queue, the SVG particle pattern, the streaming type) and apply it to your own content.
|
|
663
|
+
|
|
664
|
+
## 5. The step model
|
|
665
|
+
|
|
666
|
+
A slide may declare `steps: N`. The engine:
|
|
667
|
+
|
|
668
|
+
- Tracks `currentStep` (starts at 0).
|
|
669
|
+
- On `→`: if `currentStep < N-1`, increment and call `onStep(el, currentStep)`. Otherwise advance to next slide.
|
|
670
|
+
- On `←`: mirror.
|
|
671
|
+
- On `R`: reset to step 0, re-run `init`.
|
|
672
|
+
|
|
673
|
+
```js
|
|
674
|
+
Stage.register({
|
|
675
|
+
section: 5, title: 'reveal each',
|
|
676
|
+
steps: 3,
|
|
677
|
+
render(el) {
|
|
678
|
+
el.innerHTML = `
|
|
679
|
+
<ul>
|
|
680
|
+
<li data-step="1">First insight</li>
|
|
681
|
+
<li data-step="2">Second insight</li>
|
|
682
|
+
<li data-step="3">Third insight</li>
|
|
683
|
+
</ul>`;
|
|
684
|
+
},
|
|
685
|
+
onStep: Stage.revealByDataStep
|
|
686
|
+
});
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
For trivial cases use `Stage.revealByDataStep`. For anything richer (glow transitions, particle emit, typewriter on each step) write `onStep` yourself — that's the point.
|
|
690
|
+
|
|
691
|
+
## 6. The transition library
|
|
692
|
+
|
|
693
|
+
In `stagecraft.config.js`, the `transition` on each slide controls how it enters:
|
|
694
|
+
|
|
695
|
+
```js
|
|
696
|
+
Stage.deck({
|
|
697
|
+
theme: 'phosphor',
|
|
698
|
+
slides: [
|
|
699
|
+
{ src: 'slides/00-title.js' },
|
|
700
|
+
{ src: 'slides/01-shift.js', transition: 'fade' },
|
|
701
|
+
{ src: 'slides/02-impact.js', transition: 'glitch' }
|
|
702
|
+
]
|
|
703
|
+
});
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
Built-in (14):
|
|
707
|
+
|
|
708
|
+
| | | |
|
|
709
|
+
|---|---|---|
|
|
710
|
+
| `cut` — hard, instant | `fade` — crossfade | `slide` — push from right |
|
|
711
|
+
| `dissolve` — slow blur fade | `glitch` — scanlines + RGB shift | `wipe` — masked sweep |
|
|
712
|
+
| `zoom-in` — scale up from small | `zoom-out` — start large, shrink | `flip` — 3D Y-axis rotate |
|
|
713
|
+
| `iris` — circular reveal | `shutter` — horizontal bands | `push` — strong horizontal push |
|
|
714
|
+
| `typewriter` — scaleX 0 → 1 | `shatter` — pixelated resolve | |
|
|
715
|
+
|
|
716
|
+
Themes override visuals. Unknown → falls back to `fade`.
|
|
717
|
+
|
|
718
|
+
## 7. Edit mode (you-might-not-see-it, but: it exists)
|
|
719
|
+
|
|
720
|
+
When the human runs `npx stagecraft serve`, they get a browser-based editor that writes back to source. They might leave notes in slides:
|
|
721
|
+
|
|
722
|
+
```js
|
|
723
|
+
// @note: too text-heavy, split into two slides
|
|
724
|
+
// @note[stage-key="KineticText/line[2]"]: this line is dishonest
|
|
725
|
+
Stage.register(Stage.KineticText({ ... }));
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
When they say "process my notes":
|
|
729
|
+
1. `grep -rn '@note' slides/`
|
|
730
|
+
2. Read each note + the slide it's attached to
|
|
731
|
+
3. Edit the slide accordingly
|
|
732
|
+
4. **Delete the `@note:` lines** (absence ⇔ resolved)
|
|
733
|
+
|
|
734
|
+
Notes don't get a "resolved" state. Deleting them is how you mark them done.
|
|
735
|
+
|
|
736
|
+
## 8. When to register a custom slide vs. use a component
|
|
737
|
+
|
|
738
|
+
Use a component when:
|
|
739
|
+
- It's truly a list of bullets / a comparison / a section divider — boring is fine for these.
|
|
740
|
+
- The visual you want is achievable with one component + minor styling.
|
|
741
|
+
|
|
742
|
+
Write a custom slide (just `Stage.register({section, title, render, init, ...})`) when:
|
|
743
|
+
- The animation is core to the message (token-stream, orchestration graph, terminal log).
|
|
744
|
+
- You're combining motion patterns no component covers.
|
|
745
|
+
- The slide is the centerpiece of a section — it deserves the attention.
|
|
746
|
+
|
|
747
|
+
The split should be roughly: ~40% workhorse components (KineticText, SectionCard, Quote, BigNumber), ~30% structural (ImageText, Bento, Compare, Pillars, Timeline), ~15% chart/diagram for data-heavy moments (BarChart, Matrix2x2, Pyramid, Funnel, Venn, ProcessFlow, Cycle), ~15% bespoke. If the bespoke share goes below 10%, the deck has gone flat.
|
|
748
|
+
|
|
749
|
+
## 9. The full component catalog at a glance
|
|
750
|
+
|
|
751
|
+
| Family | Components |
|
|
752
|
+
|---|---|
|
|
753
|
+
| **Core (6)** | KineticText · SectionCard · ActivityList · Compare · Counter · ShiftArrow |
|
|
754
|
+
| **Layout (6)** | ImageText · FullImage · Quote · BigNumber · Stats · Bento |
|
|
755
|
+
| **Diagram (5)** | Pillars · Timeline · Pyramid · Cycle · Funnel |
|
|
756
|
+
| **Chart (5)** | Matrix2x2 · BarChart · Progress · ProcessFlow · Venn |
|
|
757
|
+
| **Data-viz (10)** | KPI · DonutChart · LineChart · Gauge · SparkLine · Heatmap · Roadmap · SWOT · CodeBlock · CodeDiff |
|
|
758
|
+
| **Business (10)** | Pricing · Testimonial · TeamGrid · Agenda · Checklist · Steps · CTA · Callout · Tip · BeforeAfter |
|
|
759
|
+
| **Content (8)** | Statement · QandA · Manifesto · Punchline · Definition · ImageGrid · Spotlight · Marquee |
|
|
760
|
+
| **Bespoke (5)** | TokenStream · OrchestrationGraph · TerminalLog · Whoami · ClosingCard (cookbook in `examples/`) |
|
|
761
|
+
|
|
762
|
+
**50 anchored components + 5 cookbook bespoke patterns + 15 transitions.** Pick the closest anchor, then customize. Animate. Pace. **Direct the scene.**
|
|
763
|
+
|
|
764
|
+
## 10. Speaker notes
|
|
765
|
+
|
|
766
|
+
Slides take an optional second arg to `Stage.register` for metadata. The most common field is `notes`:
|
|
767
|
+
|
|
768
|
+
```js
|
|
769
|
+
Stage.register(Stage.KineticText({...}), {
|
|
770
|
+
notes: 'Pause after the third line. The audience needs the beat.'
|
|
771
|
+
});
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
Notes show only in the **Presenter View** (`P` opens a second window with current + next + notes + timer). They're editable via the 🎙 button on each storyboard tile.
|
|
775
|
+
|
|
776
|
+
## 11. Themes (5)
|
|
777
|
+
|
|
778
|
+
| | |
|
|
779
|
+
|---|---|
|
|
780
|
+
| `phosphor` (default) | dark, JetBrains Mono, phosphor-green |
|
|
781
|
+
| `paper` | light, Inter + Source Serif 4, navy |
|
|
782
|
+
| `neon` | dark, magenta + cyan, heavy glow |
|
|
783
|
+
| `brand` | dark, Inter, blue, schlicht |
|
|
784
|
+
| `shopware` | light, Inter, brand-blue `#0870ff` — sourced from Shopware's Meteor design tokens |
|
|
785
|
+
|
|
786
|
+
Switch live from the storyboard, or set `data-theme="..."` on `<html>` and link the matching CSS bundle.
|
|
787
|
+
|
|
788
|
+
## 12. Keyboard cheat sheet
|
|
789
|
+
|
|
790
|
+
`→ ← Space` navigate · `1-9` jump to section · `R` replay · `F` fullscreen
|
|
791
|
+
`S` storyboard · `P` presenter window · `E` toggle edit mode · `N` slide-level note
|
|
792
|
+
`?` show hint · `Esc` close overlay
|