@vanillaskyai/video 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/LICENSE +201 -0
- package/PUBLIC-API.md +276 -0
- package/README.md +152 -0
- package/SECURITY.md +22 -0
- package/SUPPORT.md +28 -0
- package/bin/vanillasky.js +3 -0
- package/dist/bg-confetti-WNQXS7ZS.js +89 -0
- package/dist/bg-emoji-ETI47GLS.js +150 -0
- package/dist/bg-media-SVUZAMGX.js +99 -0
- package/dist/brand-message-F3RD4P3P.js +253 -0
- package/dist/builtin-server-F7YXRVCH.js +8 -0
- package/dist/catalog-types-BIhSpOWK.d.ts +74 -0
- package/dist/chart-bar-CNSC7BNK.js +304 -0
- package/dist/chart-counter-MCRHKN77.js +299 -0
- package/dist/chart-progress-ring-RMI4A7ZK.js +296 -0
- package/dist/check-runtime.d.ts +15 -0
- package/dist/check-runtime.js +102 -0
- package/dist/chunk-2E6T633S.js +27 -0
- package/dist/chunk-352ZZCET.js +83 -0
- package/dist/chunk-73NTSFFI.js +81 -0
- package/dist/chunk-A2X45FET.js +46 -0
- package/dist/chunk-ABPKM4GK.js +187 -0
- package/dist/chunk-ABZACD4G.js +216 -0
- package/dist/chunk-BCRUUJ6A.js +756 -0
- package/dist/chunk-CHLGW22F.js +3551 -0
- package/dist/chunk-CJ7F2CE6.js +104 -0
- package/dist/chunk-CR7FE7BW.js +109 -0
- package/dist/chunk-E7CL7UPB.js +109 -0
- package/dist/chunk-EE6PK6XC.js +18 -0
- package/dist/chunk-ERY4S6QV.js +385 -0
- package/dist/chunk-EVG2ZYIY.js +125 -0
- package/dist/chunk-FNAEQ7QO.js +155 -0
- package/dist/chunk-FQ47WXAJ.js +38 -0
- package/dist/chunk-FSG2PYWG.js +336 -0
- package/dist/chunk-GHJEAP4O.js +504 -0
- package/dist/chunk-GRMUV7QY.js +262 -0
- package/dist/chunk-IFOW65Z6.js +205 -0
- package/dist/chunk-IXCUY3B3.js +786 -0
- package/dist/chunk-L5BTTCZV.js +97 -0
- package/dist/chunk-LMG3GHLL.js +107 -0
- package/dist/chunk-OOPIETLW.js +101 -0
- package/dist/chunk-P22HHFDK.js +43 -0
- package/dist/chunk-QAAO7OAY.js +19 -0
- package/dist/chunk-S7HFLYNN.js +35 -0
- package/dist/chunk-SPVTJH3F.js +24 -0
- package/dist/chunk-W2XJKG6C.js +3177 -0
- package/dist/chunk-XB7LH4J2.js +301 -0
- package/dist/chunk-XGRA2MUV.js +242 -0
- package/dist/chunk-XTOXFMLM.js +105 -0
- package/dist/chunk-YC5MFXA5.js +132 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1681 -0
- package/dist/compose-video-CN3VSWST.js +13 -0
- package/dist/cta-logo-SVA5GP2A.js +209 -0
- package/dist/cta-media-E7VLLK42.js +215 -0
- package/dist/events-_wfjbmEp.d.ts +81 -0
- package/dist/incoming-call-62MFZL3Z.js +320 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +14 -0
- package/dist/infographic-before-after-AXCDAWND.js +460 -0
- package/dist/infographic-feature-list-GW5GUE6O.js +266 -0
- package/dist/infographic-problem-solution-7NURJANA.js +340 -0
- package/dist/infographic-stat-row-J7IZR6ZN.js +241 -0
- package/dist/infographic-steps-VSZM6F5M.js +400 -0
- package/dist/kit-BMNcHqa9.d.ts +79 -0
- package/dist/prompt-input-LOUCRXCY.js +236 -0
- package/dist/react.d.ts +81 -0
- package/dist/react.js +835 -0
- package/dist/reaction-QG4CYZLQ.js +119 -0
- package/dist/server.d.ts +141 -0
- package/dist/server.js +498 -0
- package/dist/showcase-code-RUTFZR3H.js +351 -0
- package/dist/showcase-phone-6CP6XEU5.js +272 -0
- package/dist/showcase-terminal-MGAEQWPR.js +306 -0
- package/dist/showcase-web-Y4W2HVRJ.js +390 -0
- package/dist/social-conversation-75SD2637.js +695 -0
- package/dist/social-milestone-XI2QE5BO.js +292 -0
- package/dist/social-notification-2UOHQCUY.js +244 -0
- package/dist/social-review-stack-FDYZGZTJ.js +239 -0
- package/dist/social-testimonial-OQ7N52GJ.js +284 -0
- package/dist/social-tweet-5OLCNPPC.js +295 -0
- package/dist/state-DZcKuS32.d.ts +3 -0
- package/dist/system-prompt-A6UXNTPK.js +8 -0
- package/dist/template-catalog.d.ts +24 -0
- package/dist/template-catalog.js +6 -0
- package/dist/templates.d.ts +25 -0
- package/dist/templates.js +19 -0
- package/dist/test.d.ts +149 -0
- package/dist/test.js +272 -0
- package/dist/text-stream-6XHC7J47.js +10 -0
- package/dist/types-B-PZR6G_.d.ts +208 -0
- package/dist/validate-T7GBU2YF.js +8 -0
- package/docs/agent-integration.md +39 -0
- package/docs/architecture.md +84 -0
- package/docs/branding-and-personalization.md +87 -0
- package/docs/concepts.md +106 -0
- package/docs/custom-templates.md +329 -0
- package/docs/customization.md +141 -0
- package/docs/errors.md +70 -0
- package/docs/getting-started.md +111 -0
- package/docs/input-and-first-scene.md +41 -0
- package/docs/integrate-nextjs.md +79 -0
- package/docs/media-and-audio.md +69 -0
- package/docs/motion-and-effects.md +107 -0
- package/docs/persistence.md +95 -0
- package/docs/production.md +122 -0
- package/docs/prompt-and-input.md +185 -0
- package/docs/provider-integration.md +115 -0
- package/docs/reference/protocol.md +96 -0
- package/docs/reference/provider-adapters.md +158 -0
- package/docs/responsive-orientation.md +37 -0
- package/docs/security.md +38 -0
- package/docs/streaming-protocol.md +15 -0
- package/docs/testing.md +137 -0
- package/docs/use-cases.md +59 -0
- package/examples/custom-template/README.md +19 -0
- package/examples/custom-template/minimal-text.tsx +82 -0
- package/examples/custom-template/structured-data.tsx +104 -0
- package/examples/custom-template/supplied-media.tsx +92 -0
- package/examples/nextjs-quickstart/.env.example +2 -0
- package/examples/nextjs-quickstart/README.md +22 -0
- package/examples/nextjs-quickstart/next-env.d.ts +4 -0
- package/examples/nextjs-quickstart/package.json +24 -0
- package/examples/nextjs-quickstart/src/app/api/video/route.ts +22 -0
- package/examples/nextjs-quickstart/src/app/layout.tsx +5 -0
- package/examples/nextjs-quickstart/src/app/page.tsx +31 -0
- package/examples/nextjs-quickstart/tsconfig.json +26 -0
- package/package.json +167 -0
- package/registry/items/backgrounds.json +52 -0
- package/registry/items/barChart.json +237 -0
- package/registry/items/beforeAfter.json +180 -0
- package/registry/items/bigNumber.json +225 -0
- package/registry/items/brandMessage.json +158 -0
- package/registry/items/cardList.json +206 -0
- package/registry/items/chatMessenger.json +151 -0
- package/registry/items/chatWhatsapp.json +151 -0
- package/registry/items/codeEditor.json +184 -0
- package/registry/items/confetti.json +107 -0
- package/registry/items/ctaLogo.json +160 -0
- package/registry/items/ctaMedia.json +193 -0
- package/registry/items/emojiBurst.json +101 -0
- package/registry/items/incomingCall.json +170 -0
- package/registry/items/media.json +179 -0
- package/registry/items/milestone.json +205 -0
- package/registry/items/motion.json +45 -0
- package/registry/items/notification.json +182 -0
- package/registry/items/phoneMockup.json +254 -0
- package/registry/items/problemSolution.json +186 -0
- package/registry/items/progressRing.json +199 -0
- package/registry/items/promptInput.json +148 -0
- package/registry/items/reaction.json +170 -0
- package/registry/items/reviewStack.json +224 -0
- package/registry/items/steps.json +207 -0
- package/registry/items/template-context.json +31 -0
- package/registry/items/terminal.json +212 -0
- package/registry/items/testimonial.json +164 -0
- package/registry/items/theme.json +47 -0
- package/registry/items/tripleStats.json +228 -0
- package/registry/items/tweet.json +203 -0
- package/registry/items/typography.json +47 -0
- package/registry/items/webMockup.json +273 -0
package/SECURITY.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Security fixes target the latest published version of `@vanillaskyai/video`.
|
|
6
|
+
Upgrade to the current release before reporting behavior that may already have
|
|
7
|
+
been corrected.
|
|
8
|
+
|
|
9
|
+
## Report a vulnerability
|
|
10
|
+
|
|
11
|
+
Use [GitHub private vulnerability reporting](https://github.com/VanillaSkyAi/video/security/advisories/new)
|
|
12
|
+
to report a suspected vulnerability. Do not open a public issue, discussion,
|
|
13
|
+
or pull request containing exploit details, credentials, customer data, or an
|
|
14
|
+
unannounced vulnerability.
|
|
15
|
+
|
|
16
|
+
Include the affected version, impact, reproduction steps, and any suggested
|
|
17
|
+
mitigation. Maintainers will validate the report and coordinate remediation and
|
|
18
|
+
disclosure when appropriate, without a guaranteed response time.
|
|
19
|
+
|
|
20
|
+
For deployment guidance covering authentication, provider credentials, request
|
|
21
|
+
limits, media policy, and logging, read the
|
|
22
|
+
[integration security guide](docs/security.md).
|
package/SUPPORT.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Support
|
|
2
|
+
|
|
3
|
+
VanillaSky Video is a beta open-source project. There is no guaranteed response time.
|
|
4
|
+
|
|
5
|
+
## Product and integration questions
|
|
6
|
+
|
|
7
|
+
Search the documentation and existing GitHub issues first. If the problem is
|
|
8
|
+
not covered, open a reproducible GitHub issue at
|
|
9
|
+
<https://github.com/VanillaSkyAi/video/issues> with:
|
|
10
|
+
|
|
11
|
+
- the exact package, Node, React, framework, and provider versions;
|
|
12
|
+
- a minimal reproduction or packed-consumer fixture;
|
|
13
|
+
- expected and observed behavior;
|
|
14
|
+
- redacted logs and the smallest relevant video input.
|
|
15
|
+
|
|
16
|
+
Please do not include API keys, customer data, private media URLs, or
|
|
17
|
+
unannounced security details.
|
|
18
|
+
|
|
19
|
+
## Security reports
|
|
20
|
+
|
|
21
|
+
Do not use a public issue for a suspected vulnerability. Follow `SECURITY.md`
|
|
22
|
+
and use GitHub private vulnerability reporting.
|
|
23
|
+
|
|
24
|
+
## Scope
|
|
25
|
+
|
|
26
|
+
Maintainers may close requests that cannot be reproduced, rely on unsupported
|
|
27
|
+
versions, or require application-specific implementation work. A public issue
|
|
28
|
+
does not create a response-time or resolution commitment.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConfettiLayer
|
|
3
|
+
} from "./chunk-CJ7F2CE6.js";
|
|
4
|
+
import "./chunk-QAAO7OAY.js";
|
|
5
|
+
import {
|
|
6
|
+
TemplateText
|
|
7
|
+
} from "./chunk-BCRUUJ6A.js";
|
|
8
|
+
import "./chunk-L5BTTCZV.js";
|
|
9
|
+
import {
|
|
10
|
+
BrandGradientOverlay
|
|
11
|
+
} from "./chunk-ABZACD4G.js";
|
|
12
|
+
import "./chunk-XTOXFMLM.js";
|
|
13
|
+
import {
|
|
14
|
+
resolveTokens
|
|
15
|
+
} from "./chunk-FNAEQ7QO.js";
|
|
16
|
+
|
|
17
|
+
// src/visual-system/scene-templates/bg-confetti.tsx
|
|
18
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
19
|
+
var BgConfettiTemplate = ({
|
|
20
|
+
variables,
|
|
21
|
+
style,
|
|
22
|
+
progress,
|
|
23
|
+
motionProgress = progress,
|
|
24
|
+
beatIntensity,
|
|
25
|
+
width,
|
|
26
|
+
height,
|
|
27
|
+
textArchetype,
|
|
28
|
+
safeZone,
|
|
29
|
+
sceneDuration
|
|
30
|
+
}) => {
|
|
31
|
+
const { background, foreground, font } = resolveTokens(style);
|
|
32
|
+
const textColor = foreground;
|
|
33
|
+
return /* @__PURE__ */ jsxs(
|
|
34
|
+
"div",
|
|
35
|
+
{
|
|
36
|
+
style: {
|
|
37
|
+
width,
|
|
38
|
+
height,
|
|
39
|
+
backgroundColor: "#000",
|
|
40
|
+
position: "relative",
|
|
41
|
+
overflow: "hidden",
|
|
42
|
+
fontFamily: font
|
|
43
|
+
},
|
|
44
|
+
children: [
|
|
45
|
+
/* @__PURE__ */ jsx(
|
|
46
|
+
BrandGradientOverlay,
|
|
47
|
+
{
|
|
48
|
+
style,
|
|
49
|
+
progress,
|
|
50
|
+
sceneDuration,
|
|
51
|
+
seed: String(variables.texts || "").split("").reduce((acc, c) => acc + c.charCodeAt(0), 0)
|
|
52
|
+
}
|
|
53
|
+
),
|
|
54
|
+
/* @__PURE__ */ jsx(
|
|
55
|
+
ConfettiLayer,
|
|
56
|
+
{
|
|
57
|
+
progress: motionProgress,
|
|
58
|
+
width,
|
|
59
|
+
height,
|
|
60
|
+
beatIntensity,
|
|
61
|
+
bgColor: background.type === "solid" ? background.color : background.colors[1]
|
|
62
|
+
}
|
|
63
|
+
),
|
|
64
|
+
/* @__PURE__ */ jsx(
|
|
65
|
+
TemplateText,
|
|
66
|
+
{
|
|
67
|
+
motionProgress,
|
|
68
|
+
typeTreatment: resolveTokens(style).preset.type,
|
|
69
|
+
archetype: textArchetype ?? "subtle",
|
|
70
|
+
text: String(variables.texts ?? ""),
|
|
71
|
+
progress,
|
|
72
|
+
sceneDuration: sceneDuration ?? 3,
|
|
73
|
+
width,
|
|
74
|
+
height,
|
|
75
|
+
position: "center",
|
|
76
|
+
sizeRole: "headline",
|
|
77
|
+
safeZone,
|
|
78
|
+
font,
|
|
79
|
+
color: textColor,
|
|
80
|
+
beatIntensity
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
export {
|
|
88
|
+
BgConfettiTemplate
|
|
89
|
+
};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getCelebrationParticleTiming
|
|
3
|
+
} from "./chunk-QAAO7OAY.js";
|
|
4
|
+
import {
|
|
5
|
+
TemplateText
|
|
6
|
+
} from "./chunk-BCRUUJ6A.js";
|
|
7
|
+
import {
|
|
8
|
+
Emoji
|
|
9
|
+
} from "./chunk-L5BTTCZV.js";
|
|
10
|
+
import {
|
|
11
|
+
BrandGradientOverlay
|
|
12
|
+
} from "./chunk-ABZACD4G.js";
|
|
13
|
+
import "./chunk-XTOXFMLM.js";
|
|
14
|
+
import {
|
|
15
|
+
resolveTokens
|
|
16
|
+
} from "./chunk-FNAEQ7QO.js";
|
|
17
|
+
|
|
18
|
+
// src/visual-system/scene-templates/bg-emoji.tsx
|
|
19
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
20
|
+
function seededRandom(seed) {
|
|
21
|
+
const x = Math.sin(seed * 12.9898 + seed * 78.233) * 43758.5453;
|
|
22
|
+
return x - Math.floor(x);
|
|
23
|
+
}
|
|
24
|
+
var EMOJI_LIST = [
|
|
25
|
+
"\u2764\uFE0F",
|
|
26
|
+
// red heart
|
|
27
|
+
"\u2B50",
|
|
28
|
+
// star
|
|
29
|
+
"\u{1F389}",
|
|
30
|
+
// party popper
|
|
31
|
+
"\u{1F984}",
|
|
32
|
+
// unicorn
|
|
33
|
+
"\u{1F525}",
|
|
34
|
+
// fire
|
|
35
|
+
"\u2728",
|
|
36
|
+
// sparkles
|
|
37
|
+
"\u{1F680}",
|
|
38
|
+
// rocket
|
|
39
|
+
"\u{1F49C}"
|
|
40
|
+
// purple heart
|
|
41
|
+
];
|
|
42
|
+
var PARTICLE_COUNT = 100;
|
|
43
|
+
function easeOutQuad(p) {
|
|
44
|
+
return 1 - (1 - p) * (1 - p);
|
|
45
|
+
}
|
|
46
|
+
var BgEmojiTemplate = ({
|
|
47
|
+
variables,
|
|
48
|
+
style,
|
|
49
|
+
progress,
|
|
50
|
+
motionProgress = progress,
|
|
51
|
+
beatIntensity,
|
|
52
|
+
width,
|
|
53
|
+
height,
|
|
54
|
+
textArchetype,
|
|
55
|
+
safeZone,
|
|
56
|
+
sceneDuration
|
|
57
|
+
}) => {
|
|
58
|
+
const s = Math.min(width, height) / 1080;
|
|
59
|
+
const BURST_RADIUS = Math.max(width, height) * 0.95;
|
|
60
|
+
const { foreground, font } = resolveTokens(style);
|
|
61
|
+
const textColor = foreground;
|
|
62
|
+
return /* @__PURE__ */ jsxs(
|
|
63
|
+
"div",
|
|
64
|
+
{
|
|
65
|
+
style: {
|
|
66
|
+
width,
|
|
67
|
+
height,
|
|
68
|
+
backgroundColor: "#000",
|
|
69
|
+
position: "relative",
|
|
70
|
+
overflow: "hidden",
|
|
71
|
+
fontFamily: font
|
|
72
|
+
},
|
|
73
|
+
children: [
|
|
74
|
+
/* @__PURE__ */ jsx(BrandGradientOverlay, { style, progress, sceneDuration, seed: String(variables.texts || "").split("").reduce((acc, c) => acc + c.charCodeAt(0), 0) }),
|
|
75
|
+
Array.from({ length: PARTICLE_COUNT }, (_, i) => {
|
|
76
|
+
const seed = i + 1;
|
|
77
|
+
const angle = i / PARTICLE_COUNT * Math.PI * 2;
|
|
78
|
+
const forceFactor = 0.75 + seededRandom(seed * 1) * 0.5;
|
|
79
|
+
const durationFactor = 1.1 + seededRandom(seed * 3) * 0.6;
|
|
80
|
+
const emoji = EMOJI_LIST[i % EMOJI_LIST.length];
|
|
81
|
+
const startRot = seededRandom(seed * 5) * 60 - 30;
|
|
82
|
+
const rotSpeed = (seededRandom(seed * 6) - 0.5) * 540;
|
|
83
|
+
const sizeJitter = 0.7 + seededRandom(seed * 7) * 0.7;
|
|
84
|
+
const timing = getCelebrationParticleTiming(motionProgress, i, durationFactor);
|
|
85
|
+
if (!timing) return null;
|
|
86
|
+
const p = timing.progress;
|
|
87
|
+
const reach = BURST_RADIUS * forceFactor;
|
|
88
|
+
const radialP = easeOutQuad(p);
|
|
89
|
+
const gravity = height * 0.08 * p * p;
|
|
90
|
+
const x = width * 0.5 + Math.cos(angle) * reach * radialP;
|
|
91
|
+
const y = height * 0.5 + Math.sin(angle) * reach * radialP + gravity;
|
|
92
|
+
const baseSize = (28 + seededRandom(seed * 11) * 24) * s;
|
|
93
|
+
const size = baseSize * sizeJitter;
|
|
94
|
+
const popScale = Math.min(1, p * 30);
|
|
95
|
+
const particleOpacity = p < 0.85 ? 1 : Math.max(0, 1 - (p - 0.85) / 0.15);
|
|
96
|
+
const opacity = particleOpacity * timing.opacity;
|
|
97
|
+
const beatPulse = 1 + beatIntensity * 0.2;
|
|
98
|
+
const rot = startRot + rotSpeed * p;
|
|
99
|
+
if (opacity <= 0) return null;
|
|
100
|
+
if (y > height + 100 || y < -100 || x < -100 || x > width + 100) return null;
|
|
101
|
+
return /* @__PURE__ */ jsx(
|
|
102
|
+
"div",
|
|
103
|
+
{
|
|
104
|
+
style: {
|
|
105
|
+
position: "absolute",
|
|
106
|
+
left: x - size / 2,
|
|
107
|
+
top: y - size / 2,
|
|
108
|
+
width: size,
|
|
109
|
+
height: size,
|
|
110
|
+
fontSize: size * 0.8,
|
|
111
|
+
lineHeight: 1,
|
|
112
|
+
textAlign: "center",
|
|
113
|
+
opacity,
|
|
114
|
+
transform: `rotate(${rot}deg) scale(${popScale * beatPulse})`,
|
|
115
|
+
pointerEvents: "none",
|
|
116
|
+
display: "flex",
|
|
117
|
+
alignItems: "center",
|
|
118
|
+
justifyContent: "center"
|
|
119
|
+
},
|
|
120
|
+
children: /* @__PURE__ */ jsx(Emoji, { char: emoji, size: size * 0.8, verticalAlign: "baseline" })
|
|
121
|
+
},
|
|
122
|
+
i
|
|
123
|
+
);
|
|
124
|
+
}),
|
|
125
|
+
/* @__PURE__ */ jsx(
|
|
126
|
+
TemplateText,
|
|
127
|
+
{
|
|
128
|
+
motionProgress,
|
|
129
|
+
typeTreatment: resolveTokens(style).preset.type,
|
|
130
|
+
archetype: textArchetype ?? "subtle",
|
|
131
|
+
text: String(variables.texts ?? ""),
|
|
132
|
+
progress,
|
|
133
|
+
sceneDuration: sceneDuration ?? 3,
|
|
134
|
+
width,
|
|
135
|
+
height,
|
|
136
|
+
position: "center",
|
|
137
|
+
sizeRole: "headline",
|
|
138
|
+
safeZone,
|
|
139
|
+
font,
|
|
140
|
+
color: textColor,
|
|
141
|
+
beatIntensity
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
export {
|
|
149
|
+
BgEmojiTemplate
|
|
150
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SceneBackground,
|
|
3
|
+
getMediaBackgroundProps
|
|
4
|
+
} from "./chunk-IFOW65Z6.js";
|
|
5
|
+
import {
|
|
6
|
+
ConfettiLayer
|
|
7
|
+
} from "./chunk-CJ7F2CE6.js";
|
|
8
|
+
import "./chunk-QAAO7OAY.js";
|
|
9
|
+
import {
|
|
10
|
+
TemplateText
|
|
11
|
+
} from "./chunk-BCRUUJ6A.js";
|
|
12
|
+
import "./chunk-L5BTTCZV.js";
|
|
13
|
+
import "./chunk-ABZACD4G.js";
|
|
14
|
+
import "./chunk-XTOXFMLM.js";
|
|
15
|
+
import {
|
|
16
|
+
resolveTokens
|
|
17
|
+
} from "./chunk-FNAEQ7QO.js";
|
|
18
|
+
|
|
19
|
+
// src/visual-system/scene-templates/bg-media.tsx
|
|
20
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
21
|
+
var BgMediaTemplate = ({
|
|
22
|
+
variables,
|
|
23
|
+
style,
|
|
24
|
+
progress,
|
|
25
|
+
motionProgress = progress,
|
|
26
|
+
beatIntensity,
|
|
27
|
+
width,
|
|
28
|
+
height,
|
|
29
|
+
textArchetype,
|
|
30
|
+
backgroundEffect,
|
|
31
|
+
safeZone,
|
|
32
|
+
sceneDuration,
|
|
33
|
+
isPlaying = true
|
|
34
|
+
}) => {
|
|
35
|
+
const { font, foreground, background } = resolveTokens(style);
|
|
36
|
+
const text = foreground;
|
|
37
|
+
return /* @__PURE__ */ jsxs(
|
|
38
|
+
"div",
|
|
39
|
+
{
|
|
40
|
+
style: {
|
|
41
|
+
width,
|
|
42
|
+
height,
|
|
43
|
+
backgroundColor: "#000",
|
|
44
|
+
position: "relative",
|
|
45
|
+
overflow: "hidden",
|
|
46
|
+
fontFamily: font
|
|
47
|
+
},
|
|
48
|
+
children: [
|
|
49
|
+
/* @__PURE__ */ jsx(
|
|
50
|
+
SceneBackground,
|
|
51
|
+
{
|
|
52
|
+
style,
|
|
53
|
+
progress,
|
|
54
|
+
sceneDuration,
|
|
55
|
+
width,
|
|
56
|
+
height,
|
|
57
|
+
...getMediaBackgroundProps(variables),
|
|
58
|
+
backgroundEffect,
|
|
59
|
+
seed: String(variables.texts || ""),
|
|
60
|
+
isPlaying,
|
|
61
|
+
beatIntensity
|
|
62
|
+
}
|
|
63
|
+
),
|
|
64
|
+
variables.confetti === true && /* @__PURE__ */ jsx(
|
|
65
|
+
ConfettiLayer,
|
|
66
|
+
{
|
|
67
|
+
progress: motionProgress,
|
|
68
|
+
width,
|
|
69
|
+
height,
|
|
70
|
+
beatIntensity,
|
|
71
|
+
bgColor: String(variables.mediaUrl || "").trim() === "" ? background.type === "solid" ? background.color : background.colors[1] : void 0
|
|
72
|
+
}
|
|
73
|
+
),
|
|
74
|
+
/* @__PURE__ */ jsx(
|
|
75
|
+
TemplateText,
|
|
76
|
+
{
|
|
77
|
+
motionProgress,
|
|
78
|
+
typeTreatment: resolveTokens(style).preset.type,
|
|
79
|
+
archetype: textArchetype ?? "subtle",
|
|
80
|
+
text: String(variables.texts ?? ""),
|
|
81
|
+
progress,
|
|
82
|
+
sceneDuration: sceneDuration ?? 3,
|
|
83
|
+
width,
|
|
84
|
+
height,
|
|
85
|
+
position: "center",
|
|
86
|
+
sizeRole: "headline",
|
|
87
|
+
safeZone,
|
|
88
|
+
font,
|
|
89
|
+
color: text,
|
|
90
|
+
beatIntensity
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
export {
|
|
98
|
+
BgMediaTemplate
|
|
99
|
+
};
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import {
|
|
2
|
+
stripPipe
|
|
3
|
+
} from "./chunk-S7HFLYNN.js";
|
|
4
|
+
import {
|
|
5
|
+
SceneBackground,
|
|
6
|
+
getMediaBackgroundProps
|
|
7
|
+
} from "./chunk-IFOW65Z6.js";
|
|
8
|
+
import {
|
|
9
|
+
renderWithEmoji
|
|
10
|
+
} from "./chunk-L5BTTCZV.js";
|
|
11
|
+
import "./chunk-ABZACD4G.js";
|
|
12
|
+
import {
|
|
13
|
+
interpolate
|
|
14
|
+
} from "./chunk-XTOXFMLM.js";
|
|
15
|
+
import "./chunk-FNAEQ7QO.js";
|
|
16
|
+
|
|
17
|
+
// src/visual-system/primitives/typography/BrandMessageBubble.tsx
|
|
18
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
19
|
+
var CLAMP = { extrapolateLeft: "clamp", extrapolateRight: "clamp" };
|
|
20
|
+
var BUBBLE_BG = "rgba(245,242,238,0.92)";
|
|
21
|
+
var BUBBLE_TEXT = "#1c1c1e";
|
|
22
|
+
var DOT_COLOR = "#8C8C92";
|
|
23
|
+
function easeOutBack(t) {
|
|
24
|
+
const c1 = 1.70158;
|
|
25
|
+
const c3 = c1 + 1;
|
|
26
|
+
return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
|
|
27
|
+
}
|
|
28
|
+
var TAIL_WITH_EMOJI = /(\S+)(\s+)([\p{Extended_Pictographic}\p{Emoji_Modifier}\u{FE0E}\u{FE0F}\u{200D}]+)\s*$/u;
|
|
29
|
+
function renderMessageWithEmojiTail(text, fontSizePx) {
|
|
30
|
+
const match = TAIL_WITH_EMOJI.exec(text);
|
|
31
|
+
if (!match || match.index === void 0) {
|
|
32
|
+
return renderWithEmoji(text, fontSizePx);
|
|
33
|
+
}
|
|
34
|
+
const [, lastWord, space, emoji] = match;
|
|
35
|
+
const leading = text.slice(0, match.index);
|
|
36
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37
|
+
renderWithEmoji(leading, fontSizePx),
|
|
38
|
+
/* @__PURE__ */ jsxs("span", { style: { whiteSpace: "nowrap" }, children: [
|
|
39
|
+
lastWord,
|
|
40
|
+
space,
|
|
41
|
+
renderWithEmoji(emoji, fontSizePx)
|
|
42
|
+
] })
|
|
43
|
+
] });
|
|
44
|
+
}
|
|
45
|
+
function popIn(t, start, dur = 0.4) {
|
|
46
|
+
if (t <= start) return 0;
|
|
47
|
+
if (t >= start + dur) return 1;
|
|
48
|
+
return easeOutBack((t - start) / dur);
|
|
49
|
+
}
|
|
50
|
+
var BrandMessageBubble = ({
|
|
51
|
+
progress,
|
|
52
|
+
sceneDuration,
|
|
53
|
+
brandName: rawBrandName,
|
|
54
|
+
message: rawMessage,
|
|
55
|
+
width,
|
|
56
|
+
height,
|
|
57
|
+
safeZone
|
|
58
|
+
}) => {
|
|
59
|
+
const isLandscape = width > height;
|
|
60
|
+
const s = isLandscape ? Math.min(width, height) / 534 * 1.3 : width / 534;
|
|
61
|
+
const brandName = stripPipe(rawBrandName);
|
|
62
|
+
const message = stripPipe(rawMessage);
|
|
63
|
+
const realTimeSeconds = progress * sceneDuration;
|
|
64
|
+
const typingStart = 0.1;
|
|
65
|
+
const bubbleStart = 0.38;
|
|
66
|
+
const typingPop = popIn(progress, typingStart, 0.1);
|
|
67
|
+
const typingFade = interpolate(progress, [bubbleStart - 0.06, bubbleStart], [1, 0], CLAMP);
|
|
68
|
+
const showTyping = progress >= typingStart && progress < bubbleStart;
|
|
69
|
+
const bubblePop = popIn(progress, bubbleStart, 0.18);
|
|
70
|
+
const showBubble = progress >= bubbleStart;
|
|
71
|
+
const topPad = Math.max(safeZone.top, height * 0.25);
|
|
72
|
+
const sidePad = Math.max(safeZone.left, width * 0.06);
|
|
73
|
+
return /* @__PURE__ */ jsxs(
|
|
74
|
+
"div",
|
|
75
|
+
{
|
|
76
|
+
style: {
|
|
77
|
+
position: "absolute",
|
|
78
|
+
top: topPad,
|
|
79
|
+
left: sidePad,
|
|
80
|
+
right: sidePad,
|
|
81
|
+
display: "flex",
|
|
82
|
+
justifyContent: "flex-end"
|
|
83
|
+
},
|
|
84
|
+
children: [
|
|
85
|
+
showTyping && /* @__PURE__ */ jsx(
|
|
86
|
+
"div",
|
|
87
|
+
{
|
|
88
|
+
style: {
|
|
89
|
+
opacity: typingPop * typingFade,
|
|
90
|
+
transform: `translateY(${(1 - typingPop) * 8 * s}px)`,
|
|
91
|
+
background: BUBBLE_BG,
|
|
92
|
+
borderRadius: 18 * s,
|
|
93
|
+
padding: `${12 * s}px ${16 * s}px`,
|
|
94
|
+
display: "flex",
|
|
95
|
+
gap: 5 * s,
|
|
96
|
+
alignItems: "center",
|
|
97
|
+
boxShadow: `0 ${1 * s}px ${4 * s}px rgba(0,0,0,0.10)`
|
|
98
|
+
},
|
|
99
|
+
children: [0, 1, 2].map((j) => {
|
|
100
|
+
const phase = (realTimeSeconds * 1.6 + j * 0.2) % 1;
|
|
101
|
+
const y = Math.sin(phase * Math.PI * 2) * 2.5 * s;
|
|
102
|
+
const op = 0.45 + 0.55 * Math.max(0, Math.sin(phase * Math.PI));
|
|
103
|
+
return /* @__PURE__ */ jsx(
|
|
104
|
+
"div",
|
|
105
|
+
{
|
|
106
|
+
style: {
|
|
107
|
+
width: 7 * s,
|
|
108
|
+
height: 7 * s,
|
|
109
|
+
borderRadius: 3.5 * s,
|
|
110
|
+
background: DOT_COLOR,
|
|
111
|
+
transform: `translateY(${-y}px)`,
|
|
112
|
+
opacity: op
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
j
|
|
116
|
+
);
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
),
|
|
120
|
+
showBubble && /* @__PURE__ */ jsxs(
|
|
121
|
+
"div",
|
|
122
|
+
{
|
|
123
|
+
style: {
|
|
124
|
+
// `width: max-content` forces the bubble to size to its
|
|
125
|
+
// natural one-line content width up to `maxWidth`. Without
|
|
126
|
+
// this, modern-screenshot's foreignObject text shaping (the
|
|
127
|
+
// export path) was using an intrinsic width well below
|
|
128
|
+
// `maxWidth`, breaking text that would have fit on one line
|
|
129
|
+
// in the live DOM — even after the NBSP fix glued the
|
|
130
|
+
// trailing emoji to the last word. With `max-content` +
|
|
131
|
+
// `maxWidth`, the bubble grows up to the cap on a single
|
|
132
|
+
// line, then wraps naturally inside the cap for genuinely
|
|
133
|
+
// long messages.
|
|
134
|
+
width: "max-content",
|
|
135
|
+
maxWidth: width * 0.86,
|
|
136
|
+
// Render with native system fonts in BOTH paths. The export
|
|
137
|
+
// pipeline turns the iframe DOM into an SVG and loads it via
|
|
138
|
+
// <img src="data:image/svg+xml,…">, and SVG-as-image is a
|
|
139
|
+
// sandboxed graphics context that does NOT load @font-face
|
|
140
|
+
// resources (data: or otherwise — this is a browser security
|
|
141
|
+
// model, not a CSP issue). Inter therefore never resolves in
|
|
142
|
+
// the export; the SVG falls back to Helvetica/Helvetica Neue,
|
|
143
|
+
// which is wider at the same point size, and "We built this
|
|
144
|
+
// for you ❤️" wraps inside the pinned bubble box even though
|
|
145
|
+
// the iframe's Inter rendering fit on one line. Naming the
|
|
146
|
+
// system font explicitly here makes the iframe ALSO use that
|
|
147
|
+
// same OS-native font, so preview and export compute identical
|
|
148
|
+
// widths and both fit on one line. See PRs #598/#599/#604 for
|
|
149
|
+
// the months of font-embed work that this finally closes out.
|
|
150
|
+
fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif',
|
|
151
|
+
background: BUBBLE_BG,
|
|
152
|
+
color: BUBBLE_TEXT,
|
|
153
|
+
borderRadius: `${22 * s}px ${22 * s}px 0 ${22 * s}px`,
|
|
154
|
+
padding: `${14 * s}px ${18 * s}px ${12 * s}px`,
|
|
155
|
+
fontSize: 23 * s,
|
|
156
|
+
lineHeight: `${29 * s}px`,
|
|
157
|
+
fontWeight: 400,
|
|
158
|
+
opacity: bubblePop,
|
|
159
|
+
transform: `translateY(${(1 - bubblePop) * 8 * s}px) scale(${0.96 + 0.04 * bubblePop})`,
|
|
160
|
+
transformOrigin: "right top",
|
|
161
|
+
boxShadow: `0 ${2 * s}px ${10 * s}px rgba(0,0,0,0.14)`
|
|
162
|
+
},
|
|
163
|
+
children: [
|
|
164
|
+
/* @__PURE__ */ jsx(
|
|
165
|
+
"div",
|
|
166
|
+
{
|
|
167
|
+
style: {
|
|
168
|
+
fontSize: 14 * s,
|
|
169
|
+
fontStyle: "italic",
|
|
170
|
+
fontWeight: 400,
|
|
171
|
+
color: "rgba(0,0,0,0.45)",
|
|
172
|
+
lineHeight: 1.2,
|
|
173
|
+
marginBottom: 6 * s
|
|
174
|
+
},
|
|
175
|
+
children: brandName
|
|
176
|
+
}
|
|
177
|
+
),
|
|
178
|
+
renderMessageWithEmojiTail(message, 23 * s)
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
)
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// src/visual-system/scene-templates/brand-message.tsx
|
|
188
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
189
|
+
var BrandMessageTemplate = ({
|
|
190
|
+
variables,
|
|
191
|
+
style,
|
|
192
|
+
progress,
|
|
193
|
+
beatIntensity,
|
|
194
|
+
width,
|
|
195
|
+
height,
|
|
196
|
+
sceneDuration,
|
|
197
|
+
isPlaying = true,
|
|
198
|
+
safeZone,
|
|
199
|
+
backgroundEffect
|
|
200
|
+
}) => {
|
|
201
|
+
const brandName = stripPipe(style.brand.name ?? "Your brand");
|
|
202
|
+
const message = stripPipe(String(variables.message || ""));
|
|
203
|
+
const seed = (brandName + message).split("").reduce((acc, c) => acc + c.charCodeAt(0), 0);
|
|
204
|
+
return /* @__PURE__ */ jsxs2(
|
|
205
|
+
"div",
|
|
206
|
+
{
|
|
207
|
+
style: {
|
|
208
|
+
width,
|
|
209
|
+
height,
|
|
210
|
+
backgroundColor: "#000",
|
|
211
|
+
position: "relative",
|
|
212
|
+
overflow: "hidden",
|
|
213
|
+
// System fonts only — see BrandMessageBubble for the why
|
|
214
|
+
// (SVG-as-image can't load @font-face data: URLs, so the only
|
|
215
|
+
// way to get preview/export parity is to use a font the OS
|
|
216
|
+
// already has natively).
|
|
217
|
+
fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif'
|
|
218
|
+
},
|
|
219
|
+
children: [
|
|
220
|
+
/* @__PURE__ */ jsx2(
|
|
221
|
+
SceneBackground,
|
|
222
|
+
{
|
|
223
|
+
style,
|
|
224
|
+
progress,
|
|
225
|
+
sceneDuration,
|
|
226
|
+
width,
|
|
227
|
+
height,
|
|
228
|
+
...getMediaBackgroundProps(variables),
|
|
229
|
+
backgroundEffect,
|
|
230
|
+
seed,
|
|
231
|
+
isPlaying,
|
|
232
|
+
beatIntensity
|
|
233
|
+
}
|
|
234
|
+
),
|
|
235
|
+
/* @__PURE__ */ jsx2(
|
|
236
|
+
BrandMessageBubble,
|
|
237
|
+
{
|
|
238
|
+
progress,
|
|
239
|
+
sceneDuration: sceneDuration ?? 4,
|
|
240
|
+
brandName,
|
|
241
|
+
message,
|
|
242
|
+
width,
|
|
243
|
+
height,
|
|
244
|
+
safeZone
|
|
245
|
+
}
|
|
246
|
+
)
|
|
247
|
+
]
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
};
|
|
251
|
+
export {
|
|
252
|
+
BrandMessageTemplate
|
|
253
|
+
};
|