@vanillaskyai/video 0.8.7 → 0.9.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 (175) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/PUBLIC-API.md +5 -8
  3. package/dist/{builtin-server-CUYPIDE7.js → builtin-server-HW6HGXCZ.js} +2 -2
  4. package/dist/{catalog-types-BIhSpOWK.d.ts → catalog-types-WTbLP6Jh.d.ts} +5 -1
  5. package/dist/chapter-title-YRLIQY3V.js +7 -0
  6. package/dist/check-runtime.js +6 -15
  7. package/dist/{chunk-2USVB3CY.js → chunk-3ZTEFJIR.js} +285 -178
  8. package/dist/chunk-4YM2M62S.js +13 -0
  9. package/dist/chunk-77VY4O7A.js +390 -0
  10. package/dist/{chunk-MMUXVA47.js → chunk-7M56IUUX.js} +9 -8
  11. package/dist/chunk-7NZOMTAL.js +63 -0
  12. package/dist/{chunk-2DOLF4QN.js → chunk-AUPC6MDK.js} +12 -14
  13. package/dist/{chunk-352ZZCET.js → chunk-EGVQODKU.js} +2 -2
  14. package/dist/chunk-EWWCQFTI.js +18 -0
  15. package/dist/{chunk-MXZSDGZQ.js → chunk-G7IZBBWF.js} +14 -9
  16. package/dist/{chunk-KT3M7KDL.js → chunk-HKUI5BTB.js} +3 -3
  17. package/dist/{chunk-LMG3GHLL.js → chunk-IQMYK5DX.js} +29 -3
  18. package/dist/chunk-LH4BPALA.js +564 -0
  19. package/dist/{chunk-OWBT45EN.js → chunk-MQILEEXC.js} +1 -1
  20. package/dist/chunk-MXEYPK7M.js +552 -0
  21. package/dist/{chunk-AITKH6QT.js → chunk-OR52UMSF.js} +13 -39
  22. package/dist/{chunk-5SLENAJW.js → chunk-PAJ44TFW.js} +1 -2
  23. package/dist/{chunk-L7QGGKJ2.js → chunk-PDQFQIQW.js} +1 -1
  24. package/dist/{chunk-WJ6FLKNC.js → chunk-R3XAOMKP.js} +14 -0
  25. package/dist/{chunk-2OKB27TG.js → chunk-RXTN2CW6.js} +2 -2
  26. package/dist/{chunk-XWWLKRNU.js → chunk-TVIU23OM.js} +38 -49
  27. package/dist/{chunk-224QNWRA.js → chunk-UDIODEDK.js} +1 -5
  28. package/dist/{chunk-3VRMKFM7.js → chunk-ZDJNFA52.js} +11 -24
  29. package/dist/cinema-media-YQHSIFDA.js +11 -0
  30. package/dist/cli.js +18 -9
  31. package/dist/comparison-RZMMHZR2.js +27 -0
  32. package/dist/compose-video-TBFTONUC.js +12 -0
  33. package/dist/editorial-timeline-OZX7OS6G.js +36 -0
  34. package/dist/{events-BQ6z264n.d.ts → events-B4YCc4vc.d.ts} +1 -1
  35. package/dist/focus-cards-TJ72BT7U.js +20 -0
  36. package/dist/index.d.ts +4 -6
  37. package/dist/index.js +3 -7
  38. package/dist/key-figure-GYENXKH3.js +20 -0
  39. package/dist/{kit-tQnCPMOM.d.ts → kit-DrRpdn0p.d.ts} +2 -2
  40. package/dist/mobile-message-UZUPIKHD.js +49 -0
  41. package/dist/{preload-media-LJXWKTWG.js → preload-media-CFTZIMZL.js} +1 -1
  42. package/dist/quote-EW5HQA6H.js +23 -0
  43. package/dist/react.d.ts +21 -11
  44. package/dist/react.js +608 -851
  45. package/dist/scene-video-backdrop-PCTARAAJ.js +7 -0
  46. package/dist/server.d.ts +7 -8
  47. package/dist/server.js +91 -74
  48. package/dist/{system-prompt-RRXIWDDD.js → system-prompt-SYRT5DWM.js} +1 -1
  49. package/dist/template-catalog.d.ts +257 -16
  50. package/dist/template-catalog.js +1 -1
  51. package/dist/templates.d.ts +5 -5
  52. package/dist/test.d.ts +3 -3
  53. package/dist/test.js +18 -18
  54. package/dist/text-stream-LD364KBI.js +9 -0
  55. package/dist/{types-DWFO6qca.d.ts → types-CdBmNTGD.d.ts} +1 -1
  56. package/dist/{types-CEh9eUFu.d.ts → types-DdZw4GRQ.d.ts} +17 -48
  57. package/dist/validate-4OUD2CLX.js +10 -0
  58. package/docs/architecture.md +1 -1
  59. package/docs/concepts.md +1 -1
  60. package/docs/custom-templates.md +13 -28
  61. package/docs/customization.md +11 -59
  62. package/docs/getting-started.md +2 -2
  63. package/docs/immersive-interface.md +3 -4
  64. package/docs/maintainers/cinematic-migration.md +34 -0
  65. package/docs/media-and-audio.md +14 -14
  66. package/docs/motion-and-effects.md +6 -14
  67. package/docs/persistence.md +3 -3
  68. package/docs/production.md +11 -9
  69. package/docs/provider-integration.md +9 -16
  70. package/docs/reference/design-system.html +3 -3
  71. package/docs/reference/protocol.md +14 -4
  72. package/docs/testing.md +1 -1
  73. package/package.json +6 -3
  74. package/registry/items/backgrounds.json +1 -1
  75. package/registry/items/chapterTitle.json +80 -0
  76. package/registry/items/cinemaMedia.json +136 -0
  77. package/registry/items/comparison.json +101 -0
  78. package/registry/items/editorialTimeline.json +105 -0
  79. package/registry/items/focusCards.json +90 -0
  80. package/registry/items/keyFigure.json +97 -0
  81. package/registry/items/mobileMessage.json +153 -0
  82. package/registry/items/quote.json +94 -0
  83. package/registry/items/template-context.json +1 -1
  84. package/registry/items/theme.json +1 -1
  85. package/starters/video-chat/README.md +24 -26
  86. package/starters/video-chat/package.json +1 -1
  87. package/starters/video-chat/providers/video.ts +6 -5
  88. package/starters/video-chat/stock.ts +35 -151
  89. package/styles/fonts/OFL.txt +93 -0
  90. package/styles/fonts/manifest.json +66 -0
  91. package/styles/fonts/roboto-v51-cyrillic-ext.woff2 +0 -0
  92. package/styles/fonts/roboto-v51-cyrillic.woff2 +0 -0
  93. package/styles/fonts/roboto-v51-greek-ext.woff2 +0 -0
  94. package/styles/fonts/roboto-v51-greek.woff2 +0 -0
  95. package/styles/fonts/roboto-v51-latin-ext.woff2 +0 -0
  96. package/styles/fonts/roboto-v51-latin.woff2 +0 -0
  97. package/styles/fonts/roboto-v51-math.woff2 +0 -0
  98. package/styles/fonts/roboto-v51-symbols.woff2 +0 -0
  99. package/styles/fonts/roboto-v51-vietnamese.woff2 +0 -0
  100. package/styles/fonts/roboto.css +91 -0
  101. package/styles/video-chat.css +30 -23
  102. package/dist/bg-confetti-HITCGLGD.js +0 -89
  103. package/dist/bg-emoji-VU4UZYZN.js +0 -150
  104. package/dist/bg-media-L34PDQXJ.js +0 -106
  105. package/dist/brand-message-FUJ4STFO.js +0 -256
  106. package/dist/chart-bar-EGPHJATL.js +0 -310
  107. package/dist/chart-counter-5FFWQNZO.js +0 -306
  108. package/dist/chart-progress-ring-JMXQLMLC.js +0 -302
  109. package/dist/chunk-4UNKZEAT.js +0 -3575
  110. package/dist/chunk-5CDAM24P.js +0 -31
  111. package/dist/chunk-AOWSXU2K.js +0 -18
  112. package/dist/chunk-CJ7F2CE6.js +0 -104
  113. package/dist/chunk-FRN6WKHA.js +0 -185
  114. package/dist/chunk-G5JPHBX7.js +0 -336
  115. package/dist/chunk-L5BTTCZV.js +0 -97
  116. package/dist/chunk-P22HHFDK.js +0 -43
  117. package/dist/chunk-PP3MCPN4.js +0 -1998
  118. package/dist/chunk-QAAO7OAY.js +0 -19
  119. package/dist/chunk-S7HFLYNN.js +0 -35
  120. package/dist/chunk-W3VDIBGR.js +0 -217
  121. package/dist/chunk-XGRA2MUV.js +0 -242
  122. package/dist/chunk-XTOXFMLM.js +0 -105
  123. package/dist/chunk-YJJC4N4D.js +0 -761
  124. package/dist/compose-video-2NFH4DZY.js +0 -13
  125. package/dist/cta-logo-YR7LYUR5.js +0 -212
  126. package/dist/cta-media-DQJBKUO2.js +0 -221
  127. package/dist/incoming-call-54KQ7O5A.js +0 -323
  128. package/dist/infographic-before-after-ROS52GOW.js +0 -460
  129. package/dist/infographic-feature-list-E7MGUDAN.js +0 -272
  130. package/dist/infographic-problem-solution-3S6NGO5N.js +0 -343
  131. package/dist/infographic-stat-row-SYB7AB7H.js +0 -247
  132. package/dist/infographic-steps-KCE6JWE2.js +0 -406
  133. package/dist/prompt-input-MHX4O42G.js +0 -239
  134. package/dist/reaction-SLEGR3BE.js +0 -122
  135. package/dist/scene-video-backdrop-XFPX4O3I.js +0 -10
  136. package/dist/showcase-code-2HLAVKBM.js +0 -357
  137. package/dist/showcase-phone-Q4HEO4LH.js +0 -278
  138. package/dist/showcase-terminal-DL45LUFG.js +0 -312
  139. package/dist/showcase-web-2QZO73FZ.js +0 -396
  140. package/dist/social-conversation-75SD2637.js +0 -695
  141. package/dist/social-milestone-GEFUQSBF.js +0 -296
  142. package/dist/social-notification-FJ5VHVLK.js +0 -247
  143. package/dist/social-review-stack-KXQCKFRP.js +0 -242
  144. package/dist/social-testimonial-JZ7CHC7S.js +0 -287
  145. package/dist/social-tweet-UCDXM25F.js +0 -298
  146. package/dist/text-stream-54LXABJW.js +0 -10
  147. package/dist/validate-T7GBU2YF.js +0 -8
  148. package/registry/items/barChart.json +0 -245
  149. package/registry/items/beforeAfter.json +0 -180
  150. package/registry/items/bigNumber.json +0 -232
  151. package/registry/items/brandMessage.json +0 -164
  152. package/registry/items/cardList.json +0 -214
  153. package/registry/items/chatMessenger.json +0 -151
  154. package/registry/items/chatWhatsapp.json +0 -151
  155. package/registry/items/codeEditor.json +0 -191
  156. package/registry/items/confetti.json +0 -107
  157. package/registry/items/ctaLogo.json +0 -167
  158. package/registry/items/ctaMedia.json +0 -200
  159. package/registry/items/emojiBurst.json +0 -101
  160. package/registry/items/incomingCall.json +0 -177
  161. package/registry/items/media.json +0 -187
  162. package/registry/items/milestone.json +0 -212
  163. package/registry/items/notification.json +0 -189
  164. package/registry/items/phoneMockup.json +0 -261
  165. package/registry/items/problemSolution.json +0 -193
  166. package/registry/items/progressRing.json +0 -206
  167. package/registry/items/promptInput.json +0 -155
  168. package/registry/items/reaction.json +0 -176
  169. package/registry/items/reviewStack.json +0 -231
  170. package/registry/items/steps.json +0 -215
  171. package/registry/items/terminal.json +0 -219
  172. package/registry/items/testimonial.json +0 -171
  173. package/registry/items/tripleStats.json +0 -235
  174. package/registry/items/tweet.json +0 -210
  175. package/registry/items/webMockup.json +0 -280
@@ -1,310 +0,0 @@
1
- import {
2
- SceneBackground,
3
- getMediaBackgroundProps
4
- } from "./chunk-MXZSDGZQ.js";
5
- import {
6
- TemplateText
7
- } from "./chunk-YJJC4N4D.js";
8
- import "./chunk-L5BTTCZV.js";
9
- import "./chunk-FRN6WKHA.js";
10
- import {
11
- TOP_TEXT_AREA_RATIO,
12
- withOpacity
13
- } from "./chunk-W3VDIBGR.js";
14
- import {
15
- SPRING_SNAPPY,
16
- interpolate,
17
- spring
18
- } from "./chunk-XTOXFMLM.js";
19
- import {
20
- hasSceneMedia
21
- } from "./chunk-224QNWRA.js";
22
- import "./chunk-5CDAM24P.js";
23
- import {
24
- resolveTokens
25
- } from "./chunk-XWWLKRNU.js";
26
-
27
- // src/visual-system/primitives/charts/BarChart.tsx
28
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
29
- var MAX_BAR_ITEMS = 6;
30
- function exactValue(value) {
31
- return String(value);
32
- }
33
- var BarChart = ({
34
- progress,
35
- data,
36
- width,
37
- height,
38
- chartColor = "#ffffff",
39
- textColor = "#ffffff",
40
- beatIntensity = 0
41
- }) => {
42
- const values = data.filter(({ value }) => Number.isFinite(value)).slice(0, MAX_BAR_ITEMS);
43
- const s = Math.min(width, height) / 1080;
44
- const portrait = height > width;
45
- const chartWidth = width * (portrait ? 0.88 : 0.84);
46
- const chartHeight = height * (portrait ? 0.56 : 0.52);
47
- const bottom = (portrait ? 112 : 60) * s;
48
- const labelHeight = (portrait ? 94 : 66) * s;
49
- const valueReserve = (portrait ? 52 : 44) * s;
50
- const maxBarHeight = chartHeight - labelHeight - valueReserve;
51
- const gap = (portrait ? 14 : 20) * s;
52
- const barCount = Math.max(values.length, 1);
53
- const itemWidth = (chartWidth - gap * (barCount - 1)) / barCount;
54
- const barWidth = Math.max(itemWidth * 0.68, 2 * s);
55
- const maxValue = Math.max(1, ...values.map(({ value }) => Math.max(0, value)));
56
- const beatScale = 1 + beatIntensity * 0.03;
57
- return /* @__PURE__ */ jsxs(Fragment, { children: [
58
- /* @__PURE__ */ jsx(
59
- "div",
60
- {
61
- role: "img",
62
- "aria-label": values.map(({ label, value }) => `${label || "Value"}: ${exactValue(value)}`).join(", "),
63
- style: {
64
- position: "absolute",
65
- bottom,
66
- left: (width - chartWidth) / 2,
67
- width: chartWidth,
68
- height: chartHeight,
69
- display: "flex",
70
- alignItems: "flex-end",
71
- gap
72
- },
73
- children: values.map(({ label, value }, index) => {
74
- const barStart = 0.06 + index * 0.05;
75
- const barProgress = interpolate(progress, [barStart, barStart + 0.34], [0, 1], {
76
- extrapolateLeft: "clamp",
77
- extrapolateRight: "clamp"
78
- });
79
- const springValue = spring(barProgress, SPRING_SNAPPY);
80
- const targetHeight = Math.max(0, value) / maxValue * maxBarHeight;
81
- return /* @__PURE__ */ jsxs(
82
- "div",
83
- {
84
- "data-bar-chart-item": "true",
85
- style: {
86
- width: itemWidth,
87
- height: chartHeight,
88
- display: "flex",
89
- flexDirection: "column",
90
- justifyContent: "flex-end",
91
- alignItems: "center",
92
- minWidth: 0
93
- },
94
- children: [
95
- /* @__PURE__ */ jsx(
96
- "div",
97
- {
98
- style: {
99
- width: "100%",
100
- height: maxBarHeight + valueReserve,
101
- display: "flex",
102
- alignItems: "flex-end",
103
- justifyContent: "center"
104
- },
105
- children: /* @__PURE__ */ jsx(
106
- "div",
107
- {
108
- style: {
109
- position: "relative",
110
- width: barWidth,
111
- height: springValue * targetHeight,
112
- background: `linear-gradient(to top, ${withOpacity(chartColor, 0.82)}, ${withOpacity(chartColor, 0.42)})`,
113
- border: `1px solid ${withOpacity(chartColor, 0.7)}`,
114
- borderRadius: `${10 * s}px ${10 * s}px 0 0`,
115
- boxShadow: `0 0 ${24 * s}px ${withOpacity(chartColor, 0.18)}`,
116
- transform: `scaleY(${beatScale})`,
117
- transformOrigin: "bottom"
118
- },
119
- children: /* @__PURE__ */ jsx(
120
- "div",
121
- {
122
- "data-bar-chart-value": "true",
123
- style: {
124
- position: "absolute",
125
- bottom: "100%",
126
- left: "50%",
127
- transform: `translate(-50%, ${-10 * s}px)`,
128
- color: textColor,
129
- fontSize: (portrait ? 34 : 30) * s,
130
- lineHeight: 1,
131
- fontWeight: 750,
132
- fontVariantNumeric: "tabular-nums",
133
- whiteSpace: "nowrap",
134
- opacity: barProgress,
135
- textShadow: `0 ${2 * s}px ${8 * s}px rgba(0,0,0,0.55)`
136
- },
137
- children: exactValue(value)
138
- }
139
- )
140
- }
141
- )
142
- }
143
- ),
144
- /* @__PURE__ */ jsx(
145
- "div",
146
- {
147
- "data-bar-chart-label": "true",
148
- style: {
149
- width: "100%",
150
- height: labelHeight,
151
- paddingTop: 14 * s,
152
- boxSizing: "border-box",
153
- color: withOpacity(textColor, 0.9),
154
- fontSize: (portrait ? 24 : 22) * s,
155
- lineHeight: 1.15,
156
- fontWeight: 650,
157
- textAlign: "center",
158
- overflow: "hidden",
159
- overflowWrap: "anywhere",
160
- opacity: barProgress
161
- },
162
- children: label
163
- }
164
- )
165
- ]
166
- },
167
- `${label}-${index}`
168
- );
169
- })
170
- }
171
- ),
172
- /* @__PURE__ */ jsx(
173
- "div",
174
- {
175
- style: {
176
- position: "absolute",
177
- bottom: 0,
178
- left: 0,
179
- right: 0,
180
- height: chartHeight * 0.7,
181
- background: `linear-gradient(to top, ${withOpacity(chartColor, 0.07)}, transparent)`,
182
- pointerEvents: "none"
183
- }
184
- }
185
- )
186
- ] });
187
- };
188
-
189
- // src/visual-system/scene-templates/chart-bar.tsx
190
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
191
- function parseBarDatum(value) {
192
- if (typeof value === "number") {
193
- return Number.isFinite(value) ? { label: "", value } : void 0;
194
- }
195
- if (typeof value === "object" && value !== null) {
196
- const datum = value;
197
- const numberValue2 = Number(datum.value);
198
- if (!Number.isFinite(numberValue2)) return void 0;
199
- return { label: String(datum.label ?? "").trim(), value: numberValue2 };
200
- }
201
- if (typeof value !== "string") return void 0;
202
- const trimmed = value.trim();
203
- if (!trimmed) return void 0;
204
- const separator = trimmed.lastIndexOf(":");
205
- const label = separator >= 0 ? trimmed.slice(0, separator).trim() : "";
206
- const numberValue = Number(separator >= 0 ? trimmed.slice(separator + 1).trim() : trimmed);
207
- return Number.isFinite(numberValue) ? { label, value: numberValue } : void 0;
208
- }
209
- function parseBarData(value) {
210
- let items;
211
- if (Array.isArray(value)) {
212
- items = value;
213
- } else if (typeof value === "string") {
214
- const trimmed = value.trim();
215
- if (!trimmed) return [];
216
- try {
217
- const parsed = JSON.parse(trimmed);
218
- items = Array.isArray(parsed) ? parsed : [trimmed];
219
- } catch {
220
- items = trimmed.split(",");
221
- }
222
- } else {
223
- items = [value];
224
- }
225
- return items.map(parseBarDatum).filter((datum) => datum !== void 0);
226
- }
227
- var ChartBarTemplate = ({
228
- variables,
229
- style,
230
- progress,
231
- motionProgress = progress,
232
- beatIntensity,
233
- width,
234
- height,
235
- safeZone,
236
- sceneDuration,
237
- backgroundEffect,
238
- isPlaying = true
239
- }) => {
240
- const { primary, foreground, font } = resolveTokens(style);
241
- const chartColor = primary;
242
- const textColor = foreground;
243
- const textsRaw = String(variables.texts || "");
244
- const data = parseBarData(variables.bars);
245
- return /* @__PURE__ */ jsxs2(
246
- "div",
247
- {
248
- style: {
249
- width,
250
- height,
251
- backgroundColor: "var(--vanillasky-template-surface, #000)",
252
- position: "relative",
253
- overflow: "hidden",
254
- fontFamily: font
255
- },
256
- children: [
257
- /* @__PURE__ */ jsx2(
258
- SceneBackground,
259
- {
260
- style,
261
- progress,
262
- sceneDuration,
263
- width,
264
- height,
265
- ...getMediaBackgroundProps(variables),
266
- backgroundEffect,
267
- seed: textsRaw,
268
- isPlaying,
269
- beatIntensity
270
- }
271
- ),
272
- /* @__PURE__ */ jsx2(
273
- BarChart,
274
- {
275
- progress,
276
- data,
277
- width,
278
- height,
279
- chartColor,
280
- textColor,
281
- beatIntensity
282
- }
283
- ),
284
- /* @__PURE__ */ jsx2("div", { style: { position: "absolute", top: 0, left: 0, right: 0, height: height * TOP_TEXT_AREA_RATIO, overflow: "visible" }, children: /* @__PURE__ */ jsx2(
285
- TemplateText,
286
- {
287
- overMedia: hasSceneMedia(variables),
288
- motionProgress,
289
- typeTreatment: resolveTokens(style).preset.type,
290
- archetype: "subtle",
291
- text: String(variables.texts ?? ""),
292
- progress,
293
- sceneDuration: sceneDuration ?? 3,
294
- width,
295
- height,
296
- position: "top",
297
- sizeRole: "headline",
298
- safeZone,
299
- font,
300
- color: textColor,
301
- beatIntensity
302
- }
303
- ) })
304
- ]
305
- }
306
- );
307
- };
308
- export {
309
- ChartBarTemplate
310
- };
@@ -1,306 +0,0 @@
1
- import {
2
- getResponsiveFontSize
3
- } from "./chunk-S7HFLYNN.js";
4
- import {
5
- ConfettiLayer
6
- } from "./chunk-CJ7F2CE6.js";
7
- import "./chunk-QAAO7OAY.js";
8
- import {
9
- SceneBackground,
10
- getMediaBackgroundProps
11
- } from "./chunk-MXZSDGZQ.js";
12
- import {
13
- TemplateText
14
- } from "./chunk-YJJC4N4D.js";
15
- import "./chunk-L5BTTCZV.js";
16
- import "./chunk-FRN6WKHA.js";
17
- import {
18
- TOP_TEXT_AREA_RATIO,
19
- withOpacity
20
- } from "./chunk-W3VDIBGR.js";
21
- import {
22
- interpolate,
23
- spring
24
- } from "./chunk-XTOXFMLM.js";
25
- import {
26
- hasSceneMedia
27
- } from "./chunk-224QNWRA.js";
28
- import "./chunk-5CDAM24P.js";
29
- import {
30
- MEDIA_TEXT_SHADOW,
31
- TOKEN_DEFAULTS,
32
- resolveTokens
33
- } from "./chunk-XWWLKRNU.js";
34
-
35
- // src/visual-system/primitives/typography/CountUpNumber.tsx
36
- import { jsx, jsxs } from "react/jsx-runtime";
37
- function suppliedDecimalPlaces(value) {
38
- if (!Number.isFinite(value) || Number.isInteger(value)) return 0;
39
- const normalized = String(value).toLowerCase();
40
- if (normalized.includes("e-")) {
41
- const [coefficient, exponentText] = normalized.split("e-");
42
- const coefficientDecimals = coefficient.split(".")[1]?.length ?? 0;
43
- return Math.min(6, Number(exponentText) + coefficientDecimals);
44
- }
45
- return Math.min(6, normalized.split(".")[1]?.length ?? 0);
46
- }
47
- var CountUpNumber = ({
48
- progress,
49
- motionProgress = progress,
50
- target,
51
- decimalPlaces: decimalPlacesOverride,
52
- prefix = "",
53
- unit = "",
54
- label,
55
- width,
56
- height,
57
- numberColor = "#ffffff",
58
- labelColor = "rgba(255,255,255,0.6)",
59
- font = TOKEN_DEFAULTS.font,
60
- hasMediaShadow = false,
61
- beatIntensity = 0,
62
- labelFontSize
63
- }) => {
64
- const s = Math.min(width, height) / 1080;
65
- const displayValue = interpolate(
66
- progress,
67
- [0, 0.55],
68
- [0, target],
69
- { extrapolateRight: "clamp" }
70
- );
71
- const decimalPlaces = Number.isFinite(decimalPlacesOverride) ? Math.max(0, Math.min(6, Math.trunc(decimalPlacesOverride ?? 0))) : suppliedDecimalPlaces(target);
72
- const formattedNumber = displayValue.toLocaleString("en-US", {
73
- minimumFractionDigits: decimalPlaces,
74
- maximumFractionDigits: decimalPlaces
75
- });
76
- const formattedTarget = target.toLocaleString("en-US", {
77
- minimumFractionDigits: decimalPlaces,
78
- maximumFractionDigits: decimalPlaces
79
- });
80
- const semanticValueIsTransient = formattedNumber !== formattedTarget;
81
- const fullNumberStr = `${prefix}${formattedNumber}${unit}`;
82
- const baseSize = 140 * s;
83
- const charCount = fullNumberStr.length;
84
- const numberFontSize = charCount <= 6 ? baseSize : baseSize * Math.max(0.35, 6 / charCount);
85
- const numberSpring = spring(
86
- interpolate(motionProgress, [0, 0.22], [0, 1], {
87
- extrapolateLeft: "clamp",
88
- extrapolateRight: "clamp"
89
- }),
90
- { damping: 9, stiffness: 200 }
91
- );
92
- const numberScale = interpolate(numberSpring, [0, 1], [0.3, 1]);
93
- const numberSettled = numberSpring > 0.99;
94
- const breathe = numberSettled ? 1 + Math.sin(progress * Math.PI * 4) * 8e-3 : 1;
95
- const beatScale = 1 + beatIntensity * 0.03;
96
- const labelOpacity = interpolate(
97
- motionProgress,
98
- [0.2, 0.4],
99
- [0, 1],
100
- { extrapolateLeft: "clamp", extrapolateRight: "clamp" }
101
- );
102
- const mediaTextShadow = hasMediaShadow ? MEDIA_TEXT_SHADOW : void 0;
103
- const finalLabelFontSize = labelFontSize ?? 36 * s * 1.3;
104
- return /* @__PURE__ */ jsxs(
105
- "div",
106
- {
107
- style: {
108
- position: "absolute",
109
- top: 0,
110
- left: 0,
111
- right: 0,
112
- bottom: 0,
113
- display: "flex",
114
- flexDirection: "column",
115
- alignItems: "center",
116
- justifyContent: "center",
117
- pointerEvents: "none",
118
- // font is intentionally NOT set here — caller's outer wrapper
119
- // (chart-counter root div or composed.tsx root) sets fontFamily
120
- // and the children inherit. void to silence unused-arg lint.
121
- ...(void font, {})
122
- },
123
- children: [
124
- /* @__PURE__ */ jsxs(
125
- "div",
126
- {
127
- "data-transition-semantic": semanticValueIsTransient ? "transient" : void 0,
128
- style: {
129
- fontSize: numberFontSize,
130
- fontWeight: 800,
131
- color: numberColor,
132
- textAlign: "center",
133
- lineHeight: 1.1,
134
- position: "relative",
135
- zIndex: 1,
136
- maxWidth: "90%",
137
- overflow: "visible",
138
- ...semanticValueIsTransient ? { visibility: "var(--vanillasky-transition-semantic-visibility,visible)" } : {},
139
- transform: `scale(${numberScale * beatScale * breathe})`,
140
- ...mediaTextShadow ? { textShadow: mediaTextShadow } : {}
141
- },
142
- children: [
143
- prefix,
144
- formattedNumber,
145
- unit
146
- ]
147
- }
148
- ),
149
- /* @__PURE__ */ jsx(
150
- "div",
151
- {
152
- style: {
153
- opacity: labelOpacity,
154
- fontSize: finalLabelFontSize,
155
- color: labelColor,
156
- textTransform: "uppercase",
157
- letterSpacing: 2 * s,
158
- textAlign: "center",
159
- marginTop: 12 * s,
160
- position: "relative",
161
- zIndex: 1,
162
- ...mediaTextShadow ? { textShadow: mediaTextShadow } : {}
163
- },
164
- children: label
165
- }
166
- )
167
- ]
168
- }
169
- );
170
- };
171
-
172
- // src/visual-system/scene-templates/chart-counter.tsx
173
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
174
- var ChartCounterTemplate = ({
175
- variables,
176
- style,
177
- progress,
178
- motionProgress = progress,
179
- beatIntensity,
180
- width,
181
- height,
182
- safeZone,
183
- sceneDuration,
184
- isPlaying = true,
185
- backgroundEffect
186
- }) => {
187
- const s = Math.min(width, height) / 1080;
188
- const { primary, foreground, font, background } = resolveTokens(style);
189
- const chartColor = primary;
190
- const textColor = foreground;
191
- const textsRaw = String(variables.texts || "");
192
- const gradSeed = textsRaw.split("").reduce((acc, c) => acc + c.charCodeAt(0), 0);
193
- const parsedValue = Number(variables.value);
194
- const targetValue = Number.isFinite(parsedValue) ? parsedValue : 1e3;
195
- const parsedDecimalPlaces = Number(variables.decimalPlaces);
196
- const decimalPlaces = Number.isFinite(parsedDecimalPlaces) ? Math.max(0, Math.min(6, Math.trunc(parsedDecimalPlaces))) : void 0;
197
- const label = String(variables.label || "Total users");
198
- const prefix = String(variables.prefix || "");
199
- const unit = String(variables.unit || "");
200
- const hasMedia = !!String(variables.mediaUrl || "").trim() && String(variables.mediaType || "auto") !== "gradient";
201
- const numberColor = hasMedia ? "#ffffff" : textColor;
202
- const labelColor = hasMedia ? "#ffffff" : withOpacity(textColor, 0.6);
203
- const confettiActive = variables.confetti === true && motionProgress >= 0.55;
204
- const confettiProgress = confettiActive ? (motionProgress - 0.55) / 0.45 : 0;
205
- const labelFontSize = getResponsiveFontSize(label, width, "subtitle", height) * 1.3;
206
- return /* @__PURE__ */ jsxs2(
207
- "div",
208
- {
209
- style: {
210
- width,
211
- height,
212
- backgroundColor: "var(--vanillasky-template-surface, #000)",
213
- position: "relative",
214
- overflow: "hidden",
215
- fontFamily: font
216
- },
217
- children: [
218
- /* @__PURE__ */ jsx2(
219
- SceneBackground,
220
- {
221
- style,
222
- progress,
223
- sceneDuration,
224
- width,
225
- height,
226
- ...getMediaBackgroundProps(variables),
227
- backgroundEffect,
228
- seed: gradSeed,
229
- isPlaying,
230
- beatIntensity
231
- }
232
- ),
233
- /* @__PURE__ */ jsx2(
234
- "div",
235
- {
236
- style: {
237
- position: "absolute",
238
- top: "50%",
239
- left: "50%",
240
- transform: "translate(-50%, -55%)",
241
- width: 500 * s,
242
- height: 500 * s,
243
- borderRadius: "50%",
244
- background: `radial-gradient(circle, ${withOpacity(primary, 0.15)} 0%, transparent 70%)`,
245
- pointerEvents: "none"
246
- }
247
- }
248
- ),
249
- confettiActive && /* @__PURE__ */ jsx2(
250
- ConfettiLayer,
251
- {
252
- progress: confettiProgress,
253
- width,
254
- height,
255
- beatIntensity,
256
- bgColor: hasMedia ? void 0 : background.type === "solid" ? background.color : background.colors[1]
257
- }
258
- ),
259
- /* @__PURE__ */ jsx2("div", { style: { position: "absolute", top: 0, left: 0, right: 0, height: height * TOP_TEXT_AREA_RATIO, overflow: "visible" }, children: /* @__PURE__ */ jsx2(
260
- TemplateText,
261
- {
262
- overMedia: hasSceneMedia(variables),
263
- motionProgress,
264
- typeTreatment: resolveTokens(style).preset.type,
265
- archetype: "subtle",
266
- text: String(variables.texts ?? ""),
267
- progress,
268
- sceneDuration: sceneDuration ?? 3,
269
- width,
270
- height,
271
- position: "top",
272
- sizeRole: "headline",
273
- safeZone,
274
- font,
275
- color: textColor,
276
- beatIntensity
277
- }
278
- ) }),
279
- /* @__PURE__ */ jsx2(
280
- CountUpNumber,
281
- {
282
- progress,
283
- motionProgress,
284
- target: targetValue,
285
- decimalPlaces,
286
- prefix,
287
- unit,
288
- label,
289
- width,
290
- height,
291
- numberColor,
292
- labelColor,
293
- chartColor,
294
- font,
295
- hasMediaShadow: hasMedia,
296
- beatIntensity,
297
- labelFontSize
298
- }
299
- )
300
- ]
301
- }
302
- );
303
- };
304
- export {
305
- ChartCounterTemplate
306
- };