@vanillaskyai/video 0.8.8 → 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.
- package/CHANGELOG.md +42 -0
- package/PUBLIC-API.md +5 -8
- package/dist/{builtin-server-CUYPIDE7.js → builtin-server-W4PLJUZ5.js} +2 -2
- package/dist/{catalog-types-BIhSpOWK.d.ts → catalog-types-WTbLP6Jh.d.ts} +5 -1
- package/dist/chapter-title-YRLIQY3V.js +7 -0
- package/dist/check-runtime.js +5 -14
- package/dist/{chunk-AITKH6QT.js → chunk-2HFO22K2.js} +15 -40
- package/dist/chunk-4YM2M62S.js +13 -0
- package/dist/chunk-4ZJLPHBV.js +684 -0
- package/dist/chunk-77VY4O7A.js +390 -0
- package/dist/{chunk-MMUXVA47.js → chunk-7M56IUUX.js} +9 -8
- package/dist/chunk-7NZOMTAL.js +63 -0
- package/dist/{chunk-2DOLF4QN.js → chunk-AUPC6MDK.js} +12 -14
- package/dist/{chunk-352ZZCET.js → chunk-EGVQODKU.js} +2 -2
- package/dist/{chunk-2USVB3CY.js → chunk-ELVOT2FQ.js} +284 -177
- package/dist/chunk-EWWCQFTI.js +18 -0
- package/dist/{chunk-KT3M7KDL.js → chunk-HKUI5BTB.js} +3 -3
- package/dist/chunk-IIN5M5HW.js +697 -0
- package/dist/{chunk-LMG3GHLL.js → chunk-IQMYK5DX.js} +29 -3
- package/dist/{chunk-OWBT45EN.js → chunk-IR44XKBI.js} +1 -1
- package/dist/{chunk-MXZSDGZQ.js → chunk-NMFDC2W2.js} +4 -6
- package/dist/{chunk-5SLENAJW.js → chunk-PAJ44TFW.js} +1 -2
- package/dist/{chunk-L7QGGKJ2.js → chunk-PDQFQIQW.js} +1 -1
- package/dist/{chunk-WJ6FLKNC.js → chunk-R3XAOMKP.js} +14 -0
- package/dist/{chunk-2OKB27TG.js → chunk-RXTN2CW6.js} +2 -2
- package/dist/{chunk-XWWLKRNU.js → chunk-TVIU23OM.js} +38 -49
- package/dist/chunk-XX4GXKTX.js +35 -0
- package/dist/chunk-Z67Q5KUW.js +16 -0
- package/dist/{chunk-3VRMKFM7.js → chunk-ZDJNFA52.js} +11 -24
- package/dist/cinema-media-C7OUPNSH.js +12 -0
- package/dist/cli.js +18 -9
- package/dist/comparison-GNZOR7MF.js +37 -0
- package/dist/compose-video-TBFTONUC.js +12 -0
- package/dist/editorial-timeline-EMV5335S.js +43 -0
- package/dist/{events-BQ6z264n.d.ts → events-B4YCc4vc.d.ts} +1 -1
- package/dist/index.d.ts +4 -6
- package/dist/index.js +3 -7
- package/dist/key-figure-P37VK425.js +30 -0
- package/dist/{kit-tQnCPMOM.d.ts → kit-DrRpdn0p.d.ts} +2 -2
- package/dist/mobile-message-OF7T62B7.js +50 -0
- package/dist/quote-T6WYLN7A.js +33 -0
- package/dist/react.d.ts +21 -11
- package/dist/react.js +585 -826
- package/dist/scene-video-backdrop-PCTARAAJ.js +7 -0
- package/dist/server.d.ts +7 -8
- package/dist/server.js +179 -84
- package/dist/{system-prompt-RRXIWDDD.js → system-prompt-SYRT5DWM.js} +1 -1
- package/dist/template-catalog.d.ts +392 -16
- package/dist/template-catalog.js +1 -1
- package/dist/templates.d.ts +5 -5
- package/dist/test.d.ts +3 -3
- package/dist/test.js +18 -18
- package/dist/text-stream-LD364KBI.js +9 -0
- package/dist/{types-DWFO6qca.d.ts → types-CdBmNTGD.d.ts} +1 -1
- package/dist/{types-CEh9eUFu.d.ts → types-DdZw4GRQ.d.ts} +17 -48
- package/dist/validate-4OUD2CLX.js +10 -0
- package/docs/architecture.md +1 -1
- package/docs/concepts.md +1 -1
- package/docs/custom-templates.md +13 -28
- package/docs/customization.md +11 -59
- package/docs/getting-started.md +2 -2
- package/docs/immersive-interface.md +3 -4
- package/docs/maintainers/cinematic-migration.md +38 -0
- package/docs/media-and-audio.md +14 -14
- package/docs/motion-and-effects.md +6 -14
- package/docs/persistence.md +3 -3
- package/docs/production.md +11 -9
- package/docs/provider-integration.md +9 -16
- package/docs/reference/design-system.html +1 -1
- package/docs/reference/protocol.md +14 -4
- package/docs/testing.md +1 -1
- package/package.json +6 -3
- package/registry/items/backgrounds.json +1 -1
- package/registry/items/chapterTitle.json +80 -0
- package/registry/items/cinemaMedia.json +136 -0
- package/registry/items/comparison.json +168 -0
- package/registry/items/editorialTimeline.json +172 -0
- package/registry/items/keyFigure.json +162 -0
- package/registry/items/mobileMessage.json +153 -0
- package/registry/items/quote.json +161 -0
- package/registry/items/template-context.json +1 -1
- package/registry/items/theme.json +1 -1
- package/starters/video-chat/README.md +24 -26
- package/starters/video-chat/package.json +1 -1
- package/starters/video-chat/providers/video.ts +6 -5
- package/starters/video-chat/stock.ts +35 -151
- package/styles/fonts/OFL.txt +93 -0
- package/styles/fonts/manifest.json +66 -0
- package/styles/fonts/roboto-v51-cyrillic-ext.woff2 +0 -0
- package/styles/fonts/roboto-v51-cyrillic.woff2 +0 -0
- package/styles/fonts/roboto-v51-greek-ext.woff2 +0 -0
- package/styles/fonts/roboto-v51-greek.woff2 +0 -0
- package/styles/fonts/roboto-v51-latin-ext.woff2 +0 -0
- package/styles/fonts/roboto-v51-latin.woff2 +0 -0
- package/styles/fonts/roboto-v51-math.woff2 +0 -0
- package/styles/fonts/roboto-v51-symbols.woff2 +0 -0
- package/styles/fonts/roboto-v51-vietnamese.woff2 +0 -0
- package/styles/fonts/roboto.css +91 -0
- package/styles/video-chat.css +30 -22
- package/dist/bg-confetti-HITCGLGD.js +0 -89
- package/dist/bg-emoji-VU4UZYZN.js +0 -150
- package/dist/bg-media-L34PDQXJ.js +0 -106
- package/dist/brand-message-FUJ4STFO.js +0 -256
- package/dist/chart-bar-EGPHJATL.js +0 -310
- package/dist/chart-counter-5FFWQNZO.js +0 -306
- package/dist/chart-progress-ring-JMXQLMLC.js +0 -302
- package/dist/chunk-4UNKZEAT.js +0 -3575
- package/dist/chunk-5CDAM24P.js +0 -31
- package/dist/chunk-AOWSXU2K.js +0 -18
- package/dist/chunk-CJ7F2CE6.js +0 -104
- package/dist/chunk-FRN6WKHA.js +0 -185
- package/dist/chunk-G5JPHBX7.js +0 -336
- package/dist/chunk-L5BTTCZV.js +0 -97
- package/dist/chunk-P22HHFDK.js +0 -43
- package/dist/chunk-PP3MCPN4.js +0 -1998
- package/dist/chunk-QAAO7OAY.js +0 -19
- package/dist/chunk-S7HFLYNN.js +0 -35
- package/dist/chunk-W3VDIBGR.js +0 -217
- package/dist/chunk-XGRA2MUV.js +0 -242
- package/dist/chunk-XTOXFMLM.js +0 -105
- package/dist/chunk-YJJC4N4D.js +0 -761
- package/dist/compose-video-2NFH4DZY.js +0 -13
- package/dist/cta-logo-YR7LYUR5.js +0 -212
- package/dist/cta-media-DQJBKUO2.js +0 -221
- package/dist/incoming-call-54KQ7O5A.js +0 -323
- package/dist/infographic-before-after-ROS52GOW.js +0 -460
- package/dist/infographic-feature-list-E7MGUDAN.js +0 -272
- package/dist/infographic-problem-solution-3S6NGO5N.js +0 -343
- package/dist/infographic-stat-row-SYB7AB7H.js +0 -247
- package/dist/infographic-steps-KCE6JWE2.js +0 -406
- package/dist/prompt-input-MHX4O42G.js +0 -239
- package/dist/reaction-SLEGR3BE.js +0 -122
- package/dist/scene-video-backdrop-XFPX4O3I.js +0 -10
- package/dist/showcase-code-2HLAVKBM.js +0 -357
- package/dist/showcase-phone-Q4HEO4LH.js +0 -278
- package/dist/showcase-terminal-DL45LUFG.js +0 -312
- package/dist/showcase-web-2QZO73FZ.js +0 -396
- package/dist/social-conversation-75SD2637.js +0 -695
- package/dist/social-milestone-GEFUQSBF.js +0 -296
- package/dist/social-notification-FJ5VHVLK.js +0 -247
- package/dist/social-review-stack-KXQCKFRP.js +0 -242
- package/dist/social-testimonial-JZ7CHC7S.js +0 -287
- package/dist/social-tweet-UCDXM25F.js +0 -298
- package/dist/text-stream-54LXABJW.js +0 -10
- package/dist/validate-T7GBU2YF.js +0 -8
- package/registry/items/barChart.json +0 -245
- package/registry/items/beforeAfter.json +0 -180
- package/registry/items/bigNumber.json +0 -232
- package/registry/items/brandMessage.json +0 -164
- package/registry/items/cardList.json +0 -214
- package/registry/items/chatMessenger.json +0 -151
- package/registry/items/chatWhatsapp.json +0 -151
- package/registry/items/codeEditor.json +0 -191
- package/registry/items/confetti.json +0 -107
- package/registry/items/ctaLogo.json +0 -167
- package/registry/items/ctaMedia.json +0 -200
- package/registry/items/emojiBurst.json +0 -101
- package/registry/items/incomingCall.json +0 -177
- package/registry/items/media.json +0 -187
- package/registry/items/milestone.json +0 -212
- package/registry/items/notification.json +0 -189
- package/registry/items/phoneMockup.json +0 -261
- package/registry/items/problemSolution.json +0 -193
- package/registry/items/progressRing.json +0 -206
- package/registry/items/promptInput.json +0 -155
- package/registry/items/reaction.json +0 -176
- package/registry/items/reviewStack.json +0 -231
- package/registry/items/steps.json +0 -215
- package/registry/items/terminal.json +0 -219
- package/registry/items/testimonial.json +0 -171
- package/registry/items/tripleStats.json +0 -235
- package/registry/items/tweet.json +0 -210
- package/registry/items/webMockup.json +0 -280
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
validateTemplateSchemaValue
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EGVQODKU.js";
|
|
4
4
|
import {
|
|
5
5
|
getTemplateSchemaGates,
|
|
6
6
|
isMeaningfullyPresentTemplateValue
|
|
@@ -29,7 +29,7 @@ function schemaValues(schema, variables) {
|
|
|
29
29
|
}
|
|
30
30
|
return values;
|
|
31
31
|
}
|
|
32
|
-
function
|
|
32
|
+
function validateTemplateSceneStructure(schema, value, deferMediaUrls = false) {
|
|
33
33
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
34
34
|
throw new Error("Template variable variables must be object");
|
|
35
35
|
}
|
|
@@ -45,6 +45,7 @@ function validateSchema(schema, value) {
|
|
|
45
45
|
}
|
|
46
46
|
for (const [name, property] of Object.entries(schema.properties)) {
|
|
47
47
|
if (Object.hasOwn(object, name)) validateTemplateSchemaValue(property, object[name], name, {
|
|
48
|
+
deferMediaUrls,
|
|
48
49
|
errorPrefix: "Template variable ",
|
|
49
50
|
includeTypeArticle: true,
|
|
50
51
|
allowEmptyOptionalMedia: property.default === "",
|
|
@@ -66,6 +67,24 @@ function suppliedUrls(input) {
|
|
|
66
67
|
}
|
|
67
68
|
return urls;
|
|
68
69
|
}
|
|
70
|
+
function containsSuppliedQuantity(input, value) {
|
|
71
|
+
if (typeof value !== "string" && typeof value !== "number") return false;
|
|
72
|
+
const normalize = (text) => text.normalize("NFKC").replace(/\u2212/g, "-").replace(/\s+/gu, " ").replace(/([\p{Sc}]) (?=[+−-]?\d)/gu, "$1").replace(/(\d) (?=[%‰])/gu, "$1").trim();
|
|
73
|
+
const quantity = normalize(String(value));
|
|
74
|
+
if (!/\d/u.test(quantity)) return false;
|
|
75
|
+
const source = normalize(input);
|
|
76
|
+
let offset = source.indexOf(quantity);
|
|
77
|
+
while (offset !== -1) {
|
|
78
|
+
const before = source.slice(0, offset);
|
|
79
|
+
const after = source.slice(offset + quantity.length);
|
|
80
|
+
const beginsInside = /[\p{L}\p{N}\p{Sc}%‰+−-]$/u.test(before) || /\d[.,]$/u.test(before);
|
|
81
|
+
const endsInside = /^[\p{L}\p{N}\p{Sc}%‰]/u.test(after) || /^[.,]\d/u.test(after);
|
|
82
|
+
const dropsUnit = /\d$/u.test(quantity) && /^ (?:%|‰|percent\b|per cent\b|thousand\b|million\b|billion\b|trillion\b|usd\b|eur\b|gbp\b|dollars?\b|euros?\b|pounds?\b)/iu.test(after);
|
|
83
|
+
if (!beginsInside && !endsInside && !dropsUnit) return true;
|
|
84
|
+
offset = source.indexOf(quantity, offset + 1);
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
69
88
|
function createTemplateSceneValidator(options) {
|
|
70
89
|
return (scene, context) => {
|
|
71
90
|
const template = options.kit.getTemplateMetadata(scene.templateId);
|
|
@@ -73,7 +92,7 @@ function createTemplateSceneValidator(options) {
|
|
|
73
92
|
const schema = template.schema;
|
|
74
93
|
const gates = getTemplateSchemaGates(schema);
|
|
75
94
|
validateConditionalPresence(scene.templateId, gates.requiredAnyOf, scene.variables);
|
|
76
|
-
|
|
95
|
+
validateTemplateSceneStructure(schema, scene.variables);
|
|
77
96
|
const values = schemaValues(schema, scene.variables);
|
|
78
97
|
const allowedUrls = suppliedUrls(context.input);
|
|
79
98
|
const suppliedImageUrls = new Set((context.input.suppliedMedia ?? []).filter(({ type }) => type === "image").map(({ url }) => url));
|
|
@@ -93,6 +112,12 @@ function createTemplateSceneValidator(options) {
|
|
|
93
112
|
});
|
|
94
113
|
if (!permitted) throw new Error(`Template variable ${path} must use supplied media`);
|
|
95
114
|
}
|
|
115
|
+
if (gates.requiresStat) {
|
|
116
|
+
const quantities = values.filter(({ property }) => property.format === "grounded-stat");
|
|
117
|
+
if (!quantities.length || quantities.some(({ value }) => !containsSuppliedQuantity(context.input.input, value))) {
|
|
118
|
+
throw new Error(`Template ${scene.templateId} requires an exact supplied quantity, preserving its unit`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
96
121
|
if (gates.requiresQuote) {
|
|
97
122
|
const quoteValues = values.filter(({ property, value }) => property.format === "grounded-quote" && typeof value === "string" && value.trim()).map(({ value }) => String(value).trim());
|
|
98
123
|
if (!quoteValues.length || quoteValues.some((quote) => !context.input.input.includes(quote))) {
|
|
@@ -103,5 +128,6 @@ function createTemplateSceneValidator(options) {
|
|
|
103
128
|
}
|
|
104
129
|
|
|
105
130
|
export {
|
|
131
|
+
validateTemplateSceneStructure,
|
|
106
132
|
createTemplateSceneValidator
|
|
107
133
|
};
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
+
BrandGradientOverlay,
|
|
2
3
|
SceneVideoBackdrop,
|
|
4
|
+
getBackgroundTransform,
|
|
3
5
|
resolveMediaPosition
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import {
|
|
6
|
-
BrandGradientOverlay,
|
|
7
|
-
getBackgroundTransform
|
|
8
|
-
} from "./chunk-W3VDIBGR.js";
|
|
6
|
+
} from "./chunk-77VY4O7A.js";
|
|
9
7
|
import {
|
|
10
8
|
resolveMediaType
|
|
11
9
|
} from "./chunk-224QNWRA.js";
|
|
12
10
|
import {
|
|
13
11
|
useExternalVideoBackdrop
|
|
14
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-TVIU23OM.js";
|
|
15
13
|
|
|
16
14
|
// src/visual-system/scene-templates/scene-background.tsx
|
|
17
15
|
import { useEffect, useState } from "react";
|
|
@@ -42,13 +42,12 @@ Composition rules:
|
|
|
42
42
|
- Before emitting, assign each supported fact to at most one scene. The supplied opening counts: once a fact is visible, treat it as unavailable to later scenes. Finish when the supported material is covered instead of padding the response.
|
|
43
43
|
- Do not infer that something is scheduled, ready, triggered, enabled, automatic, causal, or available unless the permitted factual basis supports it.
|
|
44
44
|
- The first generated body scene must be asset-free and fully playable before any external media resolves.
|
|
45
|
-
- Never use media, ctaMedia, or reaction as the first generated body template, including in gradient mode.
|
|
46
45
|
- Use only media URLs present in the supplied input or already resolved by the host. Never expose a loading placeholder or unresolved media keyword. Audio is optional and must never delay the first scene.
|
|
47
46
|
- Audio is selected by the host before generation. Never emit audio.
|
|
48
47
|
|
|
49
48
|
Streaming rules:
|
|
50
49
|
- Emit every scene once as a complete scene.add.
|
|
51
|
-
- Emit exactly one closer
|
|
50
|
+
- Emit exactly one closer using placement:"closer". It is held and appended last; preserve the intended story order.
|
|
52
51
|
- Prefer resolved media on scene.add. Scenes are immutable after emission.
|
|
53
52
|
- End explicitly with plan.complete. A truncated stream is never treated as complete.
|
|
54
53
|
- Return only plan parts accepted by the provided schema.
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
// src/visual-system/catalog/video-backdrop-capability.ts
|
|
2
2
|
var EXTERNAL_VIDEO_BACKDROP_CAPABILITY = "__vanillaskyExternalVideoBackdrop";
|
|
3
|
+
function markExternalVideoBackdropTemplate(template) {
|
|
4
|
+
const component = template.component;
|
|
5
|
+
if ((typeof component !== "object" || component === null) && typeof component !== "function") {
|
|
6
|
+
throw new Error("External video backdrop templates require a component");
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(component, EXTERNAL_VIDEO_BACKDROP_CAPABILITY, {
|
|
9
|
+
value: true,
|
|
10
|
+
enumerable: false,
|
|
11
|
+
configurable: false,
|
|
12
|
+
writable: false
|
|
13
|
+
});
|
|
14
|
+
return template;
|
|
15
|
+
}
|
|
3
16
|
function supportsExternalVideoBackdrop(template) {
|
|
4
17
|
if (typeof template !== "object" || template === null) return false;
|
|
5
18
|
const component = template.component;
|
|
@@ -10,6 +23,7 @@ function externalVideoBackdropCapabilitySource() {
|
|
|
10
23
|
}
|
|
11
24
|
|
|
12
25
|
export {
|
|
26
|
+
markExternalVideoBackdropTemplate,
|
|
13
27
|
supportsExternalVideoBackdrop,
|
|
14
28
|
externalVideoBackdropCapabilitySource
|
|
15
29
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseVideoEvent
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7M56IUUX.js";
|
|
4
4
|
import {
|
|
5
5
|
VIDEO_PROTOCOL_VERSION,
|
|
6
6
|
VIDEO_SCHEMA_VERSION
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-7NZOMTAL.js";
|
|
8
8
|
|
|
9
9
|
// src/protocol/stable-json.ts
|
|
10
10
|
function stableJson(value) {
|
|
@@ -1,23 +1,30 @@
|
|
|
1
|
-
// src/visual-system/scene-templates/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
// src/visual-system/scene-templates/external-video-backdrop.tsx
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
var DEFAULT = { mode: false, audioMuted: true, audioVolume: 1 };
|
|
5
|
+
var sharedContext = globalThis;
|
|
6
|
+
var BackdropContext = sharedContext.__vanillaskyVideoBackdropContext ??= React.createContext(DEFAULT);
|
|
7
|
+
function ExternalVideoBackdropProvider({
|
|
8
|
+
mode,
|
|
9
|
+
audioMuted = true,
|
|
10
|
+
audioVolume = 1,
|
|
11
|
+
children
|
|
12
|
+
}) {
|
|
13
|
+
const value = React.useMemo(
|
|
14
|
+
() => ({ mode, audioMuted, audioVolume }),
|
|
15
|
+
[mode, audioMuted, audioVolume]
|
|
16
|
+
);
|
|
17
|
+
return /* @__PURE__ */ jsx(BackdropContext.Provider, { value, children });
|
|
18
|
+
}
|
|
19
|
+
function useExternalVideoBackdrop() {
|
|
20
|
+
return React.useContext(BackdropContext).mode;
|
|
20
21
|
}
|
|
22
|
+
function useMediaAudio() {
|
|
23
|
+
const { audioMuted, audioVolume } = React.useContext(BackdropContext);
|
|
24
|
+
return { muted: audioMuted, volume: audioVolume };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/visual-system/scene-templates/tokens.ts
|
|
21
28
|
var STYLE_PRESETS = {
|
|
22
29
|
bold: {
|
|
23
30
|
id: "bold",
|
|
@@ -94,7 +101,6 @@ function resolveMotion(id) {
|
|
|
94
101
|
return id && MOTION_SCALES[id] || MOTION_SCALES[DEFAULT_MOTION_ID];
|
|
95
102
|
}
|
|
96
103
|
function resolveTokens(style) {
|
|
97
|
-
const brand = style.brand;
|
|
98
104
|
const preset = resolvePreset(style.preset);
|
|
99
105
|
const density = resolveDensity(style.density);
|
|
100
106
|
const motion = resolveMotion(style.motion);
|
|
@@ -107,17 +113,15 @@ function resolveTokens(style) {
|
|
|
107
113
|
}
|
|
108
114
|
};
|
|
109
115
|
return {
|
|
110
|
-
primary:
|
|
111
|
-
secondary:
|
|
112
|
-
background:
|
|
113
|
-
surface:
|
|
114
|
-
surfaceElevated:
|
|
115
|
-
foreground:
|
|
116
|
-
muted:
|
|
117
|
-
font:
|
|
118
|
-
scriptFont:
|
|
119
|
-
logoUrl: brand.logoUrl,
|
|
120
|
-
name: brand.name,
|
|
116
|
+
primary: "#FFFFFF",
|
|
117
|
+
secondary: "#FFFFFF",
|
|
118
|
+
background: { type: "solid", color: "#000000" },
|
|
119
|
+
surface: "#000000",
|
|
120
|
+
surfaceElevated: "#171717",
|
|
121
|
+
foreground: "#FFFFFF",
|
|
122
|
+
muted: "#B7B7BC",
|
|
123
|
+
font: '-apple-system, BlinkMacSystemFont, "Helvetica Neue", Roboto, Arial, sans-serif',
|
|
124
|
+
scriptFont: "Georgia",
|
|
121
125
|
preset: composedPreset,
|
|
122
126
|
density,
|
|
123
127
|
motion
|
|
@@ -131,27 +135,12 @@ function darken(hex, factor) {
|
|
|
131
135
|
const ch = (i) => Math.max(0, Math.round(parseInt(full.slice(i, i + 2), 16) * (1 - factor))).toString(16).padStart(2, "0");
|
|
132
136
|
return `#${ch(1)}${ch(3)}${ch(5)}`;
|
|
133
137
|
}
|
|
134
|
-
function lighten(hex, factor) {
|
|
135
|
-
if (!hex.startsWith("#") || hex.length !== 4 && hex.length !== 7) {
|
|
136
|
-
return hex;
|
|
137
|
-
}
|
|
138
|
-
const full = hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;
|
|
139
|
-
const r = parseInt(full.slice(1, 3), 16);
|
|
140
|
-
const g = parseInt(full.slice(3, 5), 16);
|
|
141
|
-
const b = parseInt(full.slice(5, 7), 16);
|
|
142
|
-
const lr = Math.min(255, Math.round(r + (255 - r) * factor));
|
|
143
|
-
const lg = Math.min(255, Math.round(g + (255 - g) * factor));
|
|
144
|
-
const lb = Math.min(255, Math.round(b + (255 - b) * factor));
|
|
145
|
-
return `#${lr.toString(16).padStart(2, "0")}${lg.toString(16).padStart(2, "0")}${lb.toString(16).padStart(2, "0")}`;
|
|
146
|
-
}
|
|
147
|
-
var MEDIA_TEXT_SHADOW = "0 2px 8px rgba(0,0,0,0.55), 0 6px 16px rgba(0,0,0,0.35)";
|
|
148
138
|
|
|
149
139
|
export {
|
|
150
|
-
TOKEN_DEFAULTS,
|
|
151
|
-
fontStack,
|
|
152
140
|
resolveDensity,
|
|
153
141
|
resolveTokens,
|
|
154
142
|
darken,
|
|
155
|
-
|
|
156
|
-
|
|
143
|
+
ExternalVideoBackdropProvider,
|
|
144
|
+
useExternalVideoBackdrop,
|
|
145
|
+
useMediaAudio
|
|
157
146
|
};
|
|
@@ -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
|
+
};
|
|
@@ -6,30 +6,27 @@ import {
|
|
|
6
6
|
checksumVideo,
|
|
7
7
|
createVideoEventFactory,
|
|
8
8
|
createVideoState
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-RXTN2CW6.js";
|
|
10
10
|
import {
|
|
11
11
|
parseVideoPlanPart,
|
|
12
12
|
safePublicDiagnostic
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-7M56IUUX.js";
|
|
14
14
|
import {
|
|
15
15
|
MAX_RETAINED_INSTRUCTIONS_LENGTH,
|
|
16
16
|
MAX_RETAINED_MEDIA_URLS,
|
|
17
17
|
MAX_RETAINED_MEDIA_URL_LENGTH,
|
|
18
18
|
MAX_RETAINED_SOURCE_LENGTH,
|
|
19
19
|
parseVideo
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-AUPC6MDK.js";
|
|
21
21
|
import {
|
|
22
22
|
VIDEO_SCHEMA_VERSION,
|
|
23
23
|
createVideoRequest
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-7NZOMTAL.js";
|
|
25
25
|
import {
|
|
26
26
|
getCloserReserve,
|
|
27
27
|
getReadableSceneDuration,
|
|
28
28
|
paceScene
|
|
29
29
|
} from "./chunk-3O7OMMMF.js";
|
|
30
|
-
import {
|
|
31
|
-
resolveVideoBrand
|
|
32
|
-
} from "./chunk-XGRA2MUV.js";
|
|
33
30
|
|
|
34
31
|
// src/replayable-stream.ts
|
|
35
32
|
function createReplayableStream(source, onError) {
|
|
@@ -114,7 +111,6 @@ function buildVideoUserPrompt(input, openingDurationSec = 0) {
|
|
|
114
111
|
input.opening === false ? "The host owns the opening wait. Add the first grounded scene as soon as it is complete; it may use host-resolved media." : typeof input.opening === "string" && input.opening.trim() ? `The host has already added the opening scene, which consumes ${openingDurationSec} seconds. Continue after it and do not repeat or rewrite it.` : "Add the first grounded scene as soon as it is complete.",
|
|
115
112
|
...input.opening === false ? [] : [
|
|
116
113
|
"The first generated body scene must be fully playable without external media. Use a content-fit text, data, comparison, list, or device-free template with no media URL or keyword.",
|
|
117
|
-
"Never use media, ctaMedia, or reaction as the first generated body template, even with mediaType=gradient. Choose a non-media template first.",
|
|
118
114
|
"Add that scene before resolving any stock or supplied asset. Resolve media as part of each complete later body scene."
|
|
119
115
|
],
|
|
120
116
|
"Use only claims supported by the factual basis permitted by the trusted system prompt.",
|
|
@@ -125,7 +121,7 @@ function buildVideoUserPrompt(input, openingDurationSec = 0) {
|
|
|
125
121
|
"If the creative instructions explicitly require one separate scene per named item, release, section, or list entry, do not merge, group, or omit those required items. Keep related required scenes adjacent in a coherent progression while preserving each item as its own scene.",
|
|
126
122
|
"Before emitting, verify that the explicitly requested structure can fit readably within the maximum duration. If it cannot, preserve readability and the requested separation for the scenes that fit, then finish with plan.complete using finishReason length rather than silently changing the structure.",
|
|
127
123
|
"For ordinary multi-fact input, form at least three distinct beats: hook, comprehension, and payoff. Use only one or two beats when the source genuinely contains no more than two independent grounded takeaways. This is a narrative guideline, never permission to repeat facts or add filler.",
|
|
128
|
-
"
|
|
124
|
+
"Emit exactly one final scene.add with placement closer. Generate a short grounded conclusion that answers the story's so-what; it must not repeat hook language or imply another scene follows.",
|
|
129
125
|
"Use a different suitable template for each body scene when the catalog supports it.",
|
|
130
126
|
"Never add filler to satisfy a count or diversity target.",
|
|
131
127
|
input.suppliedMedia?.length ? input.opening === false ? "Select zero or more relevant opaque supplied-media references for visible scenes. Never invent or transform a reference. Only emit mediaKeyword when the trusted system catalog explicitly exposes it. Never invent mediaUrl or mediaPoster." : "Select zero or more relevant opaque supplied-media references for visible later scenes. Never invent or transform a reference. Only emit mediaKeyword when the trusted system catalog explicitly exposes it, and only on later scenes. Never invent mediaUrl or mediaPoster." : input.opening === false ? "No supplied media URL is available. Use asset-free templates unless the trusted system catalog explicitly permits host-resolved media intent, which may begin on the first scene. Only emit mediaKeyword when the trusted system catalog explicitly exposes it. Never invent mediaUrl or mediaPoster." : "No supplied media URL is available. Use asset-free templates unless the trusted system catalog explicitly permits host-resolved media intent. Only emit mediaKeyword when the trusted system catalog explicitly exposes it, and only on later scenes. Never invent mediaUrl or mediaPoster.",
|
|
@@ -140,13 +136,7 @@ function buildVideoUserPrompt(input, openingDurationSec = 0) {
|
|
|
140
136
|
JSON.stringify(input.personalization ?? {}),
|
|
141
137
|
"",
|
|
142
138
|
"SUPPLIED MEDIA",
|
|
143
|
-
JSON.stringify(suppliedMediaReferences(input))
|
|
144
|
-
"",
|
|
145
|
-
"BRAND",
|
|
146
|
-
JSON.stringify({
|
|
147
|
-
...input.brand?.name?.trim() ? { name: input.brand.name.trim() } : {},
|
|
148
|
-
hasLogo: Boolean(input.brand?.logoUrl?.trim())
|
|
149
|
-
})
|
|
139
|
+
JSON.stringify(suppliedMediaReferences(input))
|
|
150
140
|
].join("\n");
|
|
151
141
|
}
|
|
152
142
|
|
|
@@ -162,7 +152,7 @@ function resolveStreamCapabilities(capabilities, hasRuntimeOpening) {
|
|
|
162
152
|
if (!hasRuntimeOpening || capabilities?.templates == null) return capabilities;
|
|
163
153
|
return {
|
|
164
154
|
...capabilities,
|
|
165
|
-
templates: [.../* @__PURE__ */ new Set(["
|
|
155
|
+
templates: [.../* @__PURE__ */ new Set(["chapterTitle", ...capabilities.templates])]
|
|
166
156
|
};
|
|
167
157
|
}
|
|
168
158
|
function validateVideoInput(input) {
|
|
@@ -190,16 +180,14 @@ function validateVideoInput(input) {
|
|
|
190
180
|
throw new Error(`Video response supplied media ${index} poster URL must be at most ${MAX_RETAINED_MEDIA_URL_LENGTH} characters`);
|
|
191
181
|
}
|
|
192
182
|
}
|
|
193
|
-
resolveVideoBrand(input.brand);
|
|
194
183
|
}
|
|
195
184
|
function buildInitialComposition(input, audio, snapshotRetention, closerReserveSec, getTemplatePacing) {
|
|
196
185
|
const openingText = typeof input.opening === "string" ? input.opening.trim() : void 0;
|
|
197
186
|
const openingScenes = openingText ? [{
|
|
198
187
|
id: "supplied-opening",
|
|
199
|
-
templateId: "
|
|
188
|
+
templateId: "chapterTitle",
|
|
200
189
|
variables: {
|
|
201
|
-
|
|
202
|
-
mediaType: "gradient"
|
|
190
|
+
title: openingText
|
|
203
191
|
},
|
|
204
192
|
timing: { fixedDuration: 3 }
|
|
205
193
|
}] : [];
|
|
@@ -223,7 +211,7 @@ function buildInitialComposition(input, audio, snapshotRetention, closerReserveS
|
|
|
223
211
|
warnings.push(...paced.warnings);
|
|
224
212
|
}
|
|
225
213
|
const meta = {
|
|
226
|
-
name:
|
|
214
|
+
name: "Video response"
|
|
227
215
|
};
|
|
228
216
|
if (snapshotRetention?.source) {
|
|
229
217
|
meta.source = input.input.trim().slice(0, MAX_RETAINED_SOURCE_LENGTH);
|
|
@@ -241,7 +229,6 @@ function buildInitialComposition(input, audio, snapshotRetention, closerReserveS
|
|
|
241
229
|
scenes,
|
|
242
230
|
...audio ? { audio } : {},
|
|
243
231
|
style: {
|
|
244
|
-
brand: resolveVideoBrand(input.brand),
|
|
245
232
|
density: input.style?.density ?? "normal",
|
|
246
233
|
motion: input.style?.motion ?? "normal",
|
|
247
234
|
defaultBackgroundEffect: input.style?.backgroundEffect ?? "static",
|
|
@@ -704,7 +691,7 @@ function createVideo(rawInput, options) {
|
|
|
704
691
|
position
|
|
705
692
|
}));
|
|
706
693
|
}
|
|
707
|
-
const systemPrompt = options.systemPrompt ?? (await import("./system-prompt-
|
|
694
|
+
const systemPrompt = options.systemPrompt ?? (await import("./system-prompt-SYRT5DWM.js")).createVideoSystemPrompt(input.knowledgeMode);
|
|
708
695
|
const context = { request, systemPrompt, userPrompt, initialConfig, signal: controller.signal };
|
|
709
696
|
attachGenerationLifecycleSink(context, lifecycle);
|
|
710
697
|
for await (const untrustedPart of options.generate(context)) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MediaScene,
|
|
3
|
+
MediaSceneTemplate
|
|
4
|
+
} from "./chunk-Z67Q5KUW.js";
|
|
5
|
+
import "./chunk-NMFDC2W2.js";
|
|
6
|
+
import "./chunk-77VY4O7A.js";
|
|
7
|
+
import "./chunk-224QNWRA.js";
|
|
8
|
+
import "./chunk-TVIU23OM.js";
|
|
9
|
+
export {
|
|
10
|
+
MediaScene,
|
|
11
|
+
MediaSceneTemplate
|
|
12
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./chunk-
|
|
3
|
-
import "./chunk-
|
|
2
|
+
import "./chunk-2HFO22K2.js";
|
|
3
|
+
import "./chunk-PAJ44TFW.js";
|
|
4
4
|
import {
|
|
5
5
|
isTemplatePropertyFormatSupported,
|
|
6
6
|
validateTemplateSchemaValue
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-EGVQODKU.js";
|
|
8
8
|
import {
|
|
9
9
|
getBuiltinTemplateMetadata,
|
|
10
10
|
listBuiltinTemplateMetadata
|
|
11
|
-
} from "./chunk-
|
|
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-
|
|
18
|
+
} from "./chunk-4ZJLPHBV.js";
|
|
19
19
|
import {
|
|
20
20
|
externalVideoBackdropCapabilitySource
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-R3XAOMKP.js";
|
|
22
22
|
import {
|
|
23
23
|
getTemplateDefaults,
|
|
24
24
|
isMeaningfullyPresentTemplateValue,
|
|
@@ -1006,8 +1006,12 @@ function validateDiscoveredTemplate(template, cwd) {
|
|
|
1006
1006
|
validateSchema(metadata.schema);
|
|
1007
1007
|
if (metadata.timing !== void 0) {
|
|
1008
1008
|
if (!metadata.timing || typeof metadata.timing !== "object" || Array.isArray(metadata.timing)) throw new Error("timing must be an object");
|
|
1009
|
-
for (const key of Object.keys(metadata.timing)) if (!(/* @__PURE__ */ new Set(["contentFields", "contentUnit"])).has(key)) throw new Error(`timing.${key} is not supported`);
|
|
1010
|
-
if (!Array.isArray(metadata.timing.contentFields)
|
|
1009
|
+
for (const key of Object.keys(metadata.timing)) if (!(/* @__PURE__ */ new Set(["contentFields", "contentUnit", "revealSeconds", "holdSeconds", "exitSeconds"])).has(key)) throw new Error(`timing.${key} is not supported`);
|
|
1010
|
+
if (!Array.isArray(metadata.timing.contentFields)) throw new Error("timing.contentFields must be an array of schema properties");
|
|
1011
|
+
for (const key of ["revealSeconds", "holdSeconds", "exitSeconds"]) {
|
|
1012
|
+
const value = metadata.timing[key];
|
|
1013
|
+
if (value !== void 0 && (typeof value !== "number" || !Number.isFinite(value) || value < 0)) throw new Error(`timing.${key} must be a finite non-negative number`);
|
|
1014
|
+
}
|
|
1011
1015
|
const timingFields = /* @__PURE__ */ new Set();
|
|
1012
1016
|
for (const field of metadata.timing.contentFields) {
|
|
1013
1017
|
if (typeof field !== "string" || !Object.hasOwn(metadata.schema.properties, field)) throw new Error(`timing.contentFields references undeclared property ${JSON.stringify(field)}`);
|
|
@@ -1017,6 +1021,11 @@ function validateDiscoveredTemplate(template, cwd) {
|
|
|
1017
1021
|
if (!CONTENT_UNITS.has(metadata.timing.contentUnit)) throw new Error("timing.contentUnit contains an unsupported value");
|
|
1018
1022
|
}
|
|
1019
1023
|
const defaults = getTemplateDefaults(metadata.schema);
|
|
1024
|
+
const smokeVariables = { ...defaults };
|
|
1025
|
+
for (const field of metadata.schema.required ?? []) {
|
|
1026
|
+
const example = metadata.schema.properties[field]?.examples?.[0];
|
|
1027
|
+
if (!(field in smokeVariables) && example !== void 0) smokeVariables[field] = example;
|
|
1028
|
+
}
|
|
1020
1029
|
if (template.examples !== void 0 && !Array.isArray(template.examples)) throw new Error("examples must be an array");
|
|
1021
1030
|
const supplied = template.examples ?? [];
|
|
1022
1031
|
for (const [index, value] of supplied.entries()) {
|
|
@@ -1031,7 +1040,7 @@ function validateDiscoveredTemplate(template, cwd) {
|
|
|
1031
1040
|
name,
|
|
1032
1041
|
variables: { ...defaults, ...variables },
|
|
1033
1042
|
enforceRequiredAnyOf: true
|
|
1034
|
-
})) : [{ name: "defaults", variables:
|
|
1043
|
+
})) : [{ name: "defaults", variables: smokeVariables, enforceRequiredAnyOf: false }];
|
|
1035
1044
|
const names = /* @__PURE__ */ new Set();
|
|
1036
1045
|
for (const example of examples) {
|
|
1037
1046
|
if (typeof example.name !== "string" || !example.name.trim()) throw new Error("example names must be non-empty strings");
|
|
@@ -0,0 +1,37 @@
|
|
|
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/comparison.tsx
|
|
16
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
17
|
+
function ComparisonScene(props) {
|
|
18
|
+
const { variables, width, height, progress, motionProgress = progress, safeZone } = props;
|
|
19
|
+
const overMedia = hasSceneMedia(variables);
|
|
20
|
+
const portrait = height > width, u = Math.min(width, height);
|
|
21
|
+
const side = Math.max(width * 0.12, safeZone.left, safeZone.right);
|
|
22
|
+
const top = Math.max(height * 0.2, safeZone.top), bottom = height - Math.max(height * 0.23, safeZone.bottom);
|
|
23
|
+
const area = bottom - top, cy = (top + bottom) / 2, available = width - side * 2;
|
|
24
|
+
const entries = [{ label: String(variables.leftLabel ?? ""), text: String(variables.leftText ?? "") }, { label: String(variables.rightLabel ?? ""), text: String(variables.rightText ?? "") }];
|
|
25
|
+
const textWidth = portrait ? available : available * 0.39;
|
|
26
|
+
return /* @__PURE__ */ jsxs(EditorialSurface, { ...props, template: "comparison", children: [
|
|
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) } }),
|
|
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: [
|
|
29
|
+
entry.label && /* @__PURE__ */ jsx("div", { style: { ...editorialLabel(u), color: overMedia ? "#fff" : "#b7b7bc", marginBottom: u * 0.028 }, children: entry.label }),
|
|
30
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: u * 0.058, fontWeight: 500, lineHeight: 1.22, letterSpacing: "-.025em", textWrap: "balance", overflowWrap: "anywhere" }, children: entry.text })
|
|
31
|
+
] }, i))
|
|
32
|
+
] });
|
|
33
|
+
}
|
|
34
|
+
var ComparisonSceneTemplate = ComparisonScene;
|
|
35
|
+
export {
|
|
36
|
+
ComparisonSceneTemplate
|
|
37
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createVideo
|
|
3
|
+
} from "./chunk-ZDJNFA52.js";
|
|
4
|
+
import "./chunk-E7CL7UPB.js";
|
|
5
|
+
import "./chunk-RXTN2CW6.js";
|
|
6
|
+
import "./chunk-7M56IUUX.js";
|
|
7
|
+
import "./chunk-AUPC6MDK.js";
|
|
8
|
+
import "./chunk-7NZOMTAL.js";
|
|
9
|
+
import "./chunk-3O7OMMMF.js";
|
|
10
|
+
export {
|
|
11
|
+
createVideo
|
|
12
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
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 "./chunk-224QNWRA.js";
|
|
10
|
+
import "./chunk-TVIU23OM.js";
|
|
11
|
+
|
|
12
|
+
// src/visual-system/scene-templates/editorial-timeline.tsx
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
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 });
|
|
15
|
+
function TimelineScene(props) {
|
|
16
|
+
const { variables, progress, motionProgress = progress, width, height, safeZone } = props;
|
|
17
|
+
const events = (Array.isArray(variables.events) ? variables.events : []).slice(0, 5).map((e) => ({ label: String(e?.label ?? "") }));
|
|
18
|
+
const portrait = height > width, u = Math.min(width, height), n = Math.max(1, events.length);
|
|
19
|
+
const side = Math.max(width * 0.13, safeZone.left, safeZone.right), available = width - side * 2;
|
|
20
|
+
const top = Math.max(height * 0.2, safeZone.top), bottom = height - Math.max(height * 0.24, safeZone.bottom);
|
|
21
|
+
const slot = portrait ? (bottom - top) / n : available / n;
|
|
22
|
+
const points = events.map((_, i) => ({ x: portrait ? side : side + slot * (i + 0.5), y: portrait ? top + slot * (i + 0.5) : height * 0.43 }));
|
|
23
|
+
const radius = u * 45e-4;
|
|
24
|
+
return /* @__PURE__ */ jsxs(EditorialSurface, { ...props, template: "timeline", children: [
|
|
25
|
+
points.slice(0, -1).map((point, i) => {
|
|
26
|
+
const next = points[i + 1], timing = timelineTiming(i), line = fade((motionProgress - timing.lineStart) / timing.lineDuration);
|
|
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}`);
|
|
28
|
+
}),
|
|
29
|
+
points.map((point, i) => {
|
|
30
|
+
const timing = timelineTiming(i), event = events[i], opacity = fade((motionProgress - timing.nodeStart) / timing.entranceDuration);
|
|
31
|
+
const textW = portrait ? available - u * 0.055 : slot * 0.86;
|
|
32
|
+
return /* @__PURE__ */ jsxs("div", { "data-template-item": "steps", style: { opacity }, children: [
|
|
33
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { position: "absolute", left: point.x - radius, top: point.y - radius, width: radius * 2, height: radius * 2, borderRadius: "50%", background: "#fff" } }),
|
|
34
|
+
/* @__PURE__ */ jsx("div", { style: { position: "absolute", left: portrait ? point.x + u * 0.055 : point.x - textW / 2, top: portrait ? point.y : point.y + u * 0.05, width: textW, transform: portrait ? "translateY(-50%)" : void 0, textAlign: portrait ? "left" : "center" }, children: /* @__PURE__ */ jsx("div", { style: { fontSize: u * (portrait ? 0.052 : 0.041), fontWeight: 500, lineHeight: 1.22, letterSpacing: "-.025em", textWrap: "balance", overflowWrap: "anywhere" }, children: event.label }) })
|
|
35
|
+
] }, i);
|
|
36
|
+
})
|
|
37
|
+
] });
|
|
38
|
+
}
|
|
39
|
+
var TimelineSceneTemplate = TimelineScene;
|
|
40
|
+
export {
|
|
41
|
+
TimelineSceneTemplate,
|
|
42
|
+
timelineTiming
|
|
43
|
+
};
|