@anvpx/motion-scenes 0.0.0-stage → 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.
Files changed (219) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -2
  3. package/dist/catalog.d.ts +17 -0
  4. package/dist/catalog.js +51 -0
  5. package/dist/custom.d.ts +86 -0
  6. package/dist/custom.js +170 -0
  7. package/dist/define-scene.d.ts +31 -0
  8. package/dist/define-scene.js +128 -0
  9. package/dist/html.d.ts +5 -0
  10. package/dist/html.js +14 -0
  11. package/dist/index.d.ts +11 -0
  12. package/dist/index.js +11 -0
  13. package/dist/position.d.ts +21 -0
  14. package/dist/position.js +16 -0
  15. package/dist/registry.d.ts +4 -0
  16. package/dist/registry.js +68 -0
  17. package/dist/runtime/easing.d.ts +14 -0
  18. package/dist/runtime/easing.js +45 -0
  19. package/dist/runtime/mount.d.ts +50 -0
  20. package/dist/runtime/mount.js +153 -0
  21. package/dist/runtime/timeline.d.ts +147 -0
  22. package/dist/runtime/timeline.js +199 -0
  23. package/dist/runtime-files.d.ts +2 -0
  24. package/dist/runtime-files.js +15 -0
  25. package/dist/scene-contract.d.ts +7 -0
  26. package/dist/scene-contract.js +104 -0
  27. package/dist/scene3d/post.d.ts +12 -0
  28. package/dist/scene3d/post.js +16 -0
  29. package/dist/scene3d/reflector.d.ts +9 -0
  30. package/dist/scene3d/reflector.js +17 -0
  31. package/dist/scene3d/textures.d.ts +9 -0
  32. package/dist/scene3d/textures.js +11 -0
  33. package/dist/scene3d/volumetric.d.ts +9 -0
  34. package/dist/scene3d/volumetric.js +16 -0
  35. package/dist/scenes/bug/index.d.ts +1 -0
  36. package/dist/scenes/bug/index.js +45 -0
  37. package/dist/scenes/bug/scene.d.ts +2 -0
  38. package/dist/scenes/bug/scene.js +6 -0
  39. package/dist/scenes/bug/style.css +30 -0
  40. package/dist/scenes/bullets/index.d.ts +1 -0
  41. package/dist/scenes/bullets/index.js +128 -0
  42. package/dist/scenes/bullets/scene.d.ts +2 -0
  43. package/dist/scenes/bullets/scene.js +6 -0
  44. package/dist/scenes/bullets/style.css +91 -0
  45. package/dist/scenes/callout/index.d.ts +9 -0
  46. package/dist/scenes/callout/index.js +95 -0
  47. package/dist/scenes/callout/scene.d.ts +2 -0
  48. package/dist/scenes/callout/scene.js +43 -0
  49. package/dist/scenes/callout/style.css +97 -0
  50. package/dist/scenes/caption/index.d.ts +1 -0
  51. package/dist/scenes/caption/index.js +72 -0
  52. package/dist/scenes/caption/scene.d.ts +11 -0
  53. package/dist/scenes/caption/scene.js +33 -0
  54. package/dist/scenes/caption/style.css +33 -0
  55. package/dist/scenes/chapter/index.d.ts +1 -0
  56. package/dist/scenes/chapter/index.js +29 -0
  57. package/dist/scenes/chapter/scene.d.ts +2 -0
  58. package/dist/scenes/chapter/scene.js +6 -0
  59. package/dist/scenes/chapter/style.css +25 -0
  60. package/dist/scenes/chart/index.d.ts +1 -0
  61. package/dist/scenes/chart/index.js +24 -0
  62. package/dist/scenes/chart/render.d.ts +4 -0
  63. package/dist/scenes/chart/render.js +257 -0
  64. package/dist/scenes/chart/scale.d.ts +11 -0
  65. package/dist/scenes/chart/scale.js +53 -0
  66. package/dist/scenes/chart/scene.d.ts +2 -0
  67. package/dist/scenes/chart/scene.js +73 -0
  68. package/dist/scenes/chart/schema.d.ts +36 -0
  69. package/dist/scenes/chart/schema.js +109 -0
  70. package/dist/scenes/chart/style.css +425 -0
  71. package/dist/scenes/code/index.d.ts +1 -0
  72. package/dist/scenes/code/index.js +109 -0
  73. package/dist/scenes/code/scene.d.ts +2 -0
  74. package/dist/scenes/code/scene.js +108 -0
  75. package/dist/scenes/code/style.css +155 -0
  76. package/dist/scenes/code/tokenize.d.ts +8 -0
  77. package/dist/scenes/code/tokenize.js +145 -0
  78. package/dist/scenes/compare/index.d.ts +1 -0
  79. package/dist/scenes/compare/index.js +128 -0
  80. package/dist/scenes/compare/scene.d.ts +2 -0
  81. package/dist/scenes/compare/scene.js +58 -0
  82. package/dist/scenes/compare/style.css +187 -0
  83. package/dist/scenes/countdown/index.d.ts +1 -0
  84. package/dist/scenes/countdown/index.js +46 -0
  85. package/dist/scenes/countdown/scene.d.ts +2 -0
  86. package/dist/scenes/countdown/scene.js +21 -0
  87. package/dist/scenes/countdown/style.css +32 -0
  88. package/dist/scenes/flow/index.d.ts +1 -0
  89. package/dist/scenes/flow/index.js +66 -0
  90. package/dist/scenes/flow/inspect.d.ts +26 -0
  91. package/dist/scenes/flow/inspect.js +25 -0
  92. package/dist/scenes/flow/layout.d.ts +83 -0
  93. package/dist/scenes/flow/layout.js +222 -0
  94. package/dist/scenes/flow/measure.d.ts +15 -0
  95. package/dist/scenes/flow/measure.js +33 -0
  96. package/dist/scenes/flow/plan.d.ts +42 -0
  97. package/dist/scenes/flow/plan.js +117 -0
  98. package/dist/scenes/flow/scene.d.ts +2 -0
  99. package/dist/scenes/flow/scene.js +6 -0
  100. package/dist/scenes/flow/schema.d.ts +49 -0
  101. package/dist/scenes/flow/schema.js +60 -0
  102. package/dist/scenes/flow/style.css +54 -0
  103. package/dist/scenes/hero/index.d.ts +3 -0
  104. package/dist/scenes/hero/index.js +77 -0
  105. package/dist/scenes/hero/scene.d.ts +2 -0
  106. package/dist/scenes/hero/scene.js +6 -0
  107. package/dist/scenes/hero/style.css +143 -0
  108. package/dist/scenes/icon-grid/index.d.ts +1 -0
  109. package/dist/scenes/icon-grid/index.js +69 -0
  110. package/dist/scenes/icon-grid/scene.d.ts +2 -0
  111. package/dist/scenes/icon-grid/scene.js +6 -0
  112. package/dist/scenes/icon-grid/style.css +74 -0
  113. package/dist/scenes/kinetic/index.d.ts +1 -0
  114. package/dist/scenes/kinetic/index.js +62 -0
  115. package/dist/scenes/kinetic/scene.d.ts +2 -0
  116. package/dist/scenes/kinetic/scene.js +98 -0
  117. package/dist/scenes/kinetic/style.css +94 -0
  118. package/dist/scenes/kpi-grid/index.d.ts +1 -0
  119. package/dist/scenes/kpi-grid/index.js +161 -0
  120. package/dist/scenes/kpi-grid/scene.d.ts +2 -0
  121. package/dist/scenes/kpi-grid/scene.js +6 -0
  122. package/dist/scenes/kpi-grid/style.css +141 -0
  123. package/dist/scenes/lower-third/index.d.ts +1 -0
  124. package/dist/scenes/lower-third/index.js +33 -0
  125. package/dist/scenes/lower-third/scene.d.ts +2 -0
  126. package/dist/scenes/lower-third/scene.js +6 -0
  127. package/dist/scenes/lower-third/style.css +45 -0
  128. package/dist/scenes/media-frame/index.d.ts +1 -0
  129. package/dist/scenes/media-frame/index.js +99 -0
  130. package/dist/scenes/media-frame/scene.d.ts +2 -0
  131. package/dist/scenes/media-frame/scene.js +85 -0
  132. package/dist/scenes/media-frame/style.css +275 -0
  133. package/dist/scenes/outro/index.d.ts +1 -0
  134. package/dist/scenes/outro/index.js +54 -0
  135. package/dist/scenes/outro/scene.d.ts +2 -0
  136. package/dist/scenes/outro/scene.js +6 -0
  137. package/dist/scenes/outro/style.css +92 -0
  138. package/dist/scenes/poster/index.d.ts +3 -0
  139. package/dist/scenes/poster/index.js +62 -0
  140. package/dist/scenes/poster/scene.d.ts +2 -0
  141. package/dist/scenes/poster/scene.js +6 -0
  142. package/dist/scenes/poster/style.css +102 -0
  143. package/dist/scenes/progress/index.d.ts +1 -0
  144. package/dist/scenes/progress/index.js +40 -0
  145. package/dist/scenes/progress/scene.d.ts +2 -0
  146. package/dist/scenes/progress/scene.js +17 -0
  147. package/dist/scenes/progress/style.css +31 -0
  148. package/dist/scenes/quote/index.d.ts +3 -0
  149. package/dist/scenes/quote/index.js +69 -0
  150. package/dist/scenes/quote/scene.d.ts +2 -0
  151. package/dist/scenes/quote/scene.js +6 -0
  152. package/dist/scenes/quote/style.css +86 -0
  153. package/dist/scenes/scene3d/index.d.ts +1 -0
  154. package/dist/scenes/scene3d/index.js +58 -0
  155. package/dist/scenes/scene3d/scene.d.ts +2 -0
  156. package/dist/scenes/scene3d/scene.js +413 -0
  157. package/dist/scenes/scene3d/style.css +43 -0
  158. package/dist/scenes/stat/index.d.ts +4 -0
  159. package/dist/scenes/stat/index.js +72 -0
  160. package/dist/scenes/stat/scene.d.ts +2 -0
  161. package/dist/scenes/stat/scene.js +6 -0
  162. package/dist/scenes/stat/style.css +95 -0
  163. package/dist/scenes/steps/index.d.ts +1 -0
  164. package/dist/scenes/steps/index.js +147 -0
  165. package/dist/scenes/steps/scene.d.ts +2 -0
  166. package/dist/scenes/steps/scene.js +6 -0
  167. package/dist/scenes/steps/style.css +190 -0
  168. package/dist/scenes/sticker/index.d.ts +1 -0
  169. package/dist/scenes/sticker/index.js +48 -0
  170. package/dist/scenes/sticker/scene.d.ts +2 -0
  171. package/dist/scenes/sticker/scene.js +57 -0
  172. package/dist/scenes/sticker/style.css +88 -0
  173. package/dist/scenes/table/index.d.ts +1 -0
  174. package/dist/scenes/table/index.js +131 -0
  175. package/dist/scenes/table/scene.d.ts +2 -0
  176. package/dist/scenes/table/scene.js +6 -0
  177. package/dist/scenes/table/style.css +102 -0
  178. package/dist/scenes/timeline/index.d.ts +1 -0
  179. package/dist/scenes/timeline/index.js +68 -0
  180. package/dist/scenes/timeline/scene.d.ts +2 -0
  181. package/dist/scenes/timeline/scene.js +6 -0
  182. package/dist/scenes/timeline/style.css +161 -0
  183. package/dist/scenes/title/index.d.ts +1 -0
  184. package/dist/scenes/title/index.js +52 -0
  185. package/dist/scenes/title/scene.d.ts +2 -0
  186. package/dist/scenes/title/scene.js +6 -0
  187. package/dist/scenes/title/style.css +80 -0
  188. package/dist/scenes/waveform/index.d.ts +1 -0
  189. package/dist/scenes/waveform/index.js +39 -0
  190. package/dist/scenes/waveform/scene.d.ts +2 -0
  191. package/dist/scenes/waveform/scene.js +35 -0
  192. package/dist/scenes/waveform/style.css +44 -0
  193. package/dist/shared/fit-text.d.ts +24 -0
  194. package/dist/shared/fit-text.js +82 -0
  195. package/dist/shared/format.d.ts +24 -0
  196. package/dist/shared/format.js +59 -0
  197. package/dist/shared/frame.d.ts +14 -0
  198. package/dist/shared/frame.js +21 -0
  199. package/dist/shared/icon-search.d.ts +9 -0
  200. package/dist/shared/icon-search.js +26 -0
  201. package/dist/shared/icon.d.ts +15 -0
  202. package/dist/shared/icon.js +28 -0
  203. package/dist/shared/index.d.ts +11 -0
  204. package/dist/shared/index.js +7 -0
  205. package/dist/shared/markup.d.ts +12 -0
  206. package/dist/shared/markup.js +43 -0
  207. package/dist/shared/measure.d.ts +7 -0
  208. package/dist/shared/measure.js +34 -0
  209. package/dist/shared/motion.d.ts +94 -0
  210. package/dist/shared/motion.js +117 -0
  211. package/dist/source-hash.d.ts +4 -0
  212. package/dist/source-hash.js +26 -0
  213. package/dist/test-fixtures.d.ts +9 -0
  214. package/dist/test-fixtures.js +22 -0
  215. package/dist/text-file.d.ts +1 -0
  216. package/dist/text-file.js +3 -0
  217. package/dist/words.d.ts +11 -0
  218. package/dist/words.js +93 -0
  219. package/package.json +36 -3
@@ -0,0 +1,425 @@
1
+ #scene-root {
2
+ gap: var(--mk-space-lg);
3
+ justify-content: flex-start;
4
+ }
5
+ #scene-root .mk-head {
6
+ display: flex;
7
+ flex-direction: column;
8
+ align-items: flex-start;
9
+ gap: var(--mk-space-md);
10
+ }
11
+ #scene-root .mk-heading {
12
+ font-family: var(--mk-font-display, var(--mk-font-sans));
13
+ font-size: var(--mk-font-size-xl);
14
+ font-weight: 800;
15
+ line-height: 1.04;
16
+ letter-spacing: -0.03em;
17
+ text-wrap: balance;
18
+ }
19
+ #scene-root .mk-panel {
20
+ flex: 1;
21
+ min-height: 0;
22
+ display: flex;
23
+ flex-direction: column;
24
+ padding: var(--mk-space-lg) var(--mk-space-xl);
25
+ background: var(--mk-color-card);
26
+ border: var(--mk-stroke-card, 2px) solid var(--mk-color-divider);
27
+ border-radius: var(--mk-radius-xl);
28
+ box-shadow: var(
29
+ --mk-shadow-card,
30
+ 0 24px 56px -28px color-mix(in srgb, var(--mk-color-fg) 40%, transparent)
31
+ );
32
+ }
33
+ #scene-root .mk-caption {
34
+ flex: none;
35
+ font-size: var(--mk-font-size-md);
36
+ color: var(--mk-color-muted);
37
+ }
38
+ #scene-root .mk-chart {
39
+ flex: 1;
40
+ min-height: 0;
41
+ display: flex;
42
+ }
43
+ #scene-root .mk-s1 {
44
+ --c: var(--mk-chart-1);
45
+ }
46
+ #scene-root .mk-s2 {
47
+ --c: var(--mk-chart-2);
48
+ }
49
+ #scene-root .mk-s3 {
50
+ --c: var(--mk-chart-3);
51
+ }
52
+ #scene-root .mk-c1 {
53
+ --c: var(--mk-chart-1);
54
+ }
55
+ #scene-root .mk-c2 {
56
+ --c: var(--mk-chart-2);
57
+ }
58
+ #scene-root .mk-c3 {
59
+ --c: var(--mk-chart-3);
60
+ }
61
+ #scene-root .mk-c4 {
62
+ --c: var(--mk-chart-4);
63
+ }
64
+ #scene-root .mk-c5 {
65
+ --c: var(--mk-chart-5);
66
+ }
67
+ #scene-root .mk-c6 {
68
+ --c: var(--mk-chart-6);
69
+ }
70
+ #scene-root .mk-c7 {
71
+ --c: var(--mk-chart-7);
72
+ }
73
+ #scene-root .mk-c8 {
74
+ --c: var(--mk-chart-8);
75
+ }
76
+
77
+ /* bars: one fill colour; with a highlight the other bars step back to a neutral */
78
+ #scene-root .mk-fill {
79
+ background: var(--mk-color-accent);
80
+ border-radius: var(--mk-radius-full);
81
+ }
82
+ #scene-root .mk-fill.mk-lo {
83
+ background: color-mix(in srgb, var(--mk-color-muted) 62%, var(--mk-color-card));
84
+ }
85
+ #scene-root .mk-name {
86
+ font-size: var(--mk-font-size-md);
87
+ font-weight: 600;
88
+ line-height: 1.15;
89
+ text-wrap: balance;
90
+ }
91
+ #scene-root .mk-lo .mk-name,
92
+ #scene-root .mk-lo.mk-leg {
93
+ color: var(--mk-color-muted);
94
+ }
95
+ #scene-root .mk-val {
96
+ display: inline-block;
97
+ transform-origin: left center;
98
+ font-size: var(--mk-font-size-lg);
99
+ font-weight: 800;
100
+ line-height: 1;
101
+ letter-spacing: -0.02em;
102
+ font-variant-numeric: var(--mk-numeric, tabular-nums);
103
+ white-space: nowrap;
104
+ }
105
+ #scene-root .mk-bars.mk-h {
106
+ flex-direction: column;
107
+ justify-content: space-evenly;
108
+ gap: var(--mk-space-md);
109
+ }
110
+ #scene-root .mk-h .mk-row {
111
+ flex: 1 1 0;
112
+ min-height: 0;
113
+ max-height: 120px;
114
+ display: grid;
115
+ grid-template-columns: minmax(0, 24%) minmax(0, 1fr) var(--vw);
116
+ align-items: center;
117
+ column-gap: var(--mk-space-lg);
118
+ }
119
+ #scene-root .mk-h.mk-noval .mk-row {
120
+ grid-template-columns: minmax(0, 24%) minmax(0, 1fr);
121
+ }
122
+ #scene-root .mk-h .mk-name {
123
+ text-align: right;
124
+ }
125
+ #scene-root .mk-h .mk-track {
126
+ height: 64px;
127
+ border-radius: var(--mk-radius-full);
128
+ background: var(--mk-color-surface);
129
+ }
130
+ #scene-root .mk-h .mk-fill {
131
+ display: block;
132
+ width: 0;
133
+ height: 100%;
134
+ min-width: 12px;
135
+ }
136
+ #scene-root .mk-bars.mk-v {
137
+ display: grid;
138
+ align-items: stretch;
139
+ column-gap: var(--mk-space-lg);
140
+ }
141
+ #scene-root .mk-v .mk-col {
142
+ min-width: 0;
143
+ display: flex;
144
+ flex-direction: column;
145
+ align-items: center;
146
+ gap: var(--mk-space-md);
147
+ }
148
+ #scene-root .mk-v .mk-well {
149
+ flex: 1;
150
+ min-height: 0;
151
+ width: 100%;
152
+ display: flex;
153
+ align-items: flex-end;
154
+ justify-content: center;
155
+ padding-top: 64px;
156
+ border-bottom: 3px solid var(--mk-color-divider);
157
+ }
158
+ #scene-root .mk-v .mk-stack {
159
+ position: relative;
160
+ width: 68%;
161
+ max-width: 220px;
162
+ height: 0;
163
+ }
164
+ #scene-root .mk-v .mk-fill {
165
+ display: block;
166
+ width: 100%;
167
+ height: 100%;
168
+ border-radius: var(--mk-radius-lg) var(--mk-radius-lg) 0 0;
169
+ }
170
+ #scene-root .mk-v .mk-val {
171
+ position: absolute;
172
+ bottom: 100%;
173
+ left: 50%;
174
+ translate: -50% 0;
175
+ padding-bottom: var(--mk-space-sm);
176
+ transform-origin: center bottom;
177
+ }
178
+ #scene-root .mk-v .mk-name {
179
+ text-align: center;
180
+ }
181
+
182
+ /* line */
183
+ #scene-root .mk-lines {
184
+ flex-direction: column;
185
+ gap: var(--mk-space-md);
186
+ }
187
+ #scene-root .mk-legend {
188
+ flex: none;
189
+ list-style: none;
190
+ padding: 0;
191
+ display: flex;
192
+ flex-wrap: wrap;
193
+ gap: var(--mk-space-lg);
194
+ font-size: var(--mk-font-size-md);
195
+ font-weight: 600;
196
+ }
197
+ #scene-root .mk-legend li {
198
+ display: flex;
199
+ align-items: center;
200
+ gap: var(--mk-space-md);
201
+ }
202
+ #scene-root .mk-key {
203
+ width: 40px;
204
+ height: 10px;
205
+ border-radius: var(--mk-radius-full);
206
+ background: var(--c);
207
+ }
208
+ #scene-root .mk-frame {
209
+ flex: 1;
210
+ min-height: 0;
211
+ display: grid;
212
+ grid-template-columns: var(--yw) minmax(0, 1fr);
213
+ grid-template-rows: minmax(0, 1fr) 56px;
214
+ }
215
+ #scene-root .mk-yaxis {
216
+ position: relative;
217
+ }
218
+ #scene-root .mk-tick {
219
+ position: absolute;
220
+ right: var(--mk-space-md);
221
+ translate: 0 50%;
222
+ font-size: var(--mk-font-size-sm);
223
+ font-variant-numeric: var(--mk-numeric, tabular-nums);
224
+ color: var(--mk-color-muted);
225
+ white-space: nowrap;
226
+ }
227
+ #scene-root .mk-plot {
228
+ position: relative;
229
+ margin-right: var(--mr);
230
+ }
231
+ #scene-root .mk-gls {
232
+ position: absolute;
233
+ inset: 0;
234
+ }
235
+ #scene-root .mk-gl {
236
+ position: absolute;
237
+ left: 0;
238
+ right: calc(var(--mr) * -1);
239
+ height: 2px;
240
+ background: var(--mk-color-divider);
241
+ }
242
+ #scene-root .mk-curve {
243
+ position: absolute;
244
+ inset: 0;
245
+ width: 100%;
246
+ height: 100%;
247
+ overflow: visible;
248
+ }
249
+ #scene-root .mk-stroke {
250
+ fill: none;
251
+ stroke: var(--c);
252
+ stroke-width: 7px;
253
+ stroke-linejoin: round;
254
+ stroke-linecap: round;
255
+ vector-effect: non-scaling-stroke;
256
+ }
257
+ #scene-root .mk-area {
258
+ fill: color-mix(in srgb, var(--c) 14%, transparent);
259
+ stroke: none;
260
+ }
261
+ #scene-root .mk-dot {
262
+ position: absolute;
263
+ width: 24px;
264
+ height: 24px;
265
+ translate: -50% 50%;
266
+ border-radius: var(--mk-radius-full);
267
+ background: var(--c);
268
+ border: 4px solid var(--mk-color-card);
269
+ box-sizing: border-box;
270
+ opacity: 0;
271
+ }
272
+ #scene-root .mk-pv {
273
+ position: absolute;
274
+ padding: 0 var(--mk-space-sm);
275
+ border-radius: var(--mk-radius-md);
276
+ background: color-mix(in srgb, var(--mk-color-card) 88%, transparent);
277
+ font-size: var(--mk-font-size-sm);
278
+ font-weight: 800;
279
+ font-variant-numeric: var(--mk-numeric, tabular-nums);
280
+ white-space: nowrap;
281
+ opacity: 0;
282
+ }
283
+ #scene-root .mk-above {
284
+ margin-bottom: 20px;
285
+ translate: -50% 0;
286
+ }
287
+ #scene-root .mk-right {
288
+ margin-left: 22px;
289
+ translate: 0 50%;
290
+ }
291
+ #scene-root .mk-xaxis {
292
+ grid-column: 2;
293
+ position: relative;
294
+ margin-right: var(--mr);
295
+ }
296
+ #scene-root .mk-xl {
297
+ position: absolute;
298
+ top: var(--mk-space-md);
299
+ translate: -50% 0;
300
+ font-size: var(--mk-font-size-sm);
301
+ color: var(--mk-color-muted);
302
+ white-space: nowrap;
303
+ }
304
+
305
+ /* donut */
306
+ #scene-root .mk-donut {
307
+ align-items: center;
308
+ justify-content: center;
309
+ gap: var(--mk-space-xxl);
310
+ }
311
+ #scene-root .mk-ring {
312
+ position: relative;
313
+ flex: none;
314
+ width: 640px;
315
+ height: 640px;
316
+ }
317
+ #scene-root .mk-ring svg {
318
+ width: 100%;
319
+ height: 100%;
320
+ }
321
+ #scene-root .mk-bg {
322
+ fill: none;
323
+ stroke: var(--mk-color-surface);
324
+ stroke-width: 17;
325
+ }
326
+ #scene-root .mk-arc {
327
+ fill: none;
328
+ stroke: var(--c);
329
+ stroke-width: 17;
330
+ stroke-dasharray: 0 100;
331
+ }
332
+ #scene-root .mk-arc.mk-lo {
333
+ opacity: 0.3;
334
+ }
335
+ #scene-root .mk-core {
336
+ position: absolute;
337
+ inset: 0;
338
+ display: flex;
339
+ flex-direction: column;
340
+ align-items: center;
341
+ justify-content: center;
342
+ gap: var(--mk-space-sm);
343
+ padding: 0 130px;
344
+ text-align: center;
345
+ }
346
+ #scene-root .mk-total {
347
+ font-family: var(--mk-font-display, var(--mk-font-sans));
348
+ display: inline-block;
349
+ font-size: var(--mk-font-size-xl);
350
+ font-weight: 800;
351
+ line-height: 1;
352
+ letter-spacing: -0.03em;
353
+ font-variant-numeric: var(--mk-numeric, tabular-nums);
354
+ }
355
+ #scene-root .mk-core-label {
356
+ font-size: var(--mk-font-size-sm);
357
+ font-weight: 600;
358
+ line-height: 1.15;
359
+ color: var(--mk-color-muted);
360
+ }
361
+ #scene-root .mk-legend-list {
362
+ flex: 1;
363
+ max-width: 760px;
364
+ list-style: none;
365
+ padding: 0;
366
+ display: flex;
367
+ flex-direction: column;
368
+ gap: var(--mk-space-sm);
369
+ }
370
+ #scene-root .mk-leg {
371
+ display: grid;
372
+ grid-template-columns: 28px minmax(0, 1fr) var(--vw) 112px;
373
+ align-items: center;
374
+ column-gap: var(--mk-space-md);
375
+ padding: var(--mk-space-sm) var(--mk-space-md);
376
+ border-radius: var(--mk-radius-lg);
377
+ font-size: var(--mk-font-size-md);
378
+ }
379
+ #scene-root .mk-donut.mk-nopct .mk-leg {
380
+ grid-template-columns: 28px minmax(0, 1fr) var(--vw);
381
+ }
382
+ #scene-root .mk-donut.mk-noval .mk-leg {
383
+ grid-template-columns: 28px minmax(0, 1fr);
384
+ }
385
+ #scene-root .mk-leg.mk-hi {
386
+ background: var(--mk-color-accentSoft);
387
+ font-weight: 800;
388
+ }
389
+ #scene-root .mk-sw {
390
+ width: 28px;
391
+ height: 28px;
392
+ border-radius: var(--mk-radius-md);
393
+ background: var(--c);
394
+ }
395
+ #scene-root .mk-lname {
396
+ font-weight: 600;
397
+ line-height: 1.15;
398
+ text-wrap: balance;
399
+ }
400
+ #scene-root .mk-leg.mk-hi .mk-lname {
401
+ font-weight: 800;
402
+ }
403
+ #scene-root .mk-lval {
404
+ display: inline-block;
405
+ transform-origin: right center;
406
+ text-align: right;
407
+ font-weight: 700;
408
+ font-variant-numeric: var(--mk-numeric, tabular-nums);
409
+ white-space: nowrap;
410
+ }
411
+ #scene-root .mk-pct {
412
+ text-align: right;
413
+ font-size: var(--mk-font-size-sm);
414
+ font-variant-numeric: var(--mk-numeric, tabular-nums);
415
+ color: var(--mk-color-muted);
416
+ }
417
+
418
+ /* 7-8 slices: tighter legend rows */
419
+ #scene-root .mk-donut.mk-dense .mk-legend-list {
420
+ gap: var(--mk-space-xs);
421
+ }
422
+ #scene-root .mk-donut.mk-dense .mk-leg {
423
+ padding: var(--mk-space-xs) var(--mk-space-md);
424
+ font-size: var(--mk-font-size-sm);
425
+ }
@@ -0,0 +1 @@
1
+ export declare const codeScene: import("@anvpx/motion-schema").ScenePlugin;
@@ -0,0 +1,109 @@
1
+ import { z } from "zod";
2
+ import { defineScene } from "../../define-scene.js";
3
+ import { animAttrs, esc } from "../../html.js";
4
+ import { readText } from "../../text-file.js";
5
+ import { text } from "../../words.js";
6
+ import { tokenize } from "./tokenize.js";
7
+ const MAX_LINES = 14;
8
+ const MAX_COLS = 60;
9
+ const MONO_EM = 0.62;
10
+ const LINE_EM = 1.6;
11
+ /** Window padding, title bar and the frame's safe margin, in px. */
12
+ const WINDOW_PAD = 96;
13
+ const BAR_PX = 110;
14
+ const SAFE = 0.1;
15
+ /** A wrapped line may take this many rows before the text shrinks instead. */
16
+ const MAX_WRAP_ROWS = 2;
17
+ const configSchema = z
18
+ .strictObject({
19
+ lines: z
20
+ .array(text.max(MAX_COLS).regex(/^[^\r\n]*$/, "one line per item"))
21
+ .min(1, `need 1-${MAX_LINES} lines`)
22
+ .max(MAX_LINES, `need 1-${MAX_LINES} lines`),
23
+ lang: z.enum(["js", "ts", "json", "py", "sh", "plain"]).default("plain"),
24
+ reveal: z.enum(["type", "lines"]).default("lines"),
25
+ highlight: z.array(z.int().min(1)).max(MAX_LINES).optional(),
26
+ file: text.max(40).optional(),
27
+ })
28
+ .superRefine((props, ctx) => {
29
+ props.highlight?.forEach((line, index) => {
30
+ if (line > props.lines.length) {
31
+ ctx.addIssue({
32
+ code: "custom",
33
+ path: ["highlight", index],
34
+ message: `line ${line} does not exist; lines are numbered 1-${props.lines.length}`,
35
+ });
36
+ }
37
+ });
38
+ });
39
+ /** Lines starting with + or - are diff lines: the sign moves to its own column. */
40
+ const rowOf = (line) => {
41
+ const sign = line.startsWith("+") ? "+" : line.startsWith("-") ? "-" : "";
42
+ const rest = sign === "" ? line : line.slice(1).replace(/^ /, "");
43
+ return { sign, code: rest.replaceAll("\t", " ") };
44
+ };
45
+ const spans = (code, lang) => tokenize(code, lang)
46
+ .map((token) => token.kind === "plain"
47
+ ? esc(token.text)
48
+ : `<span class="mk-t-${token.kind}">${esc(token.text)}</span>`)
49
+ .join("");
50
+ const SIGN_CLASS = { "+": " mk-add", "-": " mk-del", "": "" };
51
+ const lineHtml = (row, index, props, numbered) => {
52
+ const hl = props.highlight?.includes(index + 1) ? " mk-hl" : "";
53
+ const length = [...row.code].length;
54
+ const number = numbered ? String(index + 1) : "";
55
+ return `<div class="mk-line${SIGN_CLASS[row.sign]}${hl}" data-len="${length}">
56
+ <span class="mk-num" aria-hidden="true">${number}</span><span class="mk-sign" aria-hidden="true">${row.sign}</span><span class="mk-code"><span class="mk-text">${spans(row.code, props.lang)}</span><span class="mk-caret" aria-hidden="true"></span></span>
57
+ </div>`;
58
+ };
59
+ /** Rows a line takes when it wraps at `usable` px of `px`-sized monospace text. */
60
+ const rowsOf = (row, numbered, px, usable) => {
61
+ const perRow = Math.max(1, Math.floor(usable / (MONO_EM * px)) - (numbered ? 5 : 2));
62
+ return Math.max(1, Math.ceil([...row.code].length / perRow));
63
+ };
64
+ /**
65
+ * Largest theme code size at which every line fits the frame unwrapped; failing that, the largest
66
+ * size at which the lines fit once long ones wrap (text never drops below the smallest step).
67
+ */
68
+ const sizeClass = (rows, numbered, ctx) => {
69
+ const widest = Math.max(...rows.map((row) => [...row.code].length));
70
+ const cols = widest + (numbered ? 5 : 2);
71
+ const sizes = ["lg", "md", "sm"];
72
+ const usableW = ctx.width * (1 - SAFE) - WINDOW_PAD;
73
+ const usableH = ctx.height * (1 - SAFE) - WINDOW_PAD;
74
+ const stack = (step, wrapped) => {
75
+ const px = ctx.theme.fontSizes[step] ?? 0;
76
+ const counts = rows.map((row) => (wrapped ? rowsOf(row, numbered, px, usableW) : 1));
77
+ const lines = counts.reduce((sum, count) => sum + count, 0);
78
+ return Math.max(...counts) <= MAX_WRAP_ROWS && lines * LINE_EM * px + BAR_PX <= usableH;
79
+ };
80
+ const plain = sizes.find((step) => cols * MONO_EM * (ctx.theme.fontSizes[step] ?? 0) <= usableW && stack(step, false));
81
+ if (plain)
82
+ return `mk-size-${plain}`;
83
+ return `mk-size-${sizes.find((step) => stack(step, true)) ?? "sm"} mk-wrap`;
84
+ };
85
+ const render = (props, ctx) => {
86
+ const rows = props.lines.map(rowOf);
87
+ const numbered = props.lang !== "sh";
88
+ const file = props.file ? `<span class="mk-file">${esc(props.file)}</span>` : "";
89
+ const dots = '<span class="mk-dots" aria-hidden="true"><i></i><i></i><i></i></span>';
90
+ const body = rows.map((row, index) => lineHtml(row, index, props, numbered)).join("\n");
91
+ const hasHighlight = (props.highlight?.length ?? 0) > 0;
92
+ return `<div class="mk-window ${sizeClass(rows, numbered, ctx)}${numbered ? "" : " mk-bare"}" ${animAttrs("rise", 0, "code")}>
93
+ <div class="mk-bar">${dots}${file}</div>
94
+ <div class="mk-body" data-reveal="${props.reveal}" data-dim="${hasHighlight ? 1 : 0}">
95
+ ${body}
96
+ </div>
97
+ </div>`;
98
+ };
99
+ export const codeScene = defineScene({
100
+ type: "code",
101
+ configSchema,
102
+ meta: {
103
+ purpose: "Code or terminal text typed or revealed line by line, with highlighted lines and +/- diff lines.",
104
+ example: { lines: ["const total = price * 2", "- old line", "+ new line"], lang: "js" },
105
+ },
106
+ style: readText("./style.css", import.meta.url),
107
+ script: readText("./scene.js", import.meta.url),
108
+ render: (props, ctx) => ({ body: render(props, ctx) }),
109
+ });
@@ -0,0 +1,2 @@
1
+ /** @type {import("../../runtime/mount.js").CreateScene} */
2
+ export declare function createScene(root: HTMLElement, config: import("../../runtime/mount.js").SceneConfig, ctx: import("../../runtime/mount.js").RuntimeContext): import("../../runtime/mount.js").Runtime;
@@ -0,0 +1,108 @@
1
+ // @ts-check
2
+ import { clamp01, ease } from "../../runtime/easing.js";
3
+ import { mountTimeline } from "../../runtime/mount.js";
4
+ const START = 0.7;
5
+ const TYPE_CHARS_PER_SECOND = 26;
6
+ const MIN_SPAN = 1;
7
+ const SPAN_SHARE = 0.6;
8
+ const LINE_STEP = 0.45;
9
+ const FADE = 0.35;
10
+ const DIM_AFTER = 0.3;
11
+ const DIM_SECONDS = 0.5;
12
+ const DIM_FLOOR = 0.6;
13
+ const BLINK_HZ = 2.2;
14
+ /**
15
+ * @param {number} t
16
+ * @param {number} from
17
+ * @param {number} to
18
+ */
19
+ const within = (t, from, to) => clamp01(to > from ? (t - from) / (to - from) : t >= from ? 1 : 0);
20
+ /** @type {import("../../runtime/mount.js").CreateScene} */
21
+ export function createScene(root, config, ctx) {
22
+ const inner = mountTimeline(root, config, ctx, { baseDelay: 0.2, staggerFrames: 4, rise: 32 });
23
+ const body = /** @type {HTMLElement} */ (root.querySelector(".mk-body"));
24
+ const typing = body.dataset.reveal === "type";
25
+ const dims = body.dataset.dim === "1";
26
+ const duration = ctx.duration ?? (Number(root.dataset.duration) || 6);
27
+ const rows = Array.from(body.querySelectorAll(".mk-line"), (node) => {
28
+ const el = /** @type {HTMLElement} */ (node);
29
+ return {
30
+ el,
31
+ text: /** @type {HTMLElement} */ (el.querySelector(".mk-text")),
32
+ caret: /** @type {HTMLElement} */ (el.querySelector(".mk-caret")),
33
+ len: Number(el.dataset.len),
34
+ lit: el.classList.contains("mk-hl"),
35
+ };
36
+ });
37
+ const total = rows.reduce((sum, row) => sum + row.len, 0);
38
+ const span = typing
39
+ ? Math.max(MIN_SPAN, Math.min(total / TYPE_CHARS_PER_SECOND, duration * SPAN_SHARE - START))
40
+ : Math.max(MIN_SPAN, Math.min(rows.length * LINE_STEP, duration * SPAN_SHARE - START));
41
+ const revealEnd = START + span;
42
+ /** @param {number} index */
43
+ const lengthBefore = (index) => rows.slice(0, index).reduce((sum, row) => sum + row.len, 0);
44
+ /**
45
+ * @param {typeof rows[number]} row
46
+ * @param {number} dim 0..1 progress of dimming the lines that are not highlighted
47
+ */
48
+ const keepOf = (row, dim) => (dims && !row.lit ? 1 - (1 - DIM_FLOOR) * ease("out", dim) : 1);
49
+ /**
50
+ * @param {typeof rows[number]} row
51
+ * @param {number} i
52
+ * @param {number} t
53
+ * @param {number} dim
54
+ * @param {number} shown characters of this row that are typed
55
+ */
56
+ const paintRow = (row, i, t, dim, shown) => {
57
+ const from = START + (i * span) / rows.length;
58
+ const lineIn = typing ? 1 : ease("out", within(t, from, from + FADE));
59
+ row.el.style.opacity = String(lineIn * keepOf(row, dim));
60
+ row.el.style.transform = typing ? "" : `translateY(${(1 - lineIn) * 14}px)`;
61
+ const ratio = row.len === 0 ? 1 : shown / row.len;
62
+ row.text.style.clipPath = typing ? `inset(0 ${(1 - ratio) * 100}% 0 0)` : "";
63
+ row.caret.style.opacity = "0";
64
+ };
65
+ /**
66
+ * @param {number} t
67
+ * @param {number} typed characters typed so far across all rows
68
+ * @param {number} active index of the row being typed, -1 when none
69
+ */
70
+ const paintCaret = (t, typed, active) => {
71
+ const done = t >= START && active < 0;
72
+ const at = done ? rows.length - 1 : Math.max(active, 0);
73
+ const row = rows[at];
74
+ if (!row)
75
+ return;
76
+ row.caret.style.left = `${done ? row.len : Math.round(typed - lengthBefore(at))}ch`;
77
+ row.caret.style.opacity = done && Math.floor(t * BLINK_HZ) % 2 === 1 ? "0" : "1";
78
+ };
79
+ /** @param {number} t */
80
+ const seek = (t) => {
81
+ inner.seek(t);
82
+ const typed = total * within(t, START, revealEnd);
83
+ const dim = dims ? within(t, revealEnd + DIM_AFTER, revealEnd + DIM_AFTER + DIM_SECONDS) : 0;
84
+ let before = 0;
85
+ let active = -1;
86
+ rows.forEach((row, i) => {
87
+ const shown = Math.min(row.len, Math.max(0, typed - before));
88
+ before += row.len;
89
+ if (active < 0 && shown < row.len && t >= START)
90
+ active = i;
91
+ paintRow(row, i, t, dim, shown);
92
+ });
93
+ if (typing)
94
+ paintCaret(t, typed, active);
95
+ };
96
+ const dispose = () => {
97
+ inner.dispose();
98
+ for (const row of rows) {
99
+ row.el.style.removeProperty("opacity");
100
+ row.el.style.removeProperty("transform");
101
+ row.text.style.removeProperty("clip-path");
102
+ row.caret.style.removeProperty("opacity");
103
+ row.caret.style.removeProperty("left");
104
+ }
105
+ };
106
+ seek(0);
107
+ return { seek, dispose, ready: inner.ready };
108
+ }