@vanillaskyai/video 0.9.0 → 0.10.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 (39) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/{builtin-server-HW6HGXCZ.js → builtin-server-W4PLJUZ5.js} +2 -2
  3. package/dist/check-runtime.js +2 -2
  4. package/dist/{chunk-UDIODEDK.js → chunk-224QNWRA.js} +5 -1
  5. package/dist/{chunk-OR52UMSF.js → chunk-2HFO22K2.js} +2 -1
  6. package/dist/{chunk-MXEYPK7M.js → chunk-4ZJLPHBV.js} +194 -62
  7. package/dist/{chunk-3ZTEFJIR.js → chunk-ELVOT2FQ.js} +1 -1
  8. package/dist/{chunk-LH4BPALA.js → chunk-IIN5M5HW.js} +194 -61
  9. package/dist/{chunk-MQILEEXC.js → chunk-IR44XKBI.js} +1 -1
  10. package/dist/{chunk-G7IZBBWF.js → chunk-NMFDC2W2.js} +3 -10
  11. package/dist/chunk-XX4GXKTX.js +35 -0
  12. package/dist/chunk-Z67Q5KUW.js +16 -0
  13. package/dist/{cinema-media-YQHSIFDA.js → cinema-media-C7OUPNSH.js} +3 -2
  14. package/dist/cli.js +3 -3
  15. package/dist/{comparison-RZMMHZR2.js → comparison-GNZOR7MF.js} +14 -4
  16. package/dist/{editorial-timeline-OZX7OS6G.js → editorial-timeline-EMV5335S.js} +10 -3
  17. package/dist/key-figure-P37VK425.js +30 -0
  18. package/dist/{mobile-message-UZUPIKHD.js → mobile-message-OF7T62B7.js} +3 -2
  19. package/dist/{preload-media-CFTZIMZL.js → preload-media-LJXWKTWG.js} +1 -1
  20. package/dist/quote-T6WYLN7A.js +33 -0
  21. package/dist/react.js +29 -27
  22. package/dist/server.js +97 -19
  23. package/dist/template-catalog.d.ts +154 -19
  24. package/dist/template-catalog.js +1 -1
  25. package/dist/test.js +1 -1
  26. package/docs/customization.md +1 -1
  27. package/docs/maintainers/cinematic-migration.md +4 -0
  28. package/docs/media-and-audio.md +3 -3
  29. package/docs/provider-integration.md +1 -1
  30. package/package.json +1 -1
  31. package/registry/items/comparison.json +71 -4
  32. package/registry/items/editorialTimeline.json +71 -4
  33. package/registry/items/keyFigure.json +69 -4
  34. package/registry/items/quote.json +71 -4
  35. package/starters/video-chat/package.json +1 -1
  36. package/dist/focus-cards-TJ72BT7U.js +0 -20
  37. package/dist/key-figure-GYENXKH3.js +0 -20
  38. package/dist/quote-EW5HQA6H.js +0 -23
  39. package/registry/items/focusCards.json +0 -90
@@ -135,62 +135,9 @@ var GENERATED_BUILTIN_TEMPLATE_CATALOG = [
135
135
  "additionalProperties": false
136
136
  }
137
137
  },
138
- {
139
- "label": "Focus cards",
140
- "description": "Two to four short phrases fade in sequentially on black; no boxes or heading.",
141
- "usesGlobalTextEffect": false,
142
- "usesGlobalTransition": false,
143
- "usesGlobalBackgroundEffect": false,
144
- "textCanvas": "tight",
145
- "id": "focusCards",
146
- "family": "Explainers",
147
- "jobs": [
148
- "setup",
149
- "proof"
150
- ],
151
- "register": "card-led",
152
- "useWhen": "Two to four short parallel points support an explanation. ",
153
- "avoidWhen": "The points require an order, long paragraphs, numerical data or additional images to make sense.",
154
- "minDuration": 4,
155
- "preferredDuration": 5,
156
- "timing": {
157
- "contentFields": [
158
- "items"
159
- ],
160
- "contentUnit": "items",
161
- "revealSeconds": 2.4,
162
- "holdSeconds": 1.8,
163
- "exitSeconds": 0
164
- },
165
- "schema": {
166
- "type": "object",
167
- "properties": {
168
- "items": {
169
- "type": "array",
170
- "minItems": 2,
171
- "maxItems": 4,
172
- "items": {
173
- "type": "string",
174
- "minLength": 1,
175
- "maxLength": 55
176
- },
177
- "default": [
178
- "Listen closely",
179
- "Notice the pattern",
180
- "Make room for change"
181
- ],
182
- "description": "2\u20134 parallel phrases, about 2\u20136 words each; no heading or numbering."
183
- }
184
- },
185
- "required": [
186
- "items"
187
- ],
188
- "additionalProperties": false
189
- }
190
- },
191
138
  {
192
139
  "label": "Timeline",
193
- "description": "Three to five events on a fine continuous line on black; without dates.",
140
+ "description": "Three to five events on a fine continuous line over relevant media or black; without dates.",
194
141
  "usesGlobalTextEffect": false,
195
142
  "usesGlobalTransition": false,
196
143
  "usesGlobalBackgroundEffect": false,
@@ -248,12 +195,59 @@ var GENERATED_BUILTIN_TEMPLATE_CATALOG = [
248
195
  }
249
196
  ],
250
197
  "description": "3\u20135 ordered events or actions, each with one short label; no dates."
198
+ },
199
+ "mediaKeyword": {
200
+ "type": "string",
201
+ "format": "stock-media-keyword",
202
+ "minLength": 1,
203
+ "maxLength": 80,
204
+ "description": "2\u20138 word literal subject/action search intent, maximum 80 characters. Host resolves URLs.",
205
+ "examples": [
206
+ "Ocean waves breaking on a rocky shore"
207
+ ]
208
+ },
209
+ "mediaUrl": {
210
+ "type": "string",
211
+ "format": "uri",
212
+ "description": "Host-only approved photo or video URL.",
213
+ "default": ""
214
+ },
215
+ "mediaType": {
216
+ "type": "string",
217
+ "enum": [
218
+ "photo",
219
+ "video"
220
+ ],
221
+ "default": "video",
222
+ "description": "Host-resolved asset kind."
223
+ },
224
+ "mediaPoster": {
225
+ "type": "string",
226
+ "format": "uri",
227
+ "description": "Host-only approved poster URL for video decoding.",
228
+ "default": ""
229
+ },
230
+ "shotDirection": {
231
+ "type": "string",
232
+ "maxLength": 220,
233
+ "description": "Optional action, framing and continuity for generation. Preserve the subject; do not request rendered text."
234
+ },
235
+ "mediaSource": {
236
+ "type": "string",
237
+ "enum": [
238
+ "generate",
239
+ "stock"
240
+ ],
241
+ "description": "Generate distinctive illustrative shots; use approved stock for familiar observable subjects."
251
242
  }
252
243
  },
253
244
  "required": [
254
245
  "events"
255
246
  ],
256
- "additionalProperties": false
247
+ "additionalProperties": false,
248
+ "x-vanillasky": {
249
+ "allowsStockMedia": true
250
+ }
257
251
  }
258
252
  },
259
253
  {
@@ -354,7 +348,7 @@ var GENERATED_BUILTIN_TEMPLATE_CATALOG = [
354
348
  },
355
349
  {
356
350
  "label": "Comparison",
357
- "description": "Two short statements with equal weight on black, side by side or stacked in portrait.",
351
+ "description": "Two short statements with equal weight over relevant media or black, side by side or stacked in portrait.",
358
352
  "usesGlobalTextEffect": false,
359
353
  "usesGlobalTransition": false,
360
354
  "usesGlobalBackgroundEffect": false,
@@ -407,18 +401,65 @@ var GENERATED_BUILTIN_TEMPLATE_CATALOG = [
407
401
  "maxLength": 60,
408
402
  "default": "More room to think",
409
403
  "description": "Second real alternative, parallel to the first."
404
+ },
405
+ "mediaKeyword": {
406
+ "type": "string",
407
+ "format": "stock-media-keyword",
408
+ "minLength": 1,
409
+ "maxLength": 80,
410
+ "description": "2\u20138 word literal subject/action search intent, maximum 80 characters. Host resolves URLs.",
411
+ "examples": [
412
+ "Ocean waves breaking on a rocky shore"
413
+ ]
414
+ },
415
+ "mediaUrl": {
416
+ "type": "string",
417
+ "format": "uri",
418
+ "description": "Host-only approved photo or video URL.",
419
+ "default": ""
420
+ },
421
+ "mediaType": {
422
+ "type": "string",
423
+ "enum": [
424
+ "photo",
425
+ "video"
426
+ ],
427
+ "default": "video",
428
+ "description": "Host-resolved asset kind."
429
+ },
430
+ "mediaPoster": {
431
+ "type": "string",
432
+ "format": "uri",
433
+ "description": "Host-only approved poster URL for video decoding.",
434
+ "default": ""
435
+ },
436
+ "shotDirection": {
437
+ "type": "string",
438
+ "maxLength": 220,
439
+ "description": "Optional action, framing and continuity for generation. Preserve the subject; do not request rendered text."
440
+ },
441
+ "mediaSource": {
442
+ "type": "string",
443
+ "enum": [
444
+ "generate",
445
+ "stock"
446
+ ],
447
+ "description": "Generate distinctive illustrative shots; use approved stock for familiar observable subjects."
410
448
  }
411
449
  },
412
450
  "required": [
413
451
  "leftText",
414
452
  "rightText"
415
453
  ],
416
- "additionalProperties": false
454
+ "additionalProperties": false,
455
+ "x-vanillasky": {
456
+ "allowsStockMedia": true
457
+ }
417
458
  }
418
459
  },
419
460
  {
420
461
  "label": "Quote",
421
- "description": "A short exact quotation with a legible attribution on black.",
462
+ "description": "A short exact quotation with a legible attribution over relevant media or black.",
422
463
  "usesGlobalTextEffect": false,
423
464
  "usesGlobalTransition": false,
424
465
  "usesGlobalBackgroundEffect": false,
@@ -464,18 +505,65 @@ var GENERATED_BUILTIN_TEMPLATE_CATALOG = [
464
505
  "Illustrative example"
465
506
  ],
466
507
  "description": "Grounded attribution belonging to these exact quoted words."
508
+ },
509
+ "mediaKeyword": {
510
+ "type": "string",
511
+ "format": "stock-media-keyword",
512
+ "minLength": 1,
513
+ "maxLength": 80,
514
+ "description": "2\u20138 word literal subject/action search intent, maximum 80 characters. Host resolves URLs.",
515
+ "examples": [
516
+ "Ocean waves breaking on a rocky shore"
517
+ ]
518
+ },
519
+ "mediaUrl": {
520
+ "type": "string",
521
+ "format": "uri",
522
+ "description": "Host-only approved photo or video URL.",
523
+ "default": ""
524
+ },
525
+ "mediaType": {
526
+ "type": "string",
527
+ "enum": [
528
+ "photo",
529
+ "video"
530
+ ],
531
+ "default": "video",
532
+ "description": "Host-resolved asset kind."
533
+ },
534
+ "mediaPoster": {
535
+ "type": "string",
536
+ "format": "uri",
537
+ "description": "Host-only approved poster URL for video decoding.",
538
+ "default": ""
539
+ },
540
+ "shotDirection": {
541
+ "type": "string",
542
+ "maxLength": 220,
543
+ "description": "Optional action, framing and continuity for generation. Preserve the subject; do not request rendered text."
544
+ },
545
+ "mediaSource": {
546
+ "type": "string",
547
+ "enum": [
548
+ "generate",
549
+ "stock"
550
+ ],
551
+ "description": "Generate distinctive illustrative shots; use approved stock for familiar observable subjects."
467
552
  }
468
553
  },
469
554
  "required": [
470
555
  "quote",
471
556
  "attribution"
472
557
  ],
473
- "additionalProperties": false
558
+ "additionalProperties": false,
559
+ "x-vanillasky": {
560
+ "allowsStockMedia": true
561
+ }
474
562
  }
475
563
  },
476
564
  {
477
565
  "label": "Key figure",
478
- "description": "One supplied figure with one short label on black.",
566
+ "description": "One supplied figure with one short label over relevant media or black.",
479
567
  "usesGlobalTextEffect": false,
480
568
  "usesGlobalTransition": false,
481
569
  "usesGlobalBackgroundEffect": false,
@@ -521,6 +609,50 @@ var GENERATED_BUILTIN_TEMPLATE_CATALOG = [
521
609
  "Illustrative example"
522
610
  ],
523
611
  "description": "Exactly one short label identifying the quantity and its context."
612
+ },
613
+ "mediaKeyword": {
614
+ "type": "string",
615
+ "format": "stock-media-keyword",
616
+ "minLength": 1,
617
+ "maxLength": 80,
618
+ "description": "2\u20138 word literal subject/action search intent, maximum 80 characters. Host resolves URLs.",
619
+ "examples": [
620
+ "Ocean waves breaking on a rocky shore"
621
+ ]
622
+ },
623
+ "mediaUrl": {
624
+ "type": "string",
625
+ "format": "uri",
626
+ "description": "Host-only approved photo or video URL.",
627
+ "default": ""
628
+ },
629
+ "mediaType": {
630
+ "type": "string",
631
+ "enum": [
632
+ "photo",
633
+ "video"
634
+ ],
635
+ "default": "video",
636
+ "description": "Host-resolved asset kind."
637
+ },
638
+ "mediaPoster": {
639
+ "type": "string",
640
+ "format": "uri",
641
+ "description": "Host-only approved poster URL for video decoding.",
642
+ "default": ""
643
+ },
644
+ "shotDirection": {
645
+ "type": "string",
646
+ "maxLength": 220,
647
+ "description": "Optional action, framing and continuity for generation. Preserve the subject; do not request rendered text."
648
+ },
649
+ "mediaSource": {
650
+ "type": "string",
651
+ "enum": [
652
+ "generate",
653
+ "stock"
654
+ ],
655
+ "description": "Generate distinctive illustrative shots; use approved stock for familiar observable subjects."
524
656
  }
525
657
  },
526
658
  "required": [
@@ -529,7 +661,8 @@ var GENERATED_BUILTIN_TEMPLATE_CATALOG = [
529
661
  ],
530
662
  "additionalProperties": false,
531
663
  "x-vanillasky": {
532
- "requiresStat": true
664
+ "requiresStat": true,
665
+ "allowsStockMedia": true
533
666
  }
534
667
  }
535
668
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BUILTIN_TEMPLATE_CATALOG
3
- } from "./chunk-LH4BPALA.js";
3
+ } from "./chunk-IIN5M5HW.js";
4
4
  import {
5
5
  assertTemplateTransitionMetadata
6
6
  } from "./chunk-2E6T633S.js";
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-77VY4O7A.js";
7
7
  import {
8
8
  resolveMediaType
9
- } from "./chunk-UDIODEDK.js";
9
+ } from "./chunk-224QNWRA.js";
10
10
  import {
11
11
  useExternalVideoBackdrop
12
12
  } from "./chunk-TVIU23OM.js";
@@ -195,14 +195,7 @@ var SceneBackground = ({
195
195
  ] });
196
196
  };
197
197
 
198
- // src/visual-system/scene-templates/cinema-media.tsx
199
- import { jsx as jsx2 } from "react/jsx-runtime";
200
- function MediaScene({ variables, style, width, height, progress, sceneDuration, isPlaying }) {
201
- return /* @__PURE__ */ jsx2("div", { "data-template": "cinemaMedia", style: { width, height, position: "relative", overflow: "hidden" }, children: /* @__PURE__ */ jsx2(SceneBackground, { style, width, height, progress, sceneDuration, ...getMediaBackgroundProps(variables), mediaTreatment: "none", backgroundEffect: "none", isPlaying }) });
202
- }
203
- var MediaSceneTemplate = MediaScene;
204
-
205
198
  export {
206
- MediaScene,
207
- MediaSceneTemplate
199
+ getMediaBackgroundProps,
200
+ SceneBackground
208
201
  };
@@ -0,0 +1,35 @@
1
+ import {
2
+ SceneBackground,
3
+ getMediaBackgroundProps
4
+ } from "./chunk-NMFDC2W2.js";
5
+ import {
6
+ editorialFont
7
+ } from "./chunk-4YM2M62S.js";
8
+ import {
9
+ hasSceneMedia
10
+ } from "./chunk-224QNWRA.js";
11
+
12
+ // src/visual-system/scene-templates/editorial-background.tsx
13
+ import { jsx, jsxs } from "react/jsx-runtime";
14
+ function EditorialSurface({ children, template, ...props }) {
15
+ const { variables, style, width, height, progress, sceneDuration, isPlaying } = props;
16
+ const overMedia = hasSceneMedia(variables), u = Math.min(width, height);
17
+ const surface = {
18
+ position: "absolute",
19
+ inset: 0,
20
+ overflow: "hidden",
21
+ background: overMedia ? "var(--vanillasky-template-surface, #000)" : "#000",
22
+ fontFamily: editorialFont,
23
+ color: "#fff",
24
+ // Two soft, scale-aware shadows preserve local contrast without outlining type.
25
+ textShadow: overMedia ? `0 ${u * 2e-3}px ${u * 8e-3}px rgba(0,0,0,.65), 0 ${u * 6e-3}px ${u * 0.016}px rgba(0,0,0,.4)` : void 0
26
+ };
27
+ return /* @__PURE__ */ jsxs("div", { "data-template": template, style: surface, children: [
28
+ overMedia && /* @__PURE__ */ jsx(SceneBackground, { style, width, height, progress, sceneDuration, ...getMediaBackgroundProps(variables), mediaTreatment: "cinematic", textAnchor: "center", backgroundEffect: "none", isPlaying }),
29
+ children
30
+ ] });
31
+ }
32
+
33
+ export {
34
+ EditorialSurface
35
+ };
@@ -0,0 +1,16 @@
1
+ import {
2
+ SceneBackground,
3
+ getMediaBackgroundProps
4
+ } from "./chunk-NMFDC2W2.js";
5
+
6
+ // src/visual-system/scene-templates/cinema-media.tsx
7
+ import { jsx } from "react/jsx-runtime";
8
+ function MediaScene({ variables, style, width, height, progress, sceneDuration, isPlaying }) {
9
+ return /* @__PURE__ */ jsx("div", { "data-template": "cinemaMedia", style: { width, height, position: "relative", overflow: "hidden" }, children: /* @__PURE__ */ jsx(SceneBackground, { style, width, height, progress, sceneDuration, ...getMediaBackgroundProps(variables), mediaTreatment: "none", backgroundEffect: "none", isPlaying }) });
10
+ }
11
+ var MediaSceneTemplate = MediaScene;
12
+
13
+ export {
14
+ MediaScene,
15
+ MediaSceneTemplate
16
+ };
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  MediaScene,
3
3
  MediaSceneTemplate
4
- } from "./chunk-G7IZBBWF.js";
4
+ } from "./chunk-Z67Q5KUW.js";
5
+ import "./chunk-NMFDC2W2.js";
5
6
  import "./chunk-77VY4O7A.js";
6
- import "./chunk-UDIODEDK.js";
7
+ import "./chunk-224QNWRA.js";
7
8
  import "./chunk-TVIU23OM.js";
8
9
  export {
9
10
  MediaScene,
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-OR52UMSF.js";
2
+ import "./chunk-2HFO22K2.js";
3
3
  import "./chunk-PAJ44TFW.js";
4
4
  import {
5
5
  isTemplatePropertyFormatSupported,
@@ -8,14 +8,14 @@ import {
8
8
  import {
9
9
  getBuiltinTemplateMetadata,
10
10
  listBuiltinTemplateMetadata
11
- } from "./chunk-LH4BPALA.js";
11
+ } from "./chunk-IIN5M5HW.js";
12
12
  import "./chunk-3O7OMMMF.js";
13
13
  import {
14
14
  assertTemplateTransitionMetadata
15
15
  } from "./chunk-2E6T633S.js";
16
16
  import {
17
17
  BUILTIN_TEMPLATE_MANIFEST
18
- } from "./chunk-MXEYPK7M.js";
18
+ } from "./chunk-4ZJLPHBV.js";
19
19
  import {
20
20
  externalVideoBackdropCapabilitySource
21
21
  } from "./chunk-R3XAOMKP.js";
@@ -1,22 +1,32 @@
1
1
  import {
2
- editorialFont,
2
+ EditorialSurface
3
+ } from "./chunk-XX4GXKTX.js";
4
+ import "./chunk-NMFDC2W2.js";
5
+ import "./chunk-77VY4O7A.js";
6
+ import {
3
7
  editorialLabel,
4
8
  fade
5
9
  } from "./chunk-4YM2M62S.js";
10
+ import {
11
+ hasSceneMedia
12
+ } from "./chunk-224QNWRA.js";
13
+ import "./chunk-TVIU23OM.js";
6
14
 
7
15
  // src/visual-system/scene-templates/comparison.tsx
8
16
  import { jsx, jsxs } from "react/jsx-runtime";
9
- function ComparisonScene({ variables, width, height, progress, motionProgress = progress, safeZone }) {
17
+ function ComparisonScene(props) {
18
+ const { variables, width, height, progress, motionProgress = progress, safeZone } = props;
19
+ const overMedia = hasSceneMedia(variables);
10
20
  const portrait = height > width, u = Math.min(width, height);
11
21
  const side = Math.max(width * 0.12, safeZone.left, safeZone.right);
12
22
  const top = Math.max(height * 0.2, safeZone.top), bottom = height - Math.max(height * 0.23, safeZone.bottom);
13
23
  const area = bottom - top, cy = (top + bottom) / 2, available = width - side * 2;
14
24
  const entries = [{ label: String(variables.leftLabel ?? ""), text: String(variables.leftText ?? "") }, { label: String(variables.rightLabel ?? ""), text: String(variables.rightText ?? "") }];
15
25
  const textWidth = portrait ? available : available * 0.39;
16
- return /* @__PURE__ */ jsxs("div", { "data-template": "comparison", style: { position: "absolute", inset: 0, background: "#000", color: "#fff", fontFamily: editorialFont, overflow: "hidden" }, children: [
26
+ return /* @__PURE__ */ jsxs(EditorialSurface, { ...props, template: "comparison", children: [
17
27
  /* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { position: "absolute", left: portrait ? width * 0.32 : width / 2, top: portrait ? cy : top + area * 0.18, width: portrait ? width * 0.36 : u * 1e-3, height: portrait ? u * 1e-3 : area * 0.64, background: "#fff", opacity: 0.22 * fade((motionProgress - 0.16) / 0.18) } }),
18
28
  entries.map((entry, i) => /* @__PURE__ */ jsxs("div", { "data-comparison-side": i === 0 ? "left" : "right", style: { position: "absolute", left: portrait ? side : side + available * (i === 0 ? 0.055 : 0.555), top: portrait ? top + area * (i === 0 ? 0.25 : 0.75) : cy, width: textWidth, transform: "translateY(-50%)", textAlign: "center", opacity: fade((motionProgress - 0.04 - i * 0.22) / 0.2) }, children: [
19
- entry.label && /* @__PURE__ */ jsx("div", { style: { ...editorialLabel(u), marginBottom: u * 0.028 }, children: entry.label }),
29
+ entry.label && /* @__PURE__ */ jsx("div", { style: { ...editorialLabel(u), color: overMedia ? "#fff" : "#b7b7bc", marginBottom: u * 0.028 }, children: entry.label }),
20
30
  /* @__PURE__ */ jsx("div", { style: { fontSize: u * 0.058, fontWeight: 500, lineHeight: 1.22, letterSpacing: "-.025em", textWrap: "balance", overflowWrap: "anywhere" }, children: entry.text })
21
31
  ] }, i))
22
32
  ] });
@@ -1,12 +1,19 @@
1
1
  import {
2
- editorialFont,
2
+ EditorialSurface
3
+ } from "./chunk-XX4GXKTX.js";
4
+ import "./chunk-NMFDC2W2.js";
5
+ import "./chunk-77VY4O7A.js";
6
+ import {
3
7
  fade
4
8
  } from "./chunk-4YM2M62S.js";
9
+ import "./chunk-224QNWRA.js";
10
+ import "./chunk-TVIU23OM.js";
5
11
 
6
12
  // src/visual-system/scene-templates/editorial-timeline.tsx
7
13
  import { jsx, jsxs } from "react/jsx-runtime";
8
14
  var timelineTiming = (index) => ({ nodeStart: index === 0 ? 0.06 : 0.23 + (index - 1) * 0.11, lineStart: 0.14 + index * 0.11, lineDuration: 0.09, entranceDuration: 0.16 });
9
- function TimelineScene({ variables, progress, motionProgress = progress, width, height, safeZone }) {
15
+ function TimelineScene(props) {
16
+ const { variables, progress, motionProgress = progress, width, height, safeZone } = props;
10
17
  const events = (Array.isArray(variables.events) ? variables.events : []).slice(0, 5).map((e) => ({ label: String(e?.label ?? "") }));
11
18
  const portrait = height > width, u = Math.min(width, height), n = Math.max(1, events.length);
12
19
  const side = Math.max(width * 0.13, safeZone.left, safeZone.right), available = width - side * 2;
@@ -14,7 +21,7 @@ function TimelineScene({ variables, progress, motionProgress = progress, width,
14
21
  const slot = portrait ? (bottom - top) / n : available / n;
15
22
  const points = events.map((_, i) => ({ x: portrait ? side : side + slot * (i + 0.5), y: portrait ? top + slot * (i + 0.5) : height * 0.43 }));
16
23
  const radius = u * 45e-4;
17
- return /* @__PURE__ */ jsxs("div", { "data-template": "timeline", style: { position: "absolute", inset: 0, overflow: "hidden", background: "#000", fontFamily: editorialFont, color: "#fff" }, children: [
24
+ return /* @__PURE__ */ jsxs(EditorialSurface, { ...props, template: "timeline", children: [
18
25
  points.slice(0, -1).map((point, i) => {
19
26
  const next = points[i + 1], timing = timelineTiming(i), line = fade((motionProgress - timing.lineStart) / timing.lineDuration);
20
27
  return /* @__PURE__ */ jsx("div", { "data-step-connector": "true", style: { position: "absolute", left: point.x, top: point.y, width: portrait ? u * 1e-3 : next.x - point.x, height: portrait ? next.y - point.y : u * 1e-3, background: "#fff", opacity: 0.3, transform: portrait ? `scaleY(${line})` : `scaleX(${line})`, transformOrigin: portrait ? "top" : "left" } }, `line-${i}`);
@@ -0,0 +1,30 @@
1
+ import {
2
+ EditorialSurface
3
+ } from "./chunk-XX4GXKTX.js";
4
+ import "./chunk-NMFDC2W2.js";
5
+ import "./chunk-77VY4O7A.js";
6
+ import {
7
+ editorialLabel,
8
+ fade
9
+ } from "./chunk-4YM2M62S.js";
10
+ import {
11
+ hasSceneMedia
12
+ } from "./chunk-224QNWRA.js";
13
+ import "./chunk-TVIU23OM.js";
14
+
15
+ // src/visual-system/scene-templates/key-figure.tsx
16
+ import { jsx, jsxs } from "react/jsx-runtime";
17
+ function KeyFigureScene(props) {
18
+ const { variables, width, height, progress, motionProgress = progress, safeZone } = props;
19
+ const overMedia = hasSceneMedia(variables);
20
+ const u = Math.min(width, height), side = Math.max(width * 0.13, safeZone.left, safeZone.right), available = width - side * 2;
21
+ const top = Math.max(height * 0.16, safeZone.top), bottom = height - Math.max(height * 0.23, safeZone.bottom), value = String(variables.value ?? "");
22
+ return /* @__PURE__ */ jsx(EditorialSurface, { ...props, template: "keyFigure", children: /* @__PURE__ */ jsxs("div", { style: { position: "absolute", left: side, top: (top + bottom) / 2, width: available, transform: "translateY(-50%)", textAlign: "center", opacity: fade((motionProgress - 0.03) / 0.22) }, children: [
23
+ /* @__PURE__ */ jsx("div", { style: { fontSize: Math.min(u * 0.22, available / Math.max(1, value.length * 0.6)), fontWeight: 500, lineHeight: 1.05, letterSpacing: "-.045em", fontVariantNumeric: "tabular-nums" }, children: value }),
24
+ /* @__PURE__ */ jsx("div", { style: { ...editorialLabel(u), color: overMedia ? "#fff" : "#b7b7bc", marginTop: u * 0.045, textWrap: "balance", overflowWrap: "anywhere" }, children: String(variables.label ?? "") })
25
+ ] }) });
26
+ }
27
+ var KeyFigureSceneTemplate = KeyFigureScene;
28
+ export {
29
+ KeyFigureSceneTemplate
30
+ };
@@ -1,13 +1,14 @@
1
1
  import {
2
2
  MediaScene
3
- } from "./chunk-G7IZBBWF.js";
3
+ } from "./chunk-Z67Q5KUW.js";
4
+ import "./chunk-NMFDC2W2.js";
4
5
  import {
5
6
  spring
6
7
  } from "./chunk-77VY4O7A.js";
7
8
  import {
8
9
  editorialFont
9
10
  } from "./chunk-4YM2M62S.js";
10
- import "./chunk-UDIODEDK.js";
11
+ import "./chunk-224QNWRA.js";
11
12
  import "./chunk-TVIU23OM.js";
12
13
 
13
14
  // src/visual-system/scene-templates/mobile-message.tsx
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  limitsConcurrentVideoDecoders,
3
3
  resolveMediaType
4
- } from "./chunk-UDIODEDK.js";
4
+ } from "./chunk-224QNWRA.js";
5
5
 
6
6
  // src/player/preload-media.ts
7
7
  var warmed = /* @__PURE__ */ new Set();
@@ -0,0 +1,33 @@
1
+ import {
2
+ EditorialSurface
3
+ } from "./chunk-XX4GXKTX.js";
4
+ import "./chunk-NMFDC2W2.js";
5
+ import "./chunk-77VY4O7A.js";
6
+ import {
7
+ fade
8
+ } from "./chunk-4YM2M62S.js";
9
+ import {
10
+ hasSceneMedia
11
+ } from "./chunk-224QNWRA.js";
12
+ import "./chunk-TVIU23OM.js";
13
+
14
+ // src/visual-system/scene-templates/quote.tsx
15
+ import { jsx, jsxs } from "react/jsx-runtime";
16
+ function QuoteScene(props) {
17
+ const { variables, width, height, progress, motionProgress = progress, safeZone } = props;
18
+ const overMedia = hasSceneMedia(variables);
19
+ const u = Math.min(width, height), top = Math.max(height * 0.16, safeZone.top), bottom = height - Math.max(height * 0.23, safeZone.bottom);
20
+ const side = Math.max(width * 0.13, safeZone.left, safeZone.right);
21
+ return /* @__PURE__ */ jsx(EditorialSurface, { ...props, template: "quote", children: /* @__PURE__ */ jsxs("div", { style: { position: "absolute", left: side, top: (top + bottom) / 2, width: width - side * 2, transform: "translateY(-50%)", textAlign: "center", opacity: fade((motionProgress - 0.03) / 0.24) }, children: [
22
+ /* @__PURE__ */ jsxs("div", { style: { fontSize: u * 0.067, fontWeight: 500, lineHeight: 1.25, letterSpacing: "-.025em", textWrap: "balance", overflowWrap: "anywhere" }, children: [
23
+ "\u201C",
24
+ String(variables.quote ?? ""),
25
+ "\u201D"
26
+ ] }),
27
+ /* @__PURE__ */ jsx("div", { style: { fontSize: u * 0.041, fontWeight: 400, color: overMedia ? "#fff" : "#b7b7bc", lineHeight: 1.3, marginTop: u * 0.065, textWrap: "balance", overflowWrap: "anywhere" }, children: String(variables.attribution ?? "") })
28
+ ] }) });
29
+ }
30
+ var QuoteSceneTemplate = QuoteScene;
31
+ export {
32
+ QuoteSceneTemplate
33
+ };