@microfox/remotion 1.2.0 → 1.2.2

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/dist/index.js ADDED
@@ -0,0 +1,4641 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/index.ts
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
+ AudioAtom: () => Atom5,
33
+ AudioAtomConfig: () => config13,
34
+ BaseLayout: () => Layout,
35
+ BaseLayoutConfig: () => config8,
36
+ BlurEffect: () => BlurEffect,
37
+ BlurEffectConfig: () => config2,
38
+ ComponentRenderer: () => ComponentRenderer,
39
+ Composition: () => Composition,
40
+ CompositionLayout: () => CompositionLayout,
41
+ CompositionProvider: () => CompositionProvider,
42
+ Frame: () => Frame,
43
+ GenericEffectPresets: () => GenericEffectPresets,
44
+ ImageAtom: () => Atom2,
45
+ ImageAtomConfig: () => config10,
46
+ LoopEffect: () => LoopEffect,
47
+ LoopEffectConfig: () => config3,
48
+ LottieAtom: () => Atom6,
49
+ LottieAtomConfig: () => config14,
50
+ NextjsLogo: () => NextjsLogo,
51
+ PanEffect: () => PanEffect,
52
+ PanEffectConfig: () => config4,
53
+ Player: () => Player,
54
+ Rings: () => Rings,
55
+ RippleOutLayout: () => RippleOutLayout,
56
+ SceneFrame: () => SceneFrame,
57
+ ShakeEffect: () => ShakeEffect,
58
+ ShakeEffectConfig: () => config6,
59
+ ShapeAtom: () => Atom,
60
+ ShapeAtomConfig: () => config9,
61
+ StretchEffect: () => StretchEffect,
62
+ StretchEffectConfig: () => config7,
63
+ TextAtom: () => Atom3,
64
+ TextAtomConfig: () => config11,
65
+ TextFade: () => TextFade,
66
+ UniversalEffect: () => UniversalEffect,
67
+ UniversalEffectProvider: () => UniversalEffectProvider,
68
+ VideoAtom: () => Atom4,
69
+ VideoAtomConfig: () => config12,
70
+ Waveform: () => Waveform,
71
+ WaveformCircle: () => WaveformCircle,
72
+ WaveformHistogram: () => WaveformHistogram,
73
+ WaveformHistogramRanged: () => WaveformHistogramRanged,
74
+ WaveformLine: () => WaveformLine,
75
+ WaveformPresets: () => WaveformPresets,
76
+ ZoomEffect: () => ZoomEffect,
77
+ ZoomEffectConfig: () => config5,
78
+ buildLayoutHook: () => buildLayoutHook,
79
+ calculateCircularPosition: () => calculateCircularPosition,
80
+ calculateComponentDuration: () => calculateComponentDuration,
81
+ calculateCompositionLayoutMetadata: () => calculateCompositionLayoutMetadata,
82
+ calculateDuration: () => calculateDuration,
83
+ calculateGridPosition: () => calculateGridPosition,
84
+ calculateHierarchy: () => calculateHierarchy,
85
+ calculateTimingWithInheritance: () => calculateTimingWithInheritance,
86
+ clearFontCache: () => clearFontCache,
87
+ componentRegistry: () => componentRegistry,
88
+ createImageDataWithProxy: () => createImageDataWithProxy,
89
+ createImageProxyUrl: () => createImageProxyUrl,
90
+ createRootContext: () => createRootContext,
91
+ findComponentById: () => findComponentById,
92
+ findMatchingComponents: () => findMatchingComponents,
93
+ findMatchingComponentsByQuery: () => findMatchingComponentsByQuery,
94
+ findParentComponent: () => findParentComponent,
95
+ getComponent: () => getComponent,
96
+ getComponentConfig: () => getComponentConfig,
97
+ getComponentWithConfig: () => getComponentWithConfig,
98
+ getLoadedFontFamily: () => getLoadedFontFamily,
99
+ getLoadedFonts: () => getLoadedFonts,
100
+ getNormalizedFontName: () => getNormalizedFontName,
101
+ isFontAvailable: () => isFontAvailable,
102
+ isFontLoaded: () => isFontLoaded,
103
+ loadGoogleFont: () => loadGoogleFont,
104
+ loadMultipleFonts: () => loadMultipleFonts,
105
+ mergeContexts: () => mergeContexts,
106
+ needsProxying: () => needsProxying,
107
+ nextjsLogoConfig: () => nextjsLogoConfig,
108
+ preloadCommonFonts: () => preloadCommonFonts,
109
+ registerComponent: () => registerComponent,
110
+ registerEffect: () => registerEffect,
111
+ registerPackage: () => registerPackage,
112
+ ringsConfig: () => ringsConfig,
113
+ rippleOutLayoutConfig: () => rippleOutLayoutConfig,
114
+ setDurationsInContext: () => setDurationsInContext,
115
+ textFadeConfig: () => textFadeConfig,
116
+ useAnimatedStyles: () => useAnimatedStyles,
117
+ useBoundaryCalculation: () => useBoundaryCalculation,
118
+ useComponentRegistry: () => useComponentRegistry,
119
+ useComposition: () => useComposition,
120
+ useFont: () => useFont,
121
+ useFontLoader: () => useFontLoader,
122
+ useHasUniversalEffectProvider: () => useHasUniversalEffectProvider,
123
+ useRenderContext: () => useRenderContext,
124
+ useRippleOutLayout: () => useRippleOutLayout,
125
+ useUniversalEffect: () => useUniversalEffect,
126
+ useUniversalEffectOptional: () => useUniversalEffectOptional,
127
+ useWaveformContext: () => useWaveformContext,
128
+ useWaveformData: () => useWaveformData
129
+ });
130
+ module.exports = __toCommonJS(index_exports);
131
+
132
+ // src/core/registry/componentRegistry.ts
133
+ var ComponentRegistryManager = class {
134
+ constructor() {
135
+ this.registry = {};
136
+ this.packageRegistry = {};
137
+ }
138
+ registerComponent(name, component, type, config15 = { displayName: "" }, packageName) {
139
+ this.registry[name] = { component, config: config15 };
140
+ if (packageName) {
141
+ if (!this.packageRegistry[packageName]) {
142
+ this.packageRegistry[packageName] = {};
143
+ }
144
+ this.packageRegistry[packageName][name] = { component, config: config15 };
145
+ }
146
+ }
147
+ registerEffect(name, component, config15 = { displayName: "" }, packageName) {
148
+ this.registerComponent(
149
+ name?.includes("effect-") ? name : `effect-${name}`,
150
+ component,
151
+ "layout",
152
+ config15,
153
+ packageName
154
+ );
155
+ }
156
+ getComponent(name) {
157
+ return this.registry[name]?.component;
158
+ }
159
+ getComponentConfig(name) {
160
+ return this.registry[name]?.config;
161
+ }
162
+ getComponentWithConfig(name) {
163
+ return this.registry[name];
164
+ }
165
+ registerPackage(packageName, components) {
166
+ this.packageRegistry[packageName] = components;
167
+ Object.entries(components).forEach(([name, { component, config: config15 }]) => {
168
+ this.registry[`${packageName}:${name}`] = { component, config: config15 };
169
+ });
170
+ }
171
+ getPackageComponents(packageName) {
172
+ return this.packageRegistry[packageName];
173
+ }
174
+ getAllComponents() {
175
+ return { ...this.registry };
176
+ }
177
+ clear() {
178
+ this.registry = {};
179
+ this.packageRegistry = {};
180
+ }
181
+ };
182
+ var componentRegistry = new ComponentRegistryManager();
183
+ var registerComponent = (name, component, type, config15 = { displayName: "" }, packageName) => {
184
+ componentRegistry.registerComponent(
185
+ name,
186
+ component,
187
+ type,
188
+ config15,
189
+ packageName
190
+ );
191
+ };
192
+ var registerEffect = (name, component, config15 = { displayName: "" }, packageName) => {
193
+ componentRegistry.registerEffect(name, component, config15, packageName);
194
+ };
195
+ var registerPackage = (packageName, components) => {
196
+ componentRegistry.registerPackage(packageName, components);
197
+ };
198
+ var getComponent = (name) => componentRegistry.getComponent(name);
199
+ var getComponentConfig = (name) => componentRegistry.getComponentConfig(name);
200
+ var getComponentWithConfig = (name) => componentRegistry.getComponentWithConfig(name);
201
+
202
+ // src/core/context/CompositionContext.tsx
203
+ var import_react = __toESM(require("react"));
204
+ var CompositionContext = (0, import_react.createContext)(null);
205
+ var CompositionProvider = ({ children, value }) => {
206
+ return /* @__PURE__ */ import_react.default.createElement(CompositionContext.Provider, { value }, children);
207
+ };
208
+ var useComposition = () => {
209
+ const context = (0, import_react.useContext)(CompositionContext);
210
+ if (!context) {
211
+ throw new Error("useComposition must be used within a CompositionProvider");
212
+ }
213
+ return context;
214
+ };
215
+
216
+ // src/core/context/timing.ts
217
+ var import_mediabunny = require("mediabunny");
218
+ var findMatchingComponents = (childrenData, targetIds) => {
219
+ const matches = [];
220
+ const searchRecursively = (components) => {
221
+ for (const component of components) {
222
+ if (targetIds.includes(component.id)) {
223
+ matches.push(component);
224
+ }
225
+ if (component.childrenData && component.childrenData.length > 0) {
226
+ searchRecursively(component.childrenData);
227
+ }
228
+ }
229
+ };
230
+ searchRecursively(childrenData);
231
+ return matches;
232
+ };
233
+ var findMatchingComponentsByQuery = (childrenData, query) => {
234
+ const matches = [];
235
+ const searchRecursively = (components) => {
236
+ for (const component of components) {
237
+ let matchesQuery = false;
238
+ if (query.type && component.type === query.type) {
239
+ matchesQuery = true;
240
+ }
241
+ if (query.componentId && component.componentId === query.componentId) {
242
+ matchesQuery = true;
243
+ }
244
+ if (query.type && query.componentId) {
245
+ matchesQuery = component.type === query.type && component.componentId === query.componentId;
246
+ }
247
+ if (matchesQuery) {
248
+ matches.push(component);
249
+ }
250
+ if (component.childrenData && component.childrenData.length > 0) {
251
+ searchRecursively(component.childrenData);
252
+ }
253
+ }
254
+ };
255
+ searchRecursively(childrenData);
256
+ return matches;
257
+ };
258
+ var calculateComponentDuration = async (component) => {
259
+ const src = component.data.src;
260
+ if (src.startsWith("http")) {
261
+ const audioInput = new import_mediabunny.Input({
262
+ formats: import_mediabunny.ALL_FORMATS,
263
+ source: new import_mediabunny.UrlSource(src)
264
+ });
265
+ const audioDuration = await audioInput.computeDuration();
266
+ let trimmedDuration = audioDuration;
267
+ if (component.data.startFrom || component.data.endAt) {
268
+ trimmedDuration = audioDuration - (component.data.startFrom || 0) - (component.data.endAt ? audioDuration - (component.data.endAt || 0) : 0);
269
+ }
270
+ const playbackRate = component.data.playbackRate || 1;
271
+ const effectiveDuration = trimmedDuration / playbackRate;
272
+ return effectiveDuration;
273
+ } else {
274
+ }
275
+ };
276
+ var calculateDuration = async (childrenData, config15) => {
277
+ let calculatedDuration = void 0;
278
+ const targetIds = Array.isArray(config15.fitDurationTo) ? config15.fitDurationTo : [config15.fitDurationTo];
279
+ const matchingComponents = findMatchingComponents(
280
+ childrenData || [],
281
+ targetIds
282
+ );
283
+ if (matchingComponents.length === 1) {
284
+ if (matchingComponents[0].type === "atom" && (matchingComponents[0].componentId === "AudioAtom" || matchingComponents[0].componentId === "VideoAtom")) {
285
+ calculatedDuration = await calculateComponentDuration(
286
+ matchingComponents[0]
287
+ );
288
+ }
289
+ if ((matchingComponents[0].type === "scene" || matchingComponents[0].type === "layout") && matchingComponents[0].context?.timing?.duration) {
290
+ calculatedDuration = matchingComponents[0].context.timing.duration;
291
+ }
292
+ }
293
+ return calculatedDuration;
294
+ };
295
+ var setDurationsInContext = async (root) => {
296
+ const iterateRecursively = async (components, onlyScene = false) => {
297
+ const updatedComponents = [];
298
+ for (const component of components) {
299
+ let updatedComponent = { ...component };
300
+ if (component.childrenData && component.childrenData.length > 0) {
301
+ updatedComponent.childrenData = await iterateRecursively(
302
+ component.childrenData,
303
+ onlyScene
304
+ );
305
+ }
306
+ if (updatedComponent.context?.timing?.fitDurationTo?.length > 0 && !onlyScene && updatedComponent.context?.timing?.fitDurationTo != updatedComponent.id && updatedComponent.context?.timing?.fitDurationTo != "this" && updatedComponent.context?.timing?.fitDurationTo != "fill") {
307
+ const duration = await calculateDuration(
308
+ updatedComponent.childrenData,
309
+ {
310
+ fitDurationTo: updatedComponent.context?.timing?.fitDurationTo
311
+ }
312
+ );
313
+ updatedComponent = {
314
+ ...updatedComponent,
315
+ context: {
316
+ ...updatedComponent.context,
317
+ timing: {
318
+ ...updatedComponent.context.timing,
319
+ duration
320
+ }
321
+ }
322
+ };
323
+ }
324
+ if ((updatedComponent.type === "scene" || updatedComponent.type === "layout") && onlyScene) {
325
+ let duration;
326
+ if (updatedComponent.context?.timing?.fitDurationTo && updatedComponent.context.timing.fitDurationTo !== updatedComponent.id && updatedComponent.context.timing.fitDurationTo !== "this") {
327
+ duration = await calculateDuration(updatedComponent.childrenData, {
328
+ fitDurationTo: updatedComponent.context.timing.fitDurationTo
329
+ });
330
+ } else if (!updatedComponent.context?.timing?.duration) {
331
+ duration = updatedComponent.childrenData.reduce(
332
+ (acc, child) => acc + (child.context?.timing?.duration ?? 0),
333
+ 0
334
+ ) ?? 10;
335
+ }
336
+ if (duration !== void 0) {
337
+ updatedComponent.context = {
338
+ ...updatedComponent.context || {},
339
+ timing: {
340
+ ...updatedComponent.context?.timing || {},
341
+ duration
342
+ }
343
+ };
344
+ }
345
+ }
346
+ if (updatedComponent.type === "atom" && !onlyScene) {
347
+ if (updatedComponent.componentId === "VideoAtom" || updatedComponent.componentId === "AudioAtom") {
348
+ const mediaDuration = await calculateComponentDuration(updatedComponent);
349
+ if (!updatedComponent.context?.timing?.fitDurationTo) {
350
+ updatedComponent.context = {
351
+ ...updatedComponent.context || {},
352
+ timing: {
353
+ ...updatedComponent.context?.timing || {},
354
+ duration: updatedComponent?.context?.timing?.duration || mediaDuration
355
+ }
356
+ };
357
+ updatedComponent.data = {
358
+ ...updatedComponent.data,
359
+ ...updatedComponent.data.loop ? { srcDuration: mediaDuration } : {}
360
+ };
361
+ } else if (updatedComponent.context?.timing?.fitDurationTo) {
362
+ updatedComponent.data = {
363
+ ...updatedComponent.data,
364
+ srcDuration: mediaDuration
365
+ };
366
+ }
367
+ }
368
+ }
369
+ updatedComponents.push(updatedComponent);
370
+ }
371
+ return updatedComponents;
372
+ };
373
+ let updatedChildrenData = await iterateRecursively(root.childrenData, false);
374
+ updatedChildrenData = await iterateRecursively(updatedChildrenData, true);
375
+ return {
376
+ ...root,
377
+ childrenData: updatedChildrenData
378
+ };
379
+ };
380
+
381
+ // src/components/base/ComponentRenderer.tsx
382
+ var import_react3 = __toESM(require("react"));
383
+ var import_remotion = require("remotion");
384
+
385
+ // src/core/utils/timing.ts
386
+ var calculateTiming = (type, context, videoConfig) => {
387
+ let newTiming;
388
+ if (type !== "atom" && context?.timing) {
389
+ const { start = 0, duration = 0 } = context.timing;
390
+ newTiming = {
391
+ startInFrames: Math.round(
392
+ context.timing?.startInFrames ? context.timing.startInFrames : type === "scene" ? start * videoConfig.fps : start * videoConfig.fps
393
+ ),
394
+ durationInFrames: Math.round(
395
+ context.timing?.durationInFrames ? context.timing.durationInFrames : type === "scene" ? duration * videoConfig.fps : duration * videoConfig.fps
396
+ ),
397
+ duration,
398
+ start
399
+ };
400
+ } else {
401
+ newTiming = {
402
+ startInFrames: context.timing?.startInFrames ? context.timing.startInFrames : context.timing?.start ? Math.round(videoConfig.fps * (context.timing.start || 0)) : 0,
403
+ durationInFrames: Math.round(
404
+ context.timing?.durationInFrames ? context.timing.durationInFrames : context.timing?.duration ? Math.round(videoConfig.fps * (context.timing.duration || 0)) : 0
405
+ ),
406
+ duration: context.timing?.duration,
407
+ start: context.timing?.start
408
+ };
409
+ }
410
+ return newTiming;
411
+ };
412
+
413
+ // src/core/utils/hierarchyUtils.ts
414
+ var findComponentById = (root, targetId) => {
415
+ if (!root) return null;
416
+ const search = (components) => {
417
+ for (const component of components) {
418
+ if (component.id === targetId) {
419
+ return component;
420
+ }
421
+ if (component.childrenData && component.childrenData.length > 0) {
422
+ const found = search(component.childrenData);
423
+ if (found) return found;
424
+ }
425
+ }
426
+ return null;
427
+ };
428
+ return search(root);
429
+ };
430
+ var findParentComponent = (root, targetId) => {
431
+ if (!root) return null;
432
+ const search = (components, parent) => {
433
+ for (const component of components) {
434
+ if (component.childrenData && component.childrenData.length > 0) {
435
+ const hasTargetChild = component.childrenData.some(
436
+ (child) => child.id === targetId
437
+ );
438
+ if (hasTargetChild) {
439
+ return component;
440
+ }
441
+ const found = search(component.childrenData, component);
442
+ if (found) return found;
443
+ }
444
+ }
445
+ return null;
446
+ };
447
+ return search(root, null);
448
+ };
449
+ var calculateHierarchy = (root, componentId, currentContext) => {
450
+ if (!root) {
451
+ return {
452
+ depth: (currentContext?.hierarchy?.depth || 0) + 1,
453
+ parentIds: [...currentContext?.hierarchy?.parentIds || [], componentId]
454
+ };
455
+ }
456
+ const parentIds = [];
457
+ let depth = 0;
458
+ const traverse = (components, currentDepth) => {
459
+ for (const component of components) {
460
+ if (component.id === componentId) {
461
+ depth = currentDepth;
462
+ return true;
463
+ }
464
+ if (component.childrenData && component.childrenData.length > 0) {
465
+ parentIds.push(component.id);
466
+ const found = traverse(component.childrenData, currentDepth + 1);
467
+ if (found) return true;
468
+ parentIds.pop();
469
+ }
470
+ }
471
+ return false;
472
+ };
473
+ traverse(root, 0);
474
+ return {
475
+ depth,
476
+ parentIds: [...parentIds]
477
+ };
478
+ };
479
+ var calculateTimingWithInheritance = (component, root, videoConfig) => {
480
+ const currentContext = component.context || {};
481
+ const baseTiming = calculateTiming(
482
+ component.type,
483
+ currentContext,
484
+ videoConfig
485
+ );
486
+ if (!baseTiming.durationInFrames || baseTiming.durationInFrames <= 0) {
487
+ const findParentWithTiming = (targetId) => {
488
+ const parent = findParentComponent(root, targetId);
489
+ if (!parent) return null;
490
+ const parentContext = parent.context || {};
491
+ const parentTiming = calculateTiming(
492
+ parent.type,
493
+ parentContext,
494
+ videoConfig
495
+ );
496
+ if (parentTiming.durationInFrames && parentTiming.durationInFrames > 0) {
497
+ return parentTiming;
498
+ }
499
+ return findParentWithTiming(parent.id);
500
+ };
501
+ const inheritedTiming = findParentWithTiming(component.id);
502
+ if (inheritedTiming) {
503
+ return {
504
+ ...baseTiming,
505
+ durationInFrames: inheritedTiming.durationInFrames ? inheritedTiming.durationInFrames : inheritedTiming.duration ? inheritedTiming.duration * videoConfig.fps : 0,
506
+ duration: inheritedTiming.duration
507
+ };
508
+ }
509
+ }
510
+ return baseTiming;
511
+ };
512
+
513
+ // src/components/base/EffectWrapper.tsx
514
+ var import_react2 = __toESM(require("react"));
515
+ var import_zod = require("zod");
516
+ var EffectWrapper = ({
517
+ effects,
518
+ children,
519
+ context
520
+ }) => {
521
+ if (!effects || effects.length === 0) {
522
+ return children;
523
+ }
524
+ let wrappedContent = children;
525
+ effects.forEach((effect, index) => {
526
+ const effectId = typeof effect === "string" ? `effect-${effect}` : `effect-${effect.componentId}`;
527
+ const EffectComponent = getComponent(effectId);
528
+ if (!EffectComponent) {
529
+ console.warn(`Effect component ${effectId} not found in registry`);
530
+ return;
531
+ }
532
+ const effectData = typeof effect === "string" ? {} : effect.data || {};
533
+ const effectContext = typeof effect === "string" ? context : effect.context || context;
534
+ const effectProps = {
535
+ id: typeof effect === "string" ? `effect-${(0, import_zod.nanoid)()}` : effect.id,
536
+ componentId: effectId,
537
+ type: "layout",
538
+ // Effects use the same rendering logic as layout
539
+ data: effectData,
540
+ context: effectContext,
541
+ children: wrappedContent
542
+ };
543
+ wrappedContent = /* @__PURE__ */ import_react2.default.createElement(EffectComponent, { ...effectProps });
544
+ });
545
+ return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, wrappedContent);
546
+ };
547
+
548
+ // src/components/base/ComponentRenderer.tsx
549
+ var RenderContext = (0, import_react3.createContext)(null);
550
+ var useRenderContext = () => {
551
+ const context = (0, import_react3.useContext)(RenderContext);
552
+ if (!context) {
553
+ throw new Error("useRenderContext must be used within a ComponentRenderer");
554
+ }
555
+ return context;
556
+ };
557
+ var ComponentRenderer = ({
558
+ id,
559
+ componentId,
560
+ type,
561
+ data,
562
+ childrenData,
563
+ context,
564
+ effects
565
+ }) => {
566
+ const videoConfig = (0, import_remotion.useVideoConfig)();
567
+ const { root } = useComposition();
568
+ const defaultContext = {
569
+ boundaries: {
570
+ left: 0,
571
+ top: 0,
572
+ width: videoConfig.width,
573
+ height: videoConfig.height,
574
+ zIndex: 0
575
+ },
576
+ timing: {
577
+ startInFrames: 0,
578
+ durationInFrames: videoConfig.durationInFrames
579
+ },
580
+ hierarchy: {
581
+ depth: 0,
582
+ parentIds: []
583
+ }
584
+ };
585
+ if (!context) {
586
+ context = {};
587
+ }
588
+ const newHierarchy = calculateHierarchy(root, id, context ?? defaultContext);
589
+ const componentData = {
590
+ id,
591
+ componentId,
592
+ type,
593
+ data,
594
+ childrenData,
595
+ context,
596
+ effects
597
+ };
598
+ let newTiming = calculateTimingWithInheritance(componentData, root, videoConfig);
599
+ const newContext = {
600
+ ...context,
601
+ boundaries: context?.boundaries,
602
+ hierarchy: newHierarchy,
603
+ timing: newTiming
604
+ };
605
+ const ComponentClass = getComponent(componentId);
606
+ if (type === "scene") {
607
+ return /* @__PURE__ */ import_react3.default.createElement(RenderContext.Provider, { value: newContext }, /* @__PURE__ */ import_react3.default.createElement(import_remotion.Series, null, childrenData?.map((child) => {
608
+ const childTiming = calculateTimingWithInheritance(child, root, videoConfig);
609
+ return /* @__PURE__ */ import_react3.default.createElement(
610
+ import_remotion.Series.Sequence,
611
+ {
612
+ key: child.id,
613
+ name: child.componentId + " - " + child.id,
614
+ offset: childTiming.startInFrames ?? 0,
615
+ durationInFrames: childTiming.durationInFrames ?? 0
616
+ },
617
+ child.effects && child.effects.length > 0 ? /* @__PURE__ */ import_react3.default.createElement(EffectWrapper, { effects: child.effects, context: newContext }, /* @__PURE__ */ import_react3.default.createElement(ComponentRenderer, { key: child.id, ...child })) : /* @__PURE__ */ import_react3.default.createElement(ComponentRenderer, { key: child.id, ...child })
618
+ );
619
+ })));
620
+ }
621
+ if (!ComponentClass) {
622
+ console.warn(`Component type ${id} not found in registry`);
623
+ return null;
624
+ }
625
+ const props = {
626
+ id,
627
+ componentId,
628
+ data,
629
+ context
630
+ };
631
+ if (type === "layout") {
632
+ const config15 = getComponentConfig(componentId);
633
+ const isInnerSequence = config15?.isInnerSequence;
634
+ if (isInnerSequence) {
635
+ return /* @__PURE__ */ import_react3.default.createElement(RenderContext.Provider, { value: newContext }, /* @__PURE__ */ import_react3.default.createElement(ComponentClass, { ...props }, effects && effects.length > 0 ? /* @__PURE__ */ import_react3.default.createElement(EffectWrapper, { effects, context: newContext }, childrenData?.map((child) => /* @__PURE__ */ import_react3.default.createElement(ComponentRenderer, { key: child.id, ...child }))) : childrenData?.map((child) => /* @__PURE__ */ import_react3.default.createElement(ComponentRenderer, { key: child.id, ...child }))));
636
+ }
637
+ return /* @__PURE__ */ import_react3.default.createElement(RenderContext.Provider, { value: newContext }, /* @__PURE__ */ import_react3.default.createElement(import_remotion.Sequence, { layout: "none", name: componentId + " - " + id, from: newTiming.startInFrames, durationInFrames: newTiming.durationInFrames }, effects && effects.length > 0 ? /* @__PURE__ */ import_react3.default.createElement(EffectWrapper, { effects, context: newContext }, /* @__PURE__ */ import_react3.default.createElement(ComponentClass, { ...props }, childrenData?.map((child) => /* @__PURE__ */ import_react3.default.createElement(ComponentRenderer, { key: child.id, ...child })))) : /* @__PURE__ */ import_react3.default.createElement(ComponentClass, { ...props }, childrenData?.map((child) => /* @__PURE__ */ import_react3.default.createElement(ComponentRenderer, { key: child.id, ...child })))));
638
+ }
639
+ if (type === "atom") {
640
+ if (newTiming.durationInFrames && newTiming.durationInFrames > 0) {
641
+ return /* @__PURE__ */ import_react3.default.createElement(RenderContext.Provider, { value: newContext }, /* @__PURE__ */ import_react3.default.createElement(import_remotion.Sequence, { layout: "none", name: componentId + " - " + id, from: newTiming.startInFrames, durationInFrames: newTiming.durationInFrames }, effects && effects.length > 0 ? /* @__PURE__ */ import_react3.default.createElement(EffectWrapper, { effects, context: newContext }, /* @__PURE__ */ import_react3.default.createElement(ComponentClass, { ...{
642
+ ...props,
643
+ context: {
644
+ timing: {
645
+ durationInFrames: newTiming.durationInFrames
646
+ }
647
+ }
648
+ } })) : /* @__PURE__ */ import_react3.default.createElement(ComponentClass, { ...{
649
+ ...props,
650
+ context: {
651
+ timing: {
652
+ durationInFrames: newTiming.durationInFrames
653
+ }
654
+ }
655
+ } })));
656
+ }
657
+ return /* @__PURE__ */ import_react3.default.createElement(RenderContext.Provider, { value: newContext }, effects && effects.length > 0 ? /* @__PURE__ */ import_react3.default.createElement(EffectWrapper, { effects, context: newContext }, /* @__PURE__ */ import_react3.default.createElement(ComponentClass, { ...props })) : /* @__PURE__ */ import_react3.default.createElement(ComponentClass, { ...props }));
658
+ }
659
+ };
660
+
661
+ // src/components/frames/Frame.tsx
662
+ var import_react4 = __toESM(require("react"));
663
+ var import_remotion2 = require("remotion");
664
+ var Frame = ({ children, data }) => {
665
+ return /* @__PURE__ */ import_react4.default.createElement(import_remotion2.AbsoluteFill, { style: data?.style }, children);
666
+ };
667
+
668
+ // src/components/frames/SceneFrame.tsx
669
+ var import_react5 = __toESM(require("react"));
670
+ var import_remotion3 = require("remotion");
671
+ var SceneFrame = ({ children }) => {
672
+ return /* @__PURE__ */ import_react5.default.createElement(import_remotion3.AbsoluteFill, null, children);
673
+ };
674
+
675
+ // src/components/layouts/BaseLayout.tsx
676
+ var import_react13 = __toESM(require("react"));
677
+ var import_remotion9 = require("remotion");
678
+
679
+ // src/components/effects/BlurEffect.tsx
680
+ var import_react7 = __toESM(require("react"));
681
+
682
+ // src/components/effects/UniversalEffect.tsx
683
+ var import_react6 = __toESM(require("react"));
684
+
685
+ // src/components/effects/mergeCSSStyles.ts
686
+ var parseFunctionsString = (functions) => {
687
+ const result = /* @__PURE__ */ new Map();
688
+ if (!functions) {
689
+ return result;
690
+ }
691
+ const regex = /(\w+)\(([^)]*)\)/g;
692
+ let match;
693
+ while ((match = regex.exec(functions)) !== null) {
694
+ result.set(match[1], match[0]);
695
+ }
696
+ return result;
697
+ };
698
+ var mergeFunctionStrings = (parentValue, childValue, preferParentOnOverlap) => {
699
+ const parentFunctions = parseFunctionsString(parentValue);
700
+ const childFunctions = parseFunctionsString(childValue);
701
+ const orderedFunctionNames = [];
702
+ parentFunctions.forEach((_v, k) => orderedFunctionNames.push(k));
703
+ childFunctions.forEach((_v, k) => {
704
+ if (!orderedFunctionNames.includes(k)) {
705
+ orderedFunctionNames.push(k);
706
+ }
707
+ });
708
+ const finalFunctions = orderedFunctionNames.map((name) => {
709
+ if (preferParentOnOverlap && parentFunctions.has(name)) {
710
+ return parentFunctions.get(name);
711
+ }
712
+ return childFunctions.get(name) ?? parentFunctions.get(name);
713
+ });
714
+ return finalFunctions.join(" ").trim();
715
+ };
716
+ var mergeCSSStyles = (parent = {}, child = {}, options = {}) => {
717
+ const result = { ...parent };
718
+ const preferParentOnOverlap = Boolean(options.preferParentOnOverlap);
719
+ for (const key in child) {
720
+ if (Object.prototype.hasOwnProperty.call(child, key)) {
721
+ const pValue = result[key];
722
+ const cValue = child[key];
723
+ if (cValue === void 0 || cValue === null) {
724
+ continue;
725
+ }
726
+ switch (key) {
727
+ case "transform":
728
+ case "filter": {
729
+ result[key] = mergeFunctionStrings(
730
+ pValue,
731
+ cValue,
732
+ preferParentOnOverlap
733
+ );
734
+ break;
735
+ }
736
+ case "opacity":
737
+ if (preferParentOnOverlap && pValue !== void 0 && cValue !== void 0) {
738
+ const parentOpacity = typeof pValue === "number" && !isNaN(pValue) ? pValue : 1;
739
+ result.opacity = Math.max(0, Math.min(1, parentOpacity));
740
+ } else {
741
+ const parentOpacity = typeof pValue === "number" && !isNaN(pValue) ? pValue : 1;
742
+ const childOpacity = typeof cValue === "number" && !isNaN(cValue) ? cValue : 1;
743
+ result.opacity = Math.max(
744
+ 0,
745
+ Math.min(1, parentOpacity * childOpacity)
746
+ );
747
+ }
748
+ break;
749
+ case "transformOrigin":
750
+ result.transformOrigin = cValue;
751
+ break;
752
+ case "color":
753
+ case "backgroundColor":
754
+ result[key] = cValue;
755
+ break;
756
+ default:
757
+ if (preferParentOnOverlap && pValue !== void 0) {
758
+ result[key] = pValue;
759
+ } else {
760
+ result[key] = cValue;
761
+ }
762
+ break;
763
+ }
764
+ }
765
+ }
766
+ if (result.transform === "") {
767
+ delete result.transform;
768
+ }
769
+ if (result.filter === "") {
770
+ delete result.filter;
771
+ }
772
+ return result;
773
+ };
774
+ var mergeCSSStyles_default = mergeCSSStyles;
775
+
776
+ // src/components/effects/UniversalEffect.tsx
777
+ var import_remotion4 = require("remotion");
778
+ var UniversalEffectContext = (0, import_react6.createContext)(null);
779
+ var useUniversalEffect = () => {
780
+ const context = (0, import_react6.useContext)(UniversalEffectContext);
781
+ if (!context) {
782
+ throw new Error("useUniversalEffect must be used within a UniversalEffectProvider");
783
+ }
784
+ return context;
785
+ };
786
+ var useUniversalEffectOptional = () => {
787
+ return (0, import_react6.useContext)(UniversalEffectContext);
788
+ };
789
+ var useHasUniversalEffectProvider = () => {
790
+ const context = (0, import_react6.useContext)(UniversalEffectContext);
791
+ return context !== null;
792
+ };
793
+ var parseDuration = (duration, contextDuration, fps) => {
794
+ if (!duration) return contextDuration;
795
+ if (typeof duration === "number") {
796
+ return duration * fps;
797
+ }
798
+ if (typeof duration === "string" && duration.endsWith("%")) {
799
+ const percentage = parseFloat(duration.replace("%", "")) / 100;
800
+ return Math.floor(contextDuration * percentage);
801
+ }
802
+ return contextDuration;
803
+ };
804
+ var parseDelay = (delay, contextDuration, fps) => {
805
+ if (!delay) return 0;
806
+ if (typeof delay === "number") {
807
+ return delay * fps;
808
+ }
809
+ if (typeof delay === "string" && delay.endsWith("%")) {
810
+ const percentage = parseFloat(delay) / 100;
811
+ return Math.floor(contextDuration * percentage);
812
+ }
813
+ return 0;
814
+ };
815
+ var getEasingFunction = (type) => {
816
+ switch (type) {
817
+ case "linear":
818
+ return import_remotion4.Easing.linear;
819
+ case "ease-in":
820
+ return import_remotion4.Easing.in(import_remotion4.Easing.ease);
821
+ case "ease-out":
822
+ return import_remotion4.Easing.out(import_remotion4.Easing.ease);
823
+ case "ease-in-out":
824
+ return import_remotion4.Easing.inOut(import_remotion4.Easing.ease);
825
+ default:
826
+ return import_remotion4.Easing.linear;
827
+ }
828
+ };
829
+ var parseHexColor = (hex) => {
830
+ hex = hex.replace("#", "").toLowerCase();
831
+ if (!/^[0-9a-f]+$/.test(hex)) {
832
+ return { r: 0, g: 0, b: 0, a: 1 };
833
+ }
834
+ if (hex.length === 3) {
835
+ hex = hex.split("").map((char) => char + char).join("");
836
+ }
837
+ if (hex.length === 6) {
838
+ return {
839
+ r: Math.max(0, Math.min(255, parseInt(hex.substr(0, 2), 16))),
840
+ g: Math.max(0, Math.min(255, parseInt(hex.substr(2, 2), 16))),
841
+ b: Math.max(0, Math.min(255, parseInt(hex.substr(4, 2), 16))),
842
+ a: 1
843
+ };
844
+ }
845
+ if (hex.length === 8) {
846
+ return {
847
+ r: Math.max(0, Math.min(255, parseInt(hex.substr(0, 2), 16))),
848
+ g: Math.max(0, Math.min(255, parseInt(hex.substr(2, 2), 16))),
849
+ b: Math.max(0, Math.min(255, parseInt(hex.substr(4, 2), 16))),
850
+ a: Math.max(0, Math.min(1, parseInt(hex.substr(6, 2), 16) / 255))
851
+ };
852
+ }
853
+ return { r: 0, g: 0, b: 0, a: 1 };
854
+ };
855
+ var parseRgbaColor = (rgba) => {
856
+ const match = rgba.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+))?\s*\)/);
857
+ if (match) {
858
+ return {
859
+ r: Math.max(0, Math.min(255, parseInt(match[1], 10))),
860
+ g: Math.max(0, Math.min(255, parseInt(match[2], 10))),
861
+ b: Math.max(0, Math.min(255, parseInt(match[3], 10))),
862
+ a: match[4] ? Math.max(0, Math.min(1, parseFloat(match[4]))) : 1
863
+ };
864
+ }
865
+ return { r: 0, g: 0, b: 0, a: 1 };
866
+ };
867
+ var parseColor = (color) => {
868
+ const trimmedColor = color.trim();
869
+ if (trimmedColor.startsWith("#")) {
870
+ return parseHexColor(trimmedColor);
871
+ } else if (trimmedColor.toLowerCase().startsWith("rgb")) {
872
+ return parseRgbaColor(trimmedColor);
873
+ }
874
+ return { r: 0, g: 0, b: 0, a: 1 };
875
+ };
876
+ var rgbaToString = (color) => {
877
+ if (color.a === 1) {
878
+ return `rgb(${Math.round(color.r)}, ${Math.round(color.g)}, ${Math.round(color.b)})`;
879
+ } else {
880
+ return `rgba(${Math.round(color.r)}, ${Math.round(color.g)}, ${Math.round(color.b)}, ${color.a})`;
881
+ }
882
+ };
883
+ var interpolateColors = (color1, color2, progress) => {
884
+ const parsedColor1 = parseColor(color1);
885
+ const parsedColor2 = parseColor(color2);
886
+ const interpolatedColor = {
887
+ r: (0, import_remotion4.interpolate)(progress, [0, 1], [parsedColor1.r, parsedColor2.r]),
888
+ g: (0, import_remotion4.interpolate)(progress, [0, 1], [parsedColor1.g, parsedColor2.g]),
889
+ b: (0, import_remotion4.interpolate)(progress, [0, 1], [parsedColor1.b, parsedColor2.b]),
890
+ a: (0, import_remotion4.interpolate)(progress, [0, 1], [parsedColor1.a, parsedColor2.a])
891
+ };
892
+ return rgbaToString(interpolatedColor);
893
+ };
894
+ var calculateAnimatedValue = (ranges, progress, key) => {
895
+ const sortedRanges = [...ranges].sort((a, b) => a.prog - b.prog);
896
+ if (sortedRanges.length === 0) return 0;
897
+ if (sortedRanges.length === 1) return sortedRanges[0].val;
898
+ const clampedProgress = Math.max(0, Math.min(1, progress));
899
+ if (clampedProgress <= sortedRanges[0].prog) {
900
+ return sortedRanges[0].val;
901
+ }
902
+ if (clampedProgress >= sortedRanges[sortedRanges.length - 1].prog) {
903
+ return sortedRanges[sortedRanges.length - 1].val;
904
+ }
905
+ for (let i = 0; i < sortedRanges.length - 1; i++) {
906
+ const currentRange = sortedRanges[i];
907
+ const nextRange = sortedRanges[i + 1];
908
+ if (clampedProgress >= currentRange.prog && clampedProgress <= nextRange.prog) {
909
+ const localProgress = (clampedProgress - currentRange.prog) / (nextRange.prog - currentRange.prog);
910
+ const currentValue = currentRange.val;
911
+ const nextValue = nextRange.val;
912
+ if (typeof currentValue === "number" && typeof nextValue === "number") {
913
+ if (isFinite(currentValue) && isFinite(nextValue) && !isNaN(currentValue) && !isNaN(nextValue)) {
914
+ const interpolatedValue = currentValue + (nextValue - currentValue) * localProgress;
915
+ if (isFinite(interpolatedValue) && !isNaN(interpolatedValue)) {
916
+ return interpolatedValue;
917
+ }
918
+ }
919
+ return currentValue;
920
+ } else if (typeof currentValue === "string" && typeof nextValue === "string") {
921
+ const isColor = (str) => {
922
+ const trimmed = str.trim().toLowerCase();
923
+ return trimmed.startsWith("#") || trimmed.startsWith("rgb");
924
+ };
925
+ if (isColor(currentValue) && isColor(nextValue)) {
926
+ return interpolateColors(currentValue, nextValue, localProgress);
927
+ }
928
+ const getUnitAndValue = (str) => {
929
+ const units = ["vmax", "vmin", "rem", "deg", "bpm", "vh", "vw", "px", "em", "ms", "hz", "db", "fr", "s", "%"];
930
+ for (const unit of units) {
931
+ if (str.endsWith(unit)) {
932
+ const value2 = parseFloat(str.slice(0, -unit.length));
933
+ return {
934
+ value: isNaN(value2) ? 0 : value2,
935
+ unit
936
+ };
937
+ }
938
+ }
939
+ const value = parseFloat(str);
940
+ return {
941
+ value: isNaN(value) ? 0 : value,
942
+ unit: ""
943
+ };
944
+ };
945
+ const current = getUnitAndValue(currentValue);
946
+ const next = getUnitAndValue(nextValue);
947
+ if (current.unit === next.unit && isFinite(current.value) && isFinite(next.value)) {
948
+ const interpolatedValue = (0, import_remotion4.interpolate)(localProgress, [0, 1], [current.value, next.value]);
949
+ if (isFinite(interpolatedValue)) {
950
+ return current.unit ? `${interpolatedValue}${current.unit}` : interpolatedValue;
951
+ }
952
+ }
953
+ return currentValue;
954
+ }
955
+ return currentValue;
956
+ }
957
+ }
958
+ return sortedRanges[0]?.val || 0;
959
+ };
960
+ var rangesToCSSProperties = (ranges, progress) => {
961
+ const styles = {};
962
+ if (!ranges || !Array.isArray(ranges) || ranges.length === 0) {
963
+ return styles;
964
+ }
965
+ const rangesByKey = ranges.reduce((acc, range) => {
966
+ if (!acc[range.key]) {
967
+ acc[range.key] = [];
968
+ }
969
+ acc[range.key].push(range);
970
+ return acc;
971
+ }, {});
972
+ Object.entries(rangesByKey).forEach(([key, keyRanges]) => {
973
+ const value = calculateAnimatedValue(keyRanges, progress, key);
974
+ switch (key) {
975
+ case "scale":
976
+ styles.transform = `scale(${value})`;
977
+ break;
978
+ case "rotate":
979
+ const rotateValue = typeof value === "string" && value.includes("deg") ? value : `${value}deg`;
980
+ styles.transform = `${styles.transform || ""} rotate(${rotateValue})`.trim();
981
+ break;
982
+ case "translateX":
983
+ const translateXValue = typeof value === "string" && (value.includes("px") || value.includes("%") || value.includes("vw") || value.includes("vh")) ? value : `${value}px`;
984
+ styles.transform = `${styles.transform || ""} translateX(${translateXValue})`.trim();
985
+ break;
986
+ case "translateY":
987
+ const translateYValue = typeof value === "string" && (value.includes("px") || value.includes("%") || value.includes("vw") || value.includes("vh")) ? value : `${value}px`;
988
+ styles.transform = `${styles.transform || ""} translateY(${translateYValue})`.trim();
989
+ break;
990
+ case "opacity":
991
+ const opacityValue = typeof value === "number" ? Math.max(0, Math.min(1, isFinite(value) && !isNaN(value) ? Math.round(value * 1e3) / 1e3 : 1)) : 1;
992
+ styles.opacity = opacityValue;
993
+ break;
994
+ case "blur":
995
+ const blurValue = typeof value === "string" && (value.includes("px") || value.includes("rem") || value.includes("em")) ? value : `${value}px`;
996
+ styles.filter = `blur(${blurValue})`;
997
+ break;
998
+ case "brightness":
999
+ styles.filter = `${styles.filter || ""} brightness(${value})`.trim();
1000
+ break;
1001
+ case "contrast":
1002
+ styles.filter = `${styles.filter || ""} contrast(${value})`.trim();
1003
+ break;
1004
+ case "filter":
1005
+ styles.filter = value;
1006
+ break;
1007
+ case "color":
1008
+ styles.color = value;
1009
+ break;
1010
+ case "backgroundColor":
1011
+ styles.backgroundColor = value;
1012
+ break;
1013
+ default:
1014
+ styles[key] = value;
1015
+ }
1016
+ });
1017
+ return styles;
1018
+ };
1019
+ var useUniversalAnimation = (data, context) => {
1020
+ let frame = 0;
1021
+ let fps = 30;
1022
+ try {
1023
+ frame = (0, import_remotion4.useCurrentFrame)();
1024
+ const videoConfig = (0, import_remotion4.useVideoConfig)();
1025
+ fps = videoConfig.fps;
1026
+ } catch (error) {
1027
+ console.warn("useUniversalAnimation used outside Remotion context, using fallback values");
1028
+ }
1029
+ const effectData = data;
1030
+ const { timing } = context ?? {};
1031
+ const contextDuration = timing?.durationInFrames || 50;
1032
+ const start = parseDelay(effectData?.start, contextDuration, fps);
1033
+ const duration = parseDuration(effectData?.duration, contextDuration, fps);
1034
+ const type = effectData?.type || "linear";
1035
+ const ranges = effectData?.ranges || [];
1036
+ const targetIds = effectData?.targetIds || [];
1037
+ const mode = effectData?.mode || "wrapper";
1038
+ const easing = getEasingFunction(type);
1039
+ const progress = (0, import_remotion4.interpolate)(
1040
+ frame - start,
1041
+ [0, duration],
1042
+ [0, 1],
1043
+ {
1044
+ easing,
1045
+ extrapolateLeft: "clamp",
1046
+ extrapolateRight: "clamp"
1047
+ }
1048
+ );
1049
+ const isActive = frame >= start && frame <= start + duration;
1050
+ const isBeforeStart = frame < start;
1051
+ const isAfterEnd = frame > start + duration;
1052
+ return {
1053
+ frame,
1054
+ fps,
1055
+ progress,
1056
+ isActive,
1057
+ isBeforeStart,
1058
+ isAfterEnd,
1059
+ start,
1060
+ duration,
1061
+ type,
1062
+ ranges,
1063
+ targetIds,
1064
+ mode,
1065
+ effectData
1066
+ };
1067
+ };
1068
+ var UniversalEffect = ({
1069
+ id,
1070
+ data,
1071
+ children,
1072
+ context,
1073
+ effectType = "universal",
1074
+ customAnimationLogic
1075
+ }) => {
1076
+ const { progress, isActive, isBeforeStart, isAfterEnd, frame, ranges, mode, targetIds, effectData } = useUniversalAnimation(data, context);
1077
+ const parentContext = useUniversalEffectOptional();
1078
+ const animatedStyles = (0, import_react6.useMemo)(() => {
1079
+ const parentStyles = parentContext?.animatedStyles || {};
1080
+ let currentStyles = {};
1081
+ if (isActive) {
1082
+ if (customAnimationLogic) {
1083
+ currentStyles = customAnimationLogic(effectData, progress, frame);
1084
+ } else if (ranges.length > 0) {
1085
+ currentStyles = rangesToCSSProperties(ranges, progress);
1086
+ }
1087
+ } else if (isBeforeStart) {
1088
+ if (customAnimationLogic) {
1089
+ currentStyles = customAnimationLogic(effectData, 0, frame);
1090
+ } else if (ranges.length > 0) {
1091
+ currentStyles = rangesToCSSProperties(ranges, 0);
1092
+ }
1093
+ } else if (isAfterEnd) {
1094
+ if (customAnimationLogic) {
1095
+ currentStyles = customAnimationLogic(effectData, 1, frame);
1096
+ } else if (ranges.length > 0) {
1097
+ currentStyles = rangesToCSSProperties(ranges, 1);
1098
+ }
1099
+ }
1100
+ const preferParentOnOverlap = progress <= 0;
1101
+ if (parentContext && mode === "provider") {
1102
+ const combinedStyles = mergeCSSStyles_default(
1103
+ parentStyles,
1104
+ currentStyles,
1105
+ { preferParentOnOverlap: false }
1106
+ );
1107
+ return combinedStyles;
1108
+ }
1109
+ return currentStyles;
1110
+ }, [ranges, progress, parentContext?.animatedStyles, mode, customAnimationLogic, effectData, frame]);
1111
+ const contextValue = (0, import_react6.useMemo)(() => ({
1112
+ animatedStyles,
1113
+ targetIds,
1114
+ effectType
1115
+ }), [animatedStyles, targetIds, effectType]);
1116
+ if (mode === "provider") {
1117
+ return /* @__PURE__ */ import_react6.default.createElement(UniversalEffectContext.Provider, { value: contextValue }, children);
1118
+ } else {
1119
+ return /* @__PURE__ */ import_react6.default.createElement("div", { ...effectData.props, style: animatedStyles }, children);
1120
+ }
1121
+ };
1122
+ var UniversalEffectProvider = ({
1123
+ children,
1124
+ data,
1125
+ effectType = "universal",
1126
+ customAnimationLogic,
1127
+ id = "generic",
1128
+ componentId = "generic",
1129
+ type = "effect"
1130
+ }) => {
1131
+ return /* @__PURE__ */ import_react6.default.createElement(
1132
+ UniversalEffect,
1133
+ {
1134
+ id,
1135
+ componentId,
1136
+ type,
1137
+ data,
1138
+ context: void 0,
1139
+ effectType,
1140
+ customAnimationLogic
1141
+ },
1142
+ children
1143
+ );
1144
+ };
1145
+ var useAnimatedStyles = (componentId) => {
1146
+ const context = useUniversalEffectOptional();
1147
+ if (!context) {
1148
+ return {};
1149
+ }
1150
+ const { animatedStyles, targetIds } = context;
1151
+ if (targetIds.includes(componentId)) {
1152
+ return animatedStyles;
1153
+ }
1154
+ return {};
1155
+ };
1156
+ var config = {
1157
+ displayName: "generic",
1158
+ description: "Universal effect that can be extended for any effect type",
1159
+ isInnerSequence: false,
1160
+ props: {}
1161
+ };
1162
+
1163
+ // src/components/effects/BlurEffect.tsx
1164
+ var BlurEffect = ({
1165
+ id,
1166
+ componentId,
1167
+ type,
1168
+ data,
1169
+ children,
1170
+ context
1171
+ }) => {
1172
+ const { progress, mode, targetIds, effectData } = useUniversalAnimation(data, context);
1173
+ const { intensity = 10, direction = "in" } = effectData;
1174
+ const parentContext = useUniversalEffectOptional();
1175
+ const animatedStyles = (0, import_react7.useMemo)(() => {
1176
+ if (progress <= 0 || progress >= 1) {
1177
+ return {};
1178
+ }
1179
+ const blurValue = direction === "in" ? intensity * (1 - progress) : intensity * progress;
1180
+ const currentStyles = { filter: `blur(${blurValue}px)` };
1181
+ if (parentContext && mode === "provider") {
1182
+ const combinedStyles = mergeCSSStyles_default(parentContext.animatedStyles, currentStyles);
1183
+ return combinedStyles;
1184
+ }
1185
+ return currentStyles;
1186
+ }, [progress, intensity, direction, parentContext?.animatedStyles, mode]);
1187
+ const contextValue = (0, import_react7.useMemo)(() => ({
1188
+ animatedStyles,
1189
+ targetIds,
1190
+ effectType: "blur"
1191
+ }), [animatedStyles, targetIds]);
1192
+ if (mode === "provider") {
1193
+ return /* @__PURE__ */ import_react7.default.createElement(UniversalEffectContext.Provider, { value: contextValue }, children);
1194
+ }
1195
+ return /* @__PURE__ */ import_react7.default.createElement("div", { ...effectData.props, style: animatedStyles }, children);
1196
+ };
1197
+ var config2 = {
1198
+ displayName: "blur",
1199
+ description: "Blur effect with configurable intensity and direction",
1200
+ isInnerSequence: false,
1201
+ props: {
1202
+ intensity: {
1203
+ type: "number",
1204
+ default: 10,
1205
+ description: "Blur intensity in pixels"
1206
+ },
1207
+ direction: {
1208
+ type: "enum",
1209
+ values: ["in", "out"],
1210
+ default: "in",
1211
+ description: "Blur direction (in = start blurred, out = end blurred)"
1212
+ }
1213
+ }
1214
+ };
1215
+
1216
+ // src/components/effects/Loop.tsx
1217
+ var import_react8 = __toESM(require("react"));
1218
+ var import_remotion5 = require("remotion");
1219
+ var LoopEffect = ({
1220
+ data,
1221
+ children,
1222
+ context
1223
+ }) => {
1224
+ const { timing } = context ?? {};
1225
+ const loopData = data;
1226
+ const durationInFrames = loopData?.durationInFrames || timing?.durationInFrames || 50;
1227
+ const times = loopData?.times ?? Infinity;
1228
+ const layout = loopData?.layout || "absolute-fill";
1229
+ return (
1230
+ // @ts-ignore
1231
+ /* @__PURE__ */ import_react8.default.createElement(
1232
+ import_remotion5.Loop,
1233
+ {
1234
+ durationInFrames,
1235
+ times,
1236
+ layout
1237
+ },
1238
+ /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, children)
1239
+ )
1240
+ );
1241
+ };
1242
+ var config3 = {
1243
+ displayName: "loop",
1244
+ type: "layout",
1245
+ isInnerSequence: false,
1246
+ props: {
1247
+ durationInFrames: {
1248
+ type: "number",
1249
+ description: "How many frames one iteration of the loop should be long",
1250
+ default: 50
1251
+ },
1252
+ times: {
1253
+ type: "number",
1254
+ description: "How many times to loop the content (defaults to Infinity)",
1255
+ default: void 0
1256
+ },
1257
+ layout: {
1258
+ type: "string",
1259
+ description: 'Either "absolute-fill" (default) or "none"',
1260
+ default: "absolute-fill"
1261
+ }
1262
+ }
1263
+ };
1264
+
1265
+ // src/components/effects/Pan.tsx
1266
+ var import_react9 = __toESM(require("react"));
1267
+ var import_remotion6 = require("remotion");
1268
+ var parseDuration2 = (duration, contextDuration, fps) => {
1269
+ if (!duration) return contextDuration;
1270
+ if (typeof duration === "number") {
1271
+ return duration * fps;
1272
+ }
1273
+ if (typeof duration === "string" && duration.endsWith("%")) {
1274
+ const percentage = parseFloat(duration.replace("%", "")) / 100;
1275
+ return Math.floor(contextDuration * percentage);
1276
+ }
1277
+ return contextDuration;
1278
+ };
1279
+ var parseDelay2 = (delay, contextDuration, fps) => {
1280
+ if (!delay) return 0;
1281
+ if (typeof delay === "number") {
1282
+ return delay * fps;
1283
+ }
1284
+ if (typeof delay === "string" && delay.endsWith("%")) {
1285
+ const percentage = parseFloat(delay) / 100;
1286
+ return Math.floor(contextDuration * percentage);
1287
+ }
1288
+ return 0;
1289
+ };
1290
+ var getPanDistance = (progress, panDistance) => {
1291
+ if (typeof panDistance === "number") {
1292
+ return panDistance;
1293
+ }
1294
+ if (Array.isArray(panDistance)) {
1295
+ if (panDistance.length === 0) return 0;
1296
+ if (panDistance.length === 1) return panDistance[0][1];
1297
+ for (let i = 0; i < panDistance.length - 1; i++) {
1298
+ const [currentProgress, currentDistance] = panDistance[i];
1299
+ const [nextProgress, nextDistance] = panDistance[i + 1];
1300
+ if (progress >= currentProgress && progress <= nextProgress) {
1301
+ const localProgress = (progress - currentProgress) / (nextProgress - currentProgress);
1302
+ return (0, import_remotion6.interpolate)(localProgress, [0, 1], [currentDistance, nextDistance]);
1303
+ }
1304
+ }
1305
+ return panDistance[panDistance.length - 1][1];
1306
+ }
1307
+ return 0;
1308
+ };
1309
+ var getPosition = (position) => {
1310
+ if (!position) return [0.5, 0.5];
1311
+ if (Array.isArray(position)) {
1312
+ return position;
1313
+ }
1314
+ const positions = {
1315
+ "top-left": [0, 0],
1316
+ "top": [0.5, 0],
1317
+ "top-right": [1, 0],
1318
+ "left": [0, 0.5],
1319
+ "center": [0.5, 0.5],
1320
+ "right": [1, 0.5],
1321
+ "bottom-left": [0, 1],
1322
+ "bottom": [0.5, 1],
1323
+ "bottom-right": [1, 1]
1324
+ };
1325
+ return positions[position] || [0.5, 0.5];
1326
+ };
1327
+ var getEasingFunction2 = (animationType) => {
1328
+ switch (animationType) {
1329
+ case "linear":
1330
+ return import_remotion6.Easing.linear;
1331
+ case "ease-in":
1332
+ return import_remotion6.Easing.in(import_remotion6.Easing.ease);
1333
+ case "ease-out":
1334
+ return import_remotion6.Easing.out(import_remotion6.Easing.ease);
1335
+ case "ease-in-out":
1336
+ return import_remotion6.Easing.inOut(import_remotion6.Easing.ease);
1337
+ default:
1338
+ return import_remotion6.Easing.linear;
1339
+ }
1340
+ };
1341
+ var getPanVector = (direction, distance) => {
1342
+ switch (direction) {
1343
+ case "left":
1344
+ return [-distance, 0];
1345
+ case "right":
1346
+ return [distance, 0];
1347
+ case "up":
1348
+ return [0, -distance];
1349
+ case "down":
1350
+ return [0, distance];
1351
+ case "diagonal":
1352
+ return [distance * 0.707, distance * 0.707];
1353
+ // 45-degree diagonal
1354
+ default:
1355
+ return [0, 0];
1356
+ }
1357
+ };
1358
+ var PanEffect = ({
1359
+ data,
1360
+ children,
1361
+ context
1362
+ }) => {
1363
+ const frame = (0, import_remotion6.useCurrentFrame)();
1364
+ const { fps } = (0, import_remotion6.useVideoConfig)();
1365
+ const panData = data;
1366
+ const { timing } = context ?? {};
1367
+ const contextDuration = timing?.durationInFrames || 50;
1368
+ const effectTiming = panData?.effectTiming || "start";
1369
+ const panDuration = parseDuration2(panData?.panDuration, contextDuration, fps);
1370
+ const panStartDelay = parseDelay2(panData?.panStartDelay, contextDuration, fps);
1371
+ const panEndDelay = parseDelay2(panData?.panEndDelay, contextDuration, fps);
1372
+ const panDirection = panData?.panDirection || "right";
1373
+ let panDistance = panData?.panDistance || 100;
1374
+ const loopTimes = panData?.loopTimes || 0;
1375
+ const panStartPosition = getPosition(panData?.panStartPosition);
1376
+ const panEndPosition = getPosition(panData?.panEndPosition);
1377
+ const animationType = panData?.animationType || "linear";
1378
+ if (loopTimes > 0 && typeof panDistance === "number") {
1379
+ const loopedPanDistance = [];
1380
+ for (let i = 0; i < loopTimes; i++) {
1381
+ const loopProgress = i / loopTimes;
1382
+ const nextLoopProgress = (i + 1) / loopTimes;
1383
+ loopedPanDistance.push([loopProgress, 0]);
1384
+ loopedPanDistance.push([loopProgress + (nextLoopProgress - loopProgress) * 0.5, panDistance]);
1385
+ loopedPanDistance.push([nextLoopProgress, 0]);
1386
+ }
1387
+ panDistance = loopedPanDistance;
1388
+ }
1389
+ let progress;
1390
+ if (animationType === "spring") {
1391
+ progress = (0, import_remotion6.spring)({
1392
+ frame,
1393
+ fps,
1394
+ config: {
1395
+ stiffness: 100,
1396
+ damping: 10,
1397
+ mass: 1
1398
+ },
1399
+ durationInFrames: panDuration,
1400
+ delay: effectTiming === "start" ? panStartDelay : contextDuration - panEndDelay - panDuration
1401
+ });
1402
+ } else {
1403
+ let animationFrame;
1404
+ if (effectTiming === "start") {
1405
+ animationFrame = frame - panStartDelay;
1406
+ } else {
1407
+ animationFrame = frame - (contextDuration - panEndDelay - panDuration);
1408
+ }
1409
+ const easing = getEasingFunction2(animationType);
1410
+ progress = (0, import_remotion6.interpolate)(
1411
+ animationFrame,
1412
+ [0, panDuration],
1413
+ [0, 1],
1414
+ {
1415
+ easing,
1416
+ extrapolateLeft: "clamp",
1417
+ extrapolateRight: "clamp"
1418
+ }
1419
+ );
1420
+ }
1421
+ let panOffset;
1422
+ if (panDirection === "custom") {
1423
+ const [startX, startY] = panStartPosition;
1424
+ const [endX, endY] = panEndPosition;
1425
+ const offsetX = (endX - startX) * 100;
1426
+ const offsetY = (endY - startY) * 100;
1427
+ panOffset = [
1428
+ (0, import_remotion6.interpolate)(progress, [0, 1], [0, offsetX]),
1429
+ (0, import_remotion6.interpolate)(progress, [0, 1], [0, offsetY])
1430
+ ];
1431
+ } else {
1432
+ const distance = getPanDistance(progress, panDistance);
1433
+ const [vectorX, vectorY] = getPanVector(panDirection, distance);
1434
+ panOffset = [vectorX, vectorY];
1435
+ }
1436
+ const style = (0, import_react9.useMemo)(() => {
1437
+ return {
1438
+ width: "100%",
1439
+ height: "100%",
1440
+ transform: `translate(${panOffset[0]}px, ${panOffset[1]}px)`
1441
+ };
1442
+ }, [panOffset]);
1443
+ return /* @__PURE__ */ import_react9.default.createElement("div", { style }, children);
1444
+ };
1445
+ var config4 = {
1446
+ displayName: "pan",
1447
+ type: "layout",
1448
+ isInnerSequence: false,
1449
+ props: {
1450
+ effectTiming: {
1451
+ type: "string",
1452
+ description: 'When the pan effect should occur: "start" or "end"',
1453
+ default: "start"
1454
+ },
1455
+ panDuration: {
1456
+ type: "string",
1457
+ description: 'Duration of the pan animation in seconds or percentage (e.g., "2" or "50%")',
1458
+ default: void 0
1459
+ },
1460
+ panStart: {
1461
+ type: "number",
1462
+ description: "Start time of pan in seconds",
1463
+ default: 0
1464
+ },
1465
+ panEnd: {
1466
+ type: "number",
1467
+ description: "End time of pan in seconds",
1468
+ default: void 0
1469
+ },
1470
+ panStartDelay: {
1471
+ type: "string",
1472
+ description: "Delay before pan starts in seconds or percentage",
1473
+ default: 0
1474
+ },
1475
+ panEndDelay: {
1476
+ type: "string",
1477
+ description: "Delay before video ends in seconds or percentage",
1478
+ default: 0
1479
+ },
1480
+ panDirection: {
1481
+ type: "string",
1482
+ description: 'Direction of pan: "left", "right", "up", "down", "diagonal", or "custom"',
1483
+ default: "right"
1484
+ },
1485
+ panDistance: {
1486
+ type: "string",
1487
+ description: "Pan distance in pixels or array of [progress, distance] pairs",
1488
+ default: 100
1489
+ },
1490
+ panStartPosition: {
1491
+ type: "string",
1492
+ description: "Starting position: [x, y] coordinates or position string (top-left, center, etc.)",
1493
+ default: "center"
1494
+ },
1495
+ panEndPosition: {
1496
+ type: "string",
1497
+ description: "Ending position: [x, y] coordinates or position string (top-left, center, etc.)",
1498
+ default: "center"
1499
+ },
1500
+ animationType: {
1501
+ type: "string",
1502
+ description: 'Animation curve: "linear", "spring", "ease-in", "ease-out", "ease-in-out"',
1503
+ default: "linear"
1504
+ }
1505
+ }
1506
+ };
1507
+
1508
+ // src/components/effects/Zoom.tsx
1509
+ var import_react10 = __toESM(require("react"));
1510
+ var import_remotion7 = require("remotion");
1511
+ var parseDuration3 = (duration, contextDuration, fps) => {
1512
+ if (!duration) return contextDuration;
1513
+ if (typeof duration === "number") {
1514
+ return duration * fps;
1515
+ }
1516
+ if (typeof duration === "string" && duration.endsWith("%")) {
1517
+ const percentage = parseFloat(duration.replace("%", "")) / 100;
1518
+ return Math.floor(contextDuration * percentage);
1519
+ }
1520
+ return contextDuration;
1521
+ };
1522
+ var parseDelay3 = (delay, contextDuration, fps) => {
1523
+ if (!delay) return 0;
1524
+ if (typeof delay === "number") {
1525
+ return delay * fps;
1526
+ }
1527
+ if (typeof delay === "string" && delay.endsWith("%")) {
1528
+ const percentage = parseFloat(delay) / 100;
1529
+ return Math.floor(contextDuration * percentage);
1530
+ }
1531
+ return 0;
1532
+ };
1533
+ var getZoomScale = (progress, zoomDepth) => {
1534
+ if (typeof zoomDepth === "number") {
1535
+ return zoomDepth;
1536
+ }
1537
+ if (Array.isArray(zoomDepth)) {
1538
+ if (zoomDepth.length === 0) return 1;
1539
+ if (zoomDepth.length === 1) return zoomDepth[0][1];
1540
+ for (let i = 0; i < zoomDepth.length - 1; i++) {
1541
+ const [currentProgress, currentScale] = zoomDepth[i];
1542
+ const [nextProgress, nextScale] = zoomDepth[i + 1];
1543
+ if (progress >= currentProgress && progress <= nextProgress) {
1544
+ const localProgress = (progress - currentProgress) / (nextProgress - currentProgress);
1545
+ return (0, import_remotion7.interpolate)(localProgress, [0, 1], [currentScale, nextScale]);
1546
+ }
1547
+ }
1548
+ return zoomDepth[zoomDepth.length - 1][1];
1549
+ }
1550
+ return 1;
1551
+ };
1552
+ var getZoomPosition = (position) => {
1553
+ if (!position) return [0.5, 0.5];
1554
+ if (Array.isArray(position)) {
1555
+ return position;
1556
+ }
1557
+ const positions = {
1558
+ "top-left": [0, 0],
1559
+ "top": [0.5, 0],
1560
+ "top-right": [1, 0],
1561
+ "left": [0, 0.5],
1562
+ "center": [0.5, 0.5],
1563
+ "right": [1, 0.5],
1564
+ "bottom-left": [0, 1],
1565
+ "bottom": [0.5, 1],
1566
+ "bottom-right": [1, 1]
1567
+ };
1568
+ return positions[position] || [0.5, 0.5];
1569
+ };
1570
+ var getEasingFunction3 = (animationType) => {
1571
+ switch (animationType) {
1572
+ case "linear":
1573
+ return import_remotion7.Easing.linear;
1574
+ case "ease-in":
1575
+ return import_remotion7.Easing.in(import_remotion7.Easing.ease);
1576
+ case "ease-out":
1577
+ return import_remotion7.Easing.out(import_remotion7.Easing.ease);
1578
+ case "ease-in-out":
1579
+ return import_remotion7.Easing.inOut(import_remotion7.Easing.ease);
1580
+ default:
1581
+ return import_remotion7.Easing.linear;
1582
+ }
1583
+ };
1584
+ var ZoomEffect = ({
1585
+ data,
1586
+ children,
1587
+ context
1588
+ }) => {
1589
+ const frame = (0, import_remotion7.useCurrentFrame)();
1590
+ const { fps } = (0, import_remotion7.useVideoConfig)();
1591
+ const zoomData = data;
1592
+ const { timing } = context ?? {};
1593
+ const contextDuration = timing?.durationInFrames || 50;
1594
+ const effectTiming = zoomData?.effectTiming || "start";
1595
+ const zoomDuration = parseDuration3(zoomData?.zoomDuration, contextDuration, fps);
1596
+ const zoomStartDelay = parseDelay3(zoomData?.zoomStartDelay, contextDuration, fps);
1597
+ const zoomEndDelay = parseDelay3(zoomData?.zoomEndDelay, contextDuration, fps);
1598
+ const zoomDirection = zoomData?.zoomDirection || "in";
1599
+ let zoomDepth = zoomData?.zoomDepth || 1.5;
1600
+ const loopTimes = zoomData?.loopTimes || 0;
1601
+ if (loopTimes > 1 && Array.isArray(zoomDepth)) {
1602
+ const loopedZoomDepth = [];
1603
+ for (let i = 0; i < loopTimes; i++) {
1604
+ const loopProgress = i / loopTimes;
1605
+ const nextLoopProgress = (i + 1) / loopTimes;
1606
+ zoomDepth.forEach(([x, y]) => {
1607
+ const mappedX = loopProgress + x * (nextLoopProgress - loopProgress);
1608
+ loopedZoomDepth.push([mappedX, y]);
1609
+ });
1610
+ }
1611
+ zoomDepth = loopedZoomDepth;
1612
+ } else if (loopTimes > 0 && typeof zoomDepth === "number") {
1613
+ const loopedZoomDepth = [];
1614
+ for (let i = 0; i < loopTimes; i++) {
1615
+ const loopProgress = i / loopTimes;
1616
+ const nextLoopProgress = (i + 1) / loopTimes;
1617
+ loopedZoomDepth.push([loopProgress, 1]);
1618
+ loopedZoomDepth.push([loopProgress + (nextLoopProgress - loopProgress) * 0.5, zoomDepth]);
1619
+ loopedZoomDepth.push([nextLoopProgress, 1]);
1620
+ }
1621
+ zoomDepth = loopedZoomDepth;
1622
+ }
1623
+ const zoomPosition = getZoomPosition(zoomData?.zoomPosition);
1624
+ const animationType = zoomData?.animationType || "linear";
1625
+ let progress;
1626
+ if (animationType === "spring") {
1627
+ progress = (0, import_remotion7.spring)({
1628
+ frame,
1629
+ fps,
1630
+ config: {
1631
+ stiffness: 100,
1632
+ damping: 10,
1633
+ mass: 1
1634
+ },
1635
+ durationInFrames: zoomDuration,
1636
+ delay: effectTiming === "start" ? zoomStartDelay : contextDuration - zoomEndDelay - zoomDuration
1637
+ });
1638
+ } else {
1639
+ let animationFrame;
1640
+ if (effectTiming === "start") {
1641
+ animationFrame = frame - zoomStartDelay;
1642
+ } else {
1643
+ animationFrame = frame - (contextDuration - zoomEndDelay - zoomDuration);
1644
+ }
1645
+ const easing = getEasingFunction3(animationType);
1646
+ progress = (0, import_remotion7.interpolate)(
1647
+ animationFrame,
1648
+ [0, zoomDuration],
1649
+ [0, 1],
1650
+ {
1651
+ easing,
1652
+ extrapolateLeft: "clamp",
1653
+ extrapolateRight: "clamp"
1654
+ }
1655
+ );
1656
+ }
1657
+ let scale;
1658
+ if (typeof zoomDepth === "number") {
1659
+ const baseScale = zoomDirection === "in" ? 1 : zoomDepth;
1660
+ const targetScale = zoomDirection === "in" ? zoomDepth : 1;
1661
+ scale = (0, import_remotion7.interpolate)(progress, [0, 1], [baseScale, targetScale]);
1662
+ } else if (Array.isArray(zoomDepth)) {
1663
+ scale = getZoomScale(progress, zoomDepth);
1664
+ } else {
1665
+ const baseScale = zoomDirection === "in" ? 1 : 1.5;
1666
+ const targetScale = zoomDirection === "in" ? 1.5 : 1;
1667
+ scale = (0, import_remotion7.interpolate)(progress, [0, 1], [baseScale, targetScale]);
1668
+ }
1669
+ const [originX, originY] = zoomPosition;
1670
+ const transformOrigin = `${originX * 100}% ${originY * 100}%`;
1671
+ const style = (0, import_react10.useMemo)(() => {
1672
+ return {
1673
+ width: "100%",
1674
+ height: "100%",
1675
+ transform: `scale(${scale})`,
1676
+ transformOrigin
1677
+ };
1678
+ }, [scale, transformOrigin]);
1679
+ return /* @__PURE__ */ import_react10.default.createElement("div", { style }, children);
1680
+ };
1681
+ var config5 = {
1682
+ displayName: "zoom",
1683
+ type: "layout",
1684
+ isInnerSequence: false,
1685
+ props: {
1686
+ effectTiming: {
1687
+ type: "string",
1688
+ description: 'When the zoom effect should occur: "start" or "end"',
1689
+ default: "start"
1690
+ },
1691
+ zoomDuration: {
1692
+ type: "string",
1693
+ description: 'Duration of the zoom animation in seconds or percentage (e.g., "2" or "50%")',
1694
+ default: void 0
1695
+ },
1696
+ zoomStart: {
1697
+ type: "number",
1698
+ description: "Start time of zoom in seconds",
1699
+ default: 0
1700
+ },
1701
+ zoomEnd: {
1702
+ type: "number",
1703
+ description: "End time of zoom in seconds",
1704
+ default: void 0
1705
+ },
1706
+ zoomStartDelay: {
1707
+ type: "string",
1708
+ description: "Delay before zoom starts in seconds or percentage",
1709
+ default: 0
1710
+ },
1711
+ zoomEndDelay: {
1712
+ type: "string",
1713
+ description: "Delay before video ends in seconds or percentage",
1714
+ default: 0
1715
+ },
1716
+ zoomDirection: {
1717
+ type: "string",
1718
+ description: 'Direction of zoom: "in" or "out"',
1719
+ default: "in"
1720
+ },
1721
+ zoomDepth: {
1722
+ type: "string",
1723
+ description: "Zoom scale factor or array of [progress, scale] pairs",
1724
+ default: 1.5
1725
+ },
1726
+ zoomPosition: {
1727
+ type: "string",
1728
+ description: "Zoom anchor point: [x, y] coordinates or position string (top-left, center, etc.)",
1729
+ default: "center"
1730
+ },
1731
+ animationType: {
1732
+ type: "string",
1733
+ description: 'Animation curve: "linear", "spring", "ease-in", "ease-out", "ease-in-out"',
1734
+ default: "linear"
1735
+ }
1736
+ }
1737
+ };
1738
+
1739
+ // src/components/effects/Shake.tsx
1740
+ var import_react11 = __toESM(require("react"));
1741
+ var ShakeEffect = ({
1742
+ id,
1743
+ componentId,
1744
+ type,
1745
+ data,
1746
+ children,
1747
+ context
1748
+ }) => {
1749
+ const { progress, frame, mode, targetIds, effectData } = useUniversalAnimation(data, context);
1750
+ const { amplitude = 10, frequency = 0.1, decay = true, axis = "both" } = effectData;
1751
+ const parentContext = useUniversalEffectOptional();
1752
+ const animatedStyles = (0, import_react11.useMemo)(() => {
1753
+ if (progress <= 0 || progress >= 1) {
1754
+ return parentContext?.animatedStyles || {};
1755
+ }
1756
+ const decayFactor = decay ? 1 - progress : 1;
1757
+ const currentAmplitude = amplitude * decayFactor;
1758
+ const time = frame * frequency;
1759
+ const shakeX = axis === "x" || axis === "both" ? Math.sin(time) * currentAmplitude : 0;
1760
+ const shakeY = axis === "y" || axis === "both" ? Math.cos(time * 1.3) * currentAmplitude : 0;
1761
+ const styles = {};
1762
+ if (axis === "x" || axis === "both") {
1763
+ styles.transform = `translateX(${shakeX}px)`;
1764
+ }
1765
+ if (axis === "y" || axis === "both") {
1766
+ styles.transform = `${styles.transform || ""} translateY(${shakeY}px)`.trim();
1767
+ }
1768
+ if (parentContext && mode === "provider") {
1769
+ const combinedStyles = mergeCSSStyles_default(parentContext.animatedStyles, styles);
1770
+ return combinedStyles;
1771
+ }
1772
+ return styles;
1773
+ }, [progress, frame, amplitude, frequency, decay, axis, id, targetIds, mode, parentContext?.animatedStyles]);
1774
+ const contextValue = (0, import_react11.useMemo)(() => ({
1775
+ animatedStyles,
1776
+ targetIds,
1777
+ effectType: "shake"
1778
+ }), [animatedStyles, targetIds]);
1779
+ if (mode === "provider") {
1780
+ return /* @__PURE__ */ import_react11.default.createElement(UniversalEffectContext.Provider, { value: contextValue }, children);
1781
+ }
1782
+ return /* @__PURE__ */ import_react11.default.createElement("div", { ...effectData.props, style: animatedStyles }, children);
1783
+ };
1784
+ var config6 = {
1785
+ displayName: "shake",
1786
+ description: "Shake effect with configurable amplitude, frequency, and decay",
1787
+ isInnerSequence: false,
1788
+ props: {
1789
+ amplitude: {
1790
+ type: "number",
1791
+ default: 10,
1792
+ description: "Shake intensity in pixels"
1793
+ },
1794
+ frequency: {
1795
+ type: "number",
1796
+ default: 0.1,
1797
+ description: "Shake frequency (higher = faster shake)"
1798
+ },
1799
+ decay: {
1800
+ type: "boolean",
1801
+ default: true,
1802
+ description: "Whether shake should decay over time"
1803
+ },
1804
+ axis: {
1805
+ type: "enum",
1806
+ values: ["x", "y", "both"],
1807
+ default: "both",
1808
+ description: "Which axis to shake"
1809
+ }
1810
+ }
1811
+ };
1812
+
1813
+ // src/components/effects/StretchEffect.tsx
1814
+ var import_react12 = __toESM(require("react"));
1815
+ var import_remotion8 = require("remotion");
1816
+ var StretchEffect = ({
1817
+ id,
1818
+ componentId,
1819
+ type,
1820
+ data,
1821
+ children,
1822
+ context
1823
+ }) => {
1824
+ const { fps, frame, mode, targetIds, effectData, start, duration } = useUniversalAnimation(data, context);
1825
+ const { stretchFrom = 0.8, stretchTo = 1, springConfig } = effectData;
1826
+ const parentContext = useUniversalEffectOptional();
1827
+ const springProgress = (0, import_remotion8.spring)({
1828
+ fps,
1829
+ frame: frame - start,
1830
+ config: {
1831
+ stiffness: 100,
1832
+ damping: 10,
1833
+ mass: 1,
1834
+ ...springConfig
1835
+ },
1836
+ durationInFrames: duration
1837
+ });
1838
+ const animatedStyles = (0, import_react12.useMemo)(() => {
1839
+ if (springProgress <= 0 || springProgress >= 1) {
1840
+ return parentContext?.animatedStyles || {};
1841
+ }
1842
+ const scaleX = springProgress * (stretchTo - stretchFrom) + stretchFrom;
1843
+ const scaleY = 1 + (1 - scaleX) * 0.1;
1844
+ const currentStyles = {
1845
+ transform: `scaleX(${scaleX}) scaleY(${scaleY})`,
1846
+ transformOrigin: "center"
1847
+ };
1848
+ if (parentContext && mode === "provider") {
1849
+ const combinedStyles = mergeCSSStyles_default(parentContext.animatedStyles, currentStyles);
1850
+ return combinedStyles;
1851
+ }
1852
+ return currentStyles;
1853
+ }, [springProgress, stretchFrom, stretchTo, parentContext?.animatedStyles, mode]);
1854
+ const contextValue = (0, import_react12.useMemo)(() => ({
1855
+ animatedStyles,
1856
+ targetIds,
1857
+ effectType: "stretch"
1858
+ }), [animatedStyles, targetIds]);
1859
+ if (mode === "provider") {
1860
+ return /* @__PURE__ */ import_react12.default.createElement(UniversalEffectContext.Provider, { value: contextValue }, children);
1861
+ }
1862
+ return /* @__PURE__ */ import_react12.default.createElement("div", { ...effectData.props, style: animatedStyles }, children);
1863
+ };
1864
+ var config7 = {
1865
+ displayName: "stretch",
1866
+ description: "Stretches a component with a spring motion, ideal for subtitles.",
1867
+ isInnerSequence: false,
1868
+ props: {
1869
+ stretchFrom: {
1870
+ type: "number",
1871
+ default: 0.8,
1872
+ description: "The initial horizontal scale of the component."
1873
+ },
1874
+ stretchTo: {
1875
+ type: "number",
1876
+ default: 1,
1877
+ description: "The final horizontal scale of the component."
1878
+ }
1879
+ }
1880
+ };
1881
+
1882
+ // src/components/effects/GenericPresets.ts
1883
+ var fadeInPreset = [
1884
+ { key: "opacity", val: 0, prog: 0 },
1885
+ { key: "opacity", val: 1, prog: 1 }
1886
+ ];
1887
+ var fadeOutPreset = [
1888
+ { key: "opacity", val: 1, prog: 0 },
1889
+ { key: "opacity", val: 0, prog: 1 }
1890
+ ];
1891
+ var scaleInPreset = [
1892
+ { key: "scale", val: 0, prog: 0 },
1893
+ { key: "scale", val: 1, prog: 1 }
1894
+ ];
1895
+ var scaleOutPreset = [
1896
+ { key: "scale", val: 1, prog: 0 },
1897
+ { key: "scale", val: 0, prog: 1 }
1898
+ ];
1899
+ var slideInLeftPreset = [
1900
+ { key: "translateX", val: -100, prog: 0 },
1901
+ { key: "translateX", val: 0, prog: 1 }
1902
+ ];
1903
+ var slideInRightPreset = [
1904
+ { key: "translateX", val: 100, prog: 0 },
1905
+ { key: "translateX", val: 0, prog: 1 }
1906
+ ];
1907
+ var slideInTopPreset = [
1908
+ { key: "translateY", val: -100, prog: 0 },
1909
+ { key: "translateY", val: 0, prog: 1 }
1910
+ ];
1911
+ var slideInBottomPreset = [
1912
+ { key: "translateY", val: 100, prog: 0 },
1913
+ { key: "translateY", val: 0, prog: 1 }
1914
+ ];
1915
+ var bouncePreset = [
1916
+ { key: "scale", val: 0, prog: 0 },
1917
+ { key: "scale", val: 1.2, prog: 0.6 },
1918
+ { key: "scale", val: 1, prog: 1 }
1919
+ ];
1920
+ var pulsePreset = [
1921
+ { key: "scale", val: 1, prog: 0 },
1922
+ { key: "scale", val: 1.1, prog: 0.5 },
1923
+ { key: "scale", val: 1, prog: 1 }
1924
+ ];
1925
+ var rotateInPreset = [
1926
+ { key: "rotate", val: -180, prog: 0 },
1927
+ { key: "rotate", val: 0, prog: 1 }
1928
+ ];
1929
+ var blurInPreset = [
1930
+ { key: "blur", val: 10, prog: 0 },
1931
+ { key: "blur", val: 0, prog: 1 }
1932
+ ];
1933
+ var fadeInScalePreset = [
1934
+ { key: "opacity", val: 0, prog: 0 },
1935
+ { key: "opacity", val: 1, prog: 1 },
1936
+ { key: "scale", val: 0.8, prog: 0 },
1937
+ { key: "scale", val: 1, prog: 1 }
1938
+ ];
1939
+ var slideInFadePreset = [
1940
+ { key: "translateX", val: -50, prog: 0 },
1941
+ { key: "translateX", val: 0, prog: 1 },
1942
+ { key: "opacity", val: 0, prog: 0 },
1943
+ { key: "opacity", val: 1, prog: 1 }
1944
+ ];
1945
+ var slideInLeftStringPreset = [
1946
+ { key: "translateX", val: "-100px", prog: 0 },
1947
+ { key: "translateX", val: "0px", prog: 1 }
1948
+ ];
1949
+ var slideInRightStringPreset = [
1950
+ { key: "translateX", val: "100px", prog: 0 },
1951
+ { key: "translateX", val: "0px", prog: 1 }
1952
+ ];
1953
+ var slideInTopStringPreset = [
1954
+ { key: "translateY", val: "-100px", prog: 0 },
1955
+ { key: "translateY", val: "0px", prog: 1 }
1956
+ ];
1957
+ var slideInBottomStringPreset = [
1958
+ { key: "translateY", val: "100px", prog: 0 },
1959
+ { key: "translateY", val: "0px", prog: 1 }
1960
+ ];
1961
+ var rotateInStringPreset = [
1962
+ { key: "rotate", val: "-180deg", prog: 0 },
1963
+ { key: "rotate", val: "0deg", prog: 1 }
1964
+ ];
1965
+ var blurInStringPreset = [
1966
+ { key: "blur", val: "10px", prog: 0 },
1967
+ { key: "blur", val: "0px", prog: 1 }
1968
+ ];
1969
+ var scaleInStringPreset = [
1970
+ { key: "scale", val: 0, prog: 0 },
1971
+ { key: "scale", val: 1, prog: 1 }
1972
+ ];
1973
+ var slideInLeftResponsivePreset = [
1974
+ { key: "translateX", val: "-50vw", prog: 0 },
1975
+ { key: "translateX", val: "0vw", prog: 1 }
1976
+ ];
1977
+ var slideInTopResponsivePreset = [
1978
+ { key: "translateY", val: "-50vh", prog: 0 },
1979
+ { key: "translateY", val: "0vh", prog: 1 }
1980
+ ];
1981
+ var backgroundColorPreset = [
1982
+ { key: "backgroundColor", val: "#ff0000", prog: 0 },
1983
+ { key: "backgroundColor", val: "#0000ff", prog: 1 }
1984
+ ];
1985
+ var borderRadiusPreset = [
1986
+ { key: "borderRadius", val: "0px", prog: 0 },
1987
+ { key: "borderRadius", val: "50px", prog: 1 }
1988
+ ];
1989
+ var boxShadowPreset = [
1990
+ { key: "boxShadow", val: "0px 0px 0px rgba(0,0,0,0)", prog: 0 },
1991
+ { key: "boxShadow", val: "10px 10px 20px rgba(0,0,0,0.5)", prog: 1 }
1992
+ ];
1993
+ var fontSizePreset = [
1994
+ { key: "fontSize", val: "12px", prog: 0 },
1995
+ { key: "fontSize", val: "24px", prog: 1 }
1996
+ ];
1997
+ var letterSpacingPreset = [
1998
+ { key: "letterSpacing", val: "0px", prog: 0 },
1999
+ { key: "letterSpacing", val: "5px", prog: 1 }
2000
+ ];
2001
+ var lineHeightPreset = [
2002
+ { key: "lineHeight", val: "1", prog: 0 },
2003
+ { key: "lineHeight", val: "2", prog: 1 }
2004
+ ];
2005
+ var textShadowPreset = [
2006
+ { key: "textShadow", val: "0px 0px 0px rgba(0,0,0,0)", prog: 0 },
2007
+ { key: "textShadow", val: "2px 2px 4px rgba(0,0,0,0.5)", prog: 1 }
2008
+ ];
2009
+ var widthPreset = [
2010
+ { key: "width", val: "0px", prog: 0 },
2011
+ { key: "width", val: "100%", prog: 1 }
2012
+ ];
2013
+ var heightPreset = [
2014
+ { key: "height", val: "0px", prog: 0 },
2015
+ { key: "height", val: "100%", prog: 1 }
2016
+ ];
2017
+ var marginPreset = [
2018
+ { key: "margin", val: "0px", prog: 0 },
2019
+ { key: "margin", val: "20px", prog: 1 }
2020
+ ];
2021
+ var paddingPreset = [
2022
+ { key: "padding", val: "0px", prog: 0 },
2023
+ { key: "padding", val: "20px", prog: 1 }
2024
+ ];
2025
+ var morphingCardPreset = [
2026
+ { key: "borderRadius", val: "0px", prog: 0 },
2027
+ { key: "borderRadius", val: "20px", prog: 0.5 },
2028
+ { key: "borderRadius", val: "50px", prog: 1 },
2029
+ { key: "boxShadow", val: "0px 0px 0px rgba(0,0,0,0)", prog: 0 },
2030
+ { key: "boxShadow", val: "0px 10px 30px rgba(0,0,0,0.3)", prog: 1 },
2031
+ { key: "backgroundColor", val: "#ffffff", prog: 0 },
2032
+ { key: "backgroundColor", val: "#f0f0f0", prog: 1 }
2033
+ ];
2034
+ var textRevealPreset = [
2035
+ { key: "opacity", val: 0, prog: 0 },
2036
+ { key: "opacity", val: 1, prog: 1 },
2037
+ { key: "letterSpacing", val: "10px", prog: 0 },
2038
+ { key: "letterSpacing", val: "0px", prog: 1 },
2039
+ { key: "textShadow", val: "0px 0px 0px rgba(0,0,0,0)", prog: 0 },
2040
+ { key: "textShadow", val: "2px 2px 4px rgba(0,0,0,0.5)", prog: 1 }
2041
+ ];
2042
+ var GenericEffectPresets = {
2043
+ fadeInPreset,
2044
+ fadeOutPreset,
2045
+ scaleInPreset,
2046
+ scaleOutPreset,
2047
+ slideInLeftPreset,
2048
+ slideInRightPreset,
2049
+ slideInTopPreset,
2050
+ slideInBottomPreset,
2051
+ bouncePreset,
2052
+ pulsePreset,
2053
+ rotateInPreset,
2054
+ blurInPreset,
2055
+ fadeInScalePreset,
2056
+ slideInFadePreset,
2057
+ // String-based presets
2058
+ slideInLeftStringPreset,
2059
+ slideInRightStringPreset,
2060
+ slideInTopStringPreset,
2061
+ slideInBottomStringPreset,
2062
+ rotateInStringPreset,
2063
+ blurInStringPreset,
2064
+ scaleInStringPreset,
2065
+ slideInLeftResponsivePreset,
2066
+ slideInTopResponsivePreset,
2067
+ // Custom CSS property presets
2068
+ backgroundColorPreset,
2069
+ borderRadiusPreset,
2070
+ boxShadowPreset,
2071
+ fontSizePreset,
2072
+ letterSpacingPreset,
2073
+ lineHeightPreset,
2074
+ textShadowPreset,
2075
+ widthPreset,
2076
+ heightPreset,
2077
+ marginPreset,
2078
+ paddingPreset,
2079
+ morphingCardPreset,
2080
+ textRevealPreset
2081
+ };
2082
+
2083
+ // src/components/effects/index.ts
2084
+ registerEffect(config2.displayName, BlurEffect, config2);
2085
+ registerEffect(config3.displayName, LoopEffect, config3);
2086
+ registerEffect(config4.displayName, PanEffect, config4);
2087
+ registerEffect(config5.displayName, ZoomEffect, config5);
2088
+ registerEffect("generic", UniversalEffect, config);
2089
+ registerEffect(config6.displayName, ShakeEffect, config6);
2090
+ registerEffect(
2091
+ config7.displayName,
2092
+ StretchEffect,
2093
+ config7
2094
+ );
2095
+
2096
+ // src/components/layouts/BaseLayout.tsx
2097
+ var Layout = ({ id, children, data, context }) => {
2098
+ const { containerProps = {}, childrenProps = [], repeatChildrenProps = {} } = data;
2099
+ const overrideStyles = useAnimatedStyles(id);
2100
+ const childrenArray = import_react13.Children.toArray(children);
2101
+ const enhancedStyle = (0, import_react13.useMemo)(
2102
+ () => ({
2103
+ ...!context?.boundaries?.reset ? context?.boundaries : {},
2104
+ ...containerProps.style,
2105
+ ...overrideStyles
2106
+ }),
2107
+ [
2108
+ !context?.boundaries?.reset ? context?.boundaries : {},
2109
+ containerProps.style,
2110
+ overrideStyles
2111
+ ]
2112
+ );
2113
+ if (Object.keys(repeatChildrenProps).length <= 0 && childrenProps.length <= 0) {
2114
+ if (data.isAbsoluteFill) {
2115
+ return /* @__PURE__ */ import_react13.default.createElement(
2116
+ import_remotion9.AbsoluteFill,
2117
+ {
2118
+ ...containerProps,
2119
+ style: enhancedStyle
2120
+ },
2121
+ childrenArray
2122
+ );
2123
+ }
2124
+ return /* @__PURE__ */ import_react13.default.createElement(
2125
+ "div",
2126
+ {
2127
+ id,
2128
+ ...containerProps,
2129
+ style: enhancedStyle
2130
+ },
2131
+ childrenArray.map((child, index) => /* @__PURE__ */ import_react13.default.createElement(import_react13.default.Fragment, { key: index }, child))
2132
+ );
2133
+ }
2134
+ if (data.isAbsoluteFill) {
2135
+ return /* @__PURE__ */ import_react13.default.createElement(
2136
+ import_remotion9.AbsoluteFill,
2137
+ {
2138
+ id,
2139
+ ...containerProps,
2140
+ style: enhancedStyle
2141
+ },
2142
+ childrenArray.map((child, index) => /* @__PURE__ */ import_react13.default.createElement(
2143
+ "div",
2144
+ {
2145
+ key: index,
2146
+ ...childrenProps.length > 0 && index < childrenProps.length ? childrenProps[index] : repeatChildrenProps ? repeatChildrenProps : {}
2147
+ },
2148
+ child
2149
+ ))
2150
+ );
2151
+ }
2152
+ return /* @__PURE__ */ import_react13.default.createElement(
2153
+ "div",
2154
+ {
2155
+ id,
2156
+ ...containerProps,
2157
+ style: enhancedStyle
2158
+ },
2159
+ childrenArray.map((child, index) => /* @__PURE__ */ import_react13.default.createElement(
2160
+ "div",
2161
+ {
2162
+ key: index,
2163
+ ...childrenProps.length > 0 && index < childrenProps.length ? childrenProps[index] : repeatChildrenProps ? repeatChildrenProps : {}
2164
+ },
2165
+ child
2166
+ ))
2167
+ );
2168
+ };
2169
+ var config8 = {
2170
+ displayName: "BaseLayout",
2171
+ type: "layout",
2172
+ isInnerSequence: false
2173
+ };
2174
+
2175
+ // src/components/layouts/index.ts
2176
+ registerComponent(
2177
+ config8.displayName,
2178
+ Layout,
2179
+ "layout",
2180
+ config8
2181
+ );
2182
+
2183
+ // src/components/atoms/ShapeAtom.tsx
2184
+ var import_react14 = __toESM(require("react"));
2185
+ var import_remotion10 = require("remotion");
2186
+ var Atom = ({ data }) => {
2187
+ const frame = (0, import_remotion10.useCurrentFrame)();
2188
+ const { shape, color, rotation, style } = data;
2189
+ const rotationStyle = rotation ? {
2190
+ transform: `rotate(${(0, import_remotion10.interpolate)(
2191
+ frame % rotation.duration,
2192
+ [0, rotation.duration],
2193
+ [0, 360],
2194
+ {
2195
+ extrapolateLeft: "clamp",
2196
+ extrapolateRight: "clamp",
2197
+ easing: import_remotion10.Easing.linear
2198
+ }
2199
+ )}deg)`
2200
+ } : {};
2201
+ const baseStyle = {
2202
+ width: "100%",
2203
+ height: "100%",
2204
+ ...style,
2205
+ ...rotationStyle
2206
+ };
2207
+ switch (shape) {
2208
+ case "circle":
2209
+ return /* @__PURE__ */ import_react14.default.createElement("div", { style: { ...baseStyle, backgroundColor: color, borderRadius: "50%" } });
2210
+ case "rectangle":
2211
+ return /* @__PURE__ */ import_react14.default.createElement("div", { style: { ...baseStyle, backgroundColor: color } });
2212
+ default:
2213
+ return null;
2214
+ }
2215
+ };
2216
+ var config9 = {
2217
+ displayName: "ShapeAtom",
2218
+ type: "atom",
2219
+ isInnerSequence: false
2220
+ };
2221
+
2222
+ // src/components/atoms/ImageAtom.tsx
2223
+ var import_react15 = __toESM(require("react"));
2224
+ var import_remotion11 = require("remotion");
2225
+ var CORS_PROXIES = [
2226
+ "https://thingproxy.freeboard.io/fetch/",
2227
+ "https://api.allorigins.win/raw?url=",
2228
+ "https://corsproxy.io/?"
2229
+ ];
2230
+ var getCorsProxyUrl = (url) => {
2231
+ return `${CORS_PROXIES[0]}${encodeURIComponent(url)}`;
2232
+ };
2233
+ var useImageSource = (src, proxySrc) => {
2234
+ const [imageSource, setImageSource] = (0, import_react15.useState)(src);
2235
+ const [isLoading, setIsLoading] = (0, import_react15.useState)(false);
2236
+ const [hasError, setHasError] = (0, import_react15.useState)(false);
2237
+ const [handle] = (0, import_react15.useState)(() => (0, import_remotion11.delayRender)("Loading image"));
2238
+ (0, import_react15.useEffect)(() => {
2239
+ if (!src.startsWith("http")) {
2240
+ setImageSource(src);
2241
+ (0, import_remotion11.continueRender)(handle);
2242
+ return;
2243
+ }
2244
+ setIsLoading(true);
2245
+ setHasError(false);
2246
+ const testImage = new Image();
2247
+ testImage.crossOrigin = "anonymous";
2248
+ const handleSuccess = () => {
2249
+ setImageSource(src);
2250
+ setIsLoading(false);
2251
+ (0, import_remotion11.continueRender)(handle);
2252
+ };
2253
+ const handleError = () => {
2254
+ let proxyUrl;
2255
+ if (proxySrc) {
2256
+ proxyUrl = `${proxySrc}?url=${encodeURIComponent(src)}`;
2257
+ } else {
2258
+ proxyUrl = getCorsProxyUrl(src);
2259
+ }
2260
+ setImageSource(proxyUrl);
2261
+ setIsLoading(false);
2262
+ (0, import_remotion11.continueRender)(handle);
2263
+ };
2264
+ testImage.onload = handleSuccess;
2265
+ testImage.onerror = handleError;
2266
+ testImage.src = src;
2267
+ return () => {
2268
+ testImage.onload = null;
2269
+ testImage.onerror = null;
2270
+ };
2271
+ }, [src, proxySrc, handle]);
2272
+ return { imageSource, isLoading, hasError };
2273
+ };
2274
+ var Atom2 = ({ data, id }) => {
2275
+ const overrideStyles = useAnimatedStyles(id);
2276
+ const { imageSource, isLoading, hasError } = useImageSource(data.src, data.proxySrc);
2277
+ const source = (0, import_react15.useMemo)(() => {
2278
+ if (data.src.startsWith("http")) {
2279
+ return imageSource;
2280
+ }
2281
+ return (0, import_remotion11.staticFile)(data.src);
2282
+ }, [data.src, imageSource]);
2283
+ const enhancedStyle = (0, import_react15.useMemo)(() => ({
2284
+ ...data.style,
2285
+ ...overrideStyles
2286
+ }), [data.style, overrideStyles, isLoading, hasError]);
2287
+ return /* @__PURE__ */ import_react15.default.createElement(
2288
+ import_remotion11.Img,
2289
+ {
2290
+ className: data.className,
2291
+ src: source,
2292
+ style: enhancedStyle,
2293
+ crossOrigin: data.src.startsWith("http") ? "anonymous" : void 0,
2294
+ maxRetries: 4,
2295
+ onError: () => {
2296
+ console.warn(`Failed to load image: ${data.src}`);
2297
+ }
2298
+ }
2299
+ );
2300
+ };
2301
+ var config10 = {
2302
+ displayName: "ImageAtom",
2303
+ type: "atom",
2304
+ isInnerSequence: false
2305
+ };
2306
+
2307
+ // src/components/atoms/TextAtom.tsx
2308
+ var import_react17 = __toESM(require("react"));
2309
+ var import_remotion13 = require("remotion");
2310
+
2311
+ // src/hooks/useFontLoader.ts
2312
+ var import_react16 = require("react");
2313
+ var import_remotion12 = require("remotion");
2314
+
2315
+ // src/utils/fontUtils.ts
2316
+ var fontUtils = __toESM(require("@remotion/google-fonts"));
2317
+ var availableFonts = [];
2318
+ var getAvailableFonts2 = async () => {
2319
+ if (availableFonts.length === 0) {
2320
+ try {
2321
+ availableFonts = fontUtils.getAvailableFonts();
2322
+ } catch (error) {
2323
+ console.warn("Failed to load @remotion/google-fonts:", error);
2324
+ availableFonts = [];
2325
+ }
2326
+ }
2327
+ return availableFonts;
2328
+ };
2329
+ var loadedFonts = /* @__PURE__ */ new Map();
2330
+ var loadGoogleFont = async (fontFamily, options = {}) => {
2331
+ if (!fontFamily || typeof fontFamily !== "string" || fontFamily === "") {
2332
+ console.warn("Invalid fontFamily provided:", fontFamily);
2333
+ return "sans-serif";
2334
+ }
2335
+ const fontKey = `${fontFamily}-${JSON.stringify(options)}`;
2336
+ if (loadedFonts.has(fontKey)) {
2337
+ return loadedFonts.get(fontKey);
2338
+ }
2339
+ try {
2340
+ const fonts = await getAvailableFonts2();
2341
+ const thisFont = fonts.find((font) => font.importName === fontFamily);
2342
+ if (thisFont?.load) {
2343
+ const fontPackage = await thisFont.load();
2344
+ const allFontStuff = fontPackage.loadFont("normal", {
2345
+ subsets: options.subsets || ["latin"],
2346
+ weights: options.weights || ["400"]
2347
+ });
2348
+ await allFontStuff.waitUntilDone();
2349
+ loadedFonts.set(fontKey, allFontStuff.fontFamily);
2350
+ return allFontStuff.fontFamily;
2351
+ } else {
2352
+ throw new Error(
2353
+ `Font Package @remotion/google-fonts/${fontFamily} does not have loadFont method`
2354
+ );
2355
+ }
2356
+ } catch (error) {
2357
+ console.warn(`Failed to load font ${fontFamily}:`, error);
2358
+ try {
2359
+ const alternativeNames = [
2360
+ fontFamily.toLowerCase().replace(/\s+/g, ""),
2361
+ fontFamily.toLowerCase().replace(/\s+/g, "-"),
2362
+ fontFamily.toLowerCase().replace(/\s+/g, "_")
2363
+ ];
2364
+ for (const altName of alternativeNames) {
2365
+ if (altName === fontFamily.toLowerCase().replace(/\s+/g, "-")) {
2366
+ continue;
2367
+ }
2368
+ try {
2369
+ const altFontPackage = await import(`@remotion/google-fonts/${altName}`);
2370
+ if (altFontPackage.loadFont) {
2371
+ const { fontFamily: loadedFontFamily } = await altFontPackage.loadFont("normal", {
2372
+ subsets: options.subsets || ["latin"],
2373
+ weights: options.weights || ["400"],
2374
+ display: options.display || "swap",
2375
+ preload: options.preload !== false
2376
+ });
2377
+ loadedFonts.set(fontKey, loadedFontFamily);
2378
+ return loadedFontFamily;
2379
+ }
2380
+ } catch (altError) {
2381
+ continue;
2382
+ }
2383
+ }
2384
+ } catch (altError) {
2385
+ }
2386
+ const fallbackFontFamily = `"${fontFamily}"`;
2387
+ loadedFonts.set(fontKey, fallbackFontFamily);
2388
+ return fallbackFontFamily;
2389
+ }
2390
+ };
2391
+ var loadMultipleFonts = async (fonts) => {
2392
+ const loadPromises = fonts.map(async ({ family, options }) => {
2393
+ const fontFamily = await loadGoogleFont(family, options);
2394
+ return { family, fontFamily };
2395
+ });
2396
+ const results = await Promise.all(loadPromises);
2397
+ const fontMap = /* @__PURE__ */ new Map();
2398
+ results.forEach(({ family, fontFamily }) => {
2399
+ fontMap.set(family, fontFamily);
2400
+ });
2401
+ return fontMap;
2402
+ };
2403
+ var getLoadedFontFamily = (fontFamily, options = {}) => {
2404
+ const fontKey = `${fontFamily}-${JSON.stringify(options)}`;
2405
+ return loadedFonts.get(fontKey);
2406
+ };
2407
+ var preloadCommonFonts = async () => {
2408
+ const commonFonts = [
2409
+ { family: "Inter", options: { weights: ["400", "500", "600", "700"] } },
2410
+ { family: "Roboto", options: { weights: ["400", "500", "700"] } },
2411
+ { family: "Open Sans", options: { weights: ["400", "600", "700"] } },
2412
+ { family: "Lato", options: { weights: ["400", "700"] } }
2413
+ ];
2414
+ return await loadMultipleFonts(commonFonts);
2415
+ };
2416
+ var isFontLoaded = (fontFamily, options = {}) => {
2417
+ const fontKey = `${fontFamily}-${JSON.stringify(options)}`;
2418
+ return loadedFonts.has(fontKey);
2419
+ };
2420
+ var clearFontCache = () => {
2421
+ loadedFonts.clear();
2422
+ };
2423
+ var getLoadedFonts = () => {
2424
+ return new Map(loadedFonts);
2425
+ };
2426
+ var isFontAvailable = async (fontFamily) => {
2427
+ if (!fontFamily || typeof fontFamily !== "string") {
2428
+ return false;
2429
+ }
2430
+ try {
2431
+ const fonts = await getAvailableFonts2();
2432
+ const isInAvailableFonts = fonts.some(
2433
+ (font) => font.importName === fontFamily
2434
+ );
2435
+ if (isInAvailableFonts) {
2436
+ return true;
2437
+ }
2438
+ const normalizedFontName = fontFamily.trim().replace(/\s+/g, "-").toLowerCase();
2439
+ const fontPackage = await import(`@remotion/google-fonts/${normalizedFontName}`);
2440
+ return !!fontPackage.loadFont;
2441
+ } catch (error) {
2442
+ return false;
2443
+ }
2444
+ };
2445
+ var getNormalizedFontName = (fontFamily) => {
2446
+ if (!fontFamily || typeof fontFamily !== "string") {
2447
+ return "";
2448
+ }
2449
+ return fontFamily.trim().replace(/\s+/g, "-").toLowerCase();
2450
+ };
2451
+
2452
+ // src/hooks/useFontLoader.ts
2453
+ var useFontLoader = (options = {}) => {
2454
+ const [state, setState] = (0, import_react16.useState)({
2455
+ loadedFonts: /* @__PURE__ */ new Map(),
2456
+ loadingFonts: /* @__PURE__ */ new Set(),
2457
+ errorFonts: /* @__PURE__ */ new Map()
2458
+ });
2459
+ const loadFont = (0, import_react16.useCallback)(
2460
+ async (fontFamily, fontOptions = {}) => {
2461
+ const fontKey = `${fontFamily}-${JSON.stringify(fontOptions)}`;
2462
+ if (state.loadedFonts.has(fontKey) || state.loadingFonts.has(fontFamily)) {
2463
+ return state.loadedFonts.get(fontKey) || `"${fontFamily}", sans-serif`;
2464
+ }
2465
+ setState((prev) => ({
2466
+ ...prev,
2467
+ loadingFonts: new Set(prev.loadingFonts).add(fontFamily)
2468
+ }));
2469
+ try {
2470
+ const cssValue = await loadGoogleFont(fontFamily, fontOptions);
2471
+ if (cssValue !== null) {
2472
+ setState((prev) => ({
2473
+ ...prev,
2474
+ loadedFonts: new Map(prev.loadedFonts).set(fontKey, cssValue),
2475
+ loadingFonts: new Set(
2476
+ [...prev.loadingFonts].filter((f) => f !== fontFamily)
2477
+ )
2478
+ }));
2479
+ options.onLoad?.(fontFamily, cssValue);
2480
+ return cssValue;
2481
+ } else {
2482
+ throw new Error(
2483
+ `Font Package @remotion/google-fonts/${fontFamily} not found`
2484
+ );
2485
+ }
2486
+ } catch (error) {
2487
+ const errorObj = error instanceof Error ? error : new Error(String(error));
2488
+ setState((prev) => ({
2489
+ ...prev,
2490
+ errorFonts: new Map(prev.errorFonts).set(fontFamily, errorObj),
2491
+ loadingFonts: new Set(
2492
+ [...prev.loadingFonts].filter((f) => f !== fontFamily)
2493
+ )
2494
+ }));
2495
+ options.onError?.(fontFamily, errorObj);
2496
+ const fallbackValue = `"${fontFamily}", sans-serif`;
2497
+ return fallbackValue;
2498
+ }
2499
+ },
2500
+ [state.loadedFonts, state.loadingFonts, options]
2501
+ );
2502
+ const loadMultipleFonts2 = (0, import_react16.useCallback)(
2503
+ async (fonts) => {
2504
+ const fontsToLoad = fonts.filter(({ family, options: options2 = {} }) => {
2505
+ const fontKey = `${family}-${JSON.stringify(options2)}`;
2506
+ return !state.loadedFonts.has(fontKey) && !state.loadingFonts.has(family);
2507
+ });
2508
+ if (fontsToLoad.length === 0) {
2509
+ return state.loadedFonts;
2510
+ }
2511
+ setState((prev) => ({
2512
+ ...prev,
2513
+ loadingFonts: /* @__PURE__ */ new Set([
2514
+ ...prev.loadingFonts,
2515
+ ...fontsToLoad.map((f) => f.family)
2516
+ ])
2517
+ }));
2518
+ try {
2519
+ const fontMap = await loadMultipleFonts(fontsToLoad);
2520
+ const newFontsMap = /* @__PURE__ */ new Map();
2521
+ fontsToLoad.forEach(({ family, options: options2 = {} }) => {
2522
+ const fontKey = `${family}-${JSON.stringify(options2)}`;
2523
+ const cssValue = fontMap.get(family);
2524
+ if (cssValue) {
2525
+ newFontsMap.set(fontKey, cssValue);
2526
+ }
2527
+ });
2528
+ setState((prev) => ({
2529
+ ...prev,
2530
+ loadedFonts: new Map([...prev.loadedFonts, ...newFontsMap]),
2531
+ loadingFonts: new Set(
2532
+ [...prev.loadingFonts].filter(
2533
+ (f) => !fontsToLoad.some((ftl) => ftl.family === f)
2534
+ )
2535
+ )
2536
+ }));
2537
+ fontsToLoad.forEach(({ family }) => {
2538
+ const cssValue = fontMap.get(family);
2539
+ if (cssValue) {
2540
+ options.onLoad?.(family, cssValue);
2541
+ }
2542
+ });
2543
+ return fontMap;
2544
+ } catch (error) {
2545
+ const errorObj = error instanceof Error ? error : new Error(String(error));
2546
+ setState((prev) => ({
2547
+ ...prev,
2548
+ errorFonts: new Map(prev.errorFonts).set("multiple", errorObj),
2549
+ loadingFonts: new Set(
2550
+ [...prev.loadingFonts].filter(
2551
+ (f) => !fontsToLoad.some((ftl) => ftl.family === f)
2552
+ )
2553
+ )
2554
+ }));
2555
+ options.onError?.("multiple", errorObj);
2556
+ return state.loadedFonts;
2557
+ }
2558
+ },
2559
+ [state.loadedFonts, state.loadingFonts, options]
2560
+ );
2561
+ const isFontReady = (0, import_react16.useCallback)(
2562
+ (fontFamily, options2 = {}) => {
2563
+ const fontKey = `${fontFamily}-${JSON.stringify(options2)}`;
2564
+ return state.loadedFonts.has(fontKey);
2565
+ },
2566
+ [state.loadedFonts]
2567
+ );
2568
+ const areFontsReady = (0, import_react16.useCallback)(
2569
+ (fontFamilies) => {
2570
+ return fontFamilies.every(({ family, options: options2 = {} }) => {
2571
+ const fontKey = `${family}-${JSON.stringify(options2)}`;
2572
+ return state.loadedFonts.has(fontKey);
2573
+ });
2574
+ },
2575
+ [state.loadedFonts]
2576
+ );
2577
+ const getFontFamily = (0, import_react16.useCallback)(
2578
+ (fontFamily, options2 = {}) => {
2579
+ const fontKey = `${fontFamily}-${JSON.stringify(options2)}`;
2580
+ return state.loadedFonts.get(fontKey);
2581
+ },
2582
+ [state.loadedFonts]
2583
+ );
2584
+ const getFontError = (0, import_react16.useCallback)(
2585
+ (fontFamily) => {
2586
+ return state.errorFonts.get(fontFamily);
2587
+ },
2588
+ [state.errorFonts]
2589
+ );
2590
+ const clearErrors = (0, import_react16.useCallback)(() => {
2591
+ setState((prev) => ({
2592
+ ...prev,
2593
+ errorFonts: /* @__PURE__ */ new Map()
2594
+ }));
2595
+ }, []);
2596
+ return {
2597
+ // State
2598
+ loadedFonts: state.loadedFonts,
2599
+ loadingFonts: state.loadingFonts,
2600
+ errorFonts: state.errorFonts,
2601
+ // Actions
2602
+ loadFont,
2603
+ loadMultipleFonts: loadMultipleFonts2,
2604
+ isFontReady,
2605
+ areFontsReady,
2606
+ getFontFamily,
2607
+ getFontError,
2608
+ clearErrors
2609
+ };
2610
+ };
2611
+ var useFont = (fontFamily, options = {}) => {
2612
+ const { loadFont, isFontReady, getFontFamily, getFontError, ...rest } = useFontLoader(options);
2613
+ const [isLoaded, setIsLoaded] = (0, import_react16.useState)(false);
2614
+ const [error, setError] = (0, import_react16.useState)(null);
2615
+ const [renderHandle] = (0, import_react16.useState)(
2616
+ () => (0, import_remotion12.delayRender)(`Loading font: ${fontFamily}`)
2617
+ );
2618
+ const initialFontFamily = getFontFamily(fontFamily, options) || `"${fontFamily}", sans-serif`;
2619
+ const [fontFamilyValue, setFontFamilyValue] = (0, import_react16.useState)(initialFontFamily);
2620
+ (0, import_react16.useEffect)(() => {
2621
+ const loadFontAsync = async () => {
2622
+ try {
2623
+ const cssValue = await loadFont(fontFamily, options);
2624
+ setFontFamilyValue(cssValue);
2625
+ setIsLoaded(true);
2626
+ setError(null);
2627
+ (0, import_remotion12.continueRender)(renderHandle);
2628
+ } catch (err) {
2629
+ setError(err instanceof Error ? err : new Error(String(err)));
2630
+ setIsLoaded(false);
2631
+ (0, import_remotion12.continueRender)(renderHandle);
2632
+ }
2633
+ };
2634
+ if (!isFontReady(fontFamily, options)) {
2635
+ loadFontAsync();
2636
+ } else {
2637
+ const cachedValue = getFontFamily(fontFamily, options);
2638
+ if (cachedValue) {
2639
+ setFontFamilyValue(cachedValue);
2640
+ }
2641
+ setIsLoaded(true);
2642
+ (0, import_remotion12.continueRender)(renderHandle);
2643
+ }
2644
+ }, [fontFamily, loadFont, isFontReady, getFontFamily, options, renderHandle]);
2645
+ return {
2646
+ isLoaded,
2647
+ error,
2648
+ isReady: isFontReady(fontFamily, options),
2649
+ fontFamily: fontFamilyValue,
2650
+ ...rest
2651
+ };
2652
+ };
2653
+
2654
+ // src/components/atoms/TextAtom.tsx
2655
+ var Atom3 = ({ id, data }) => {
2656
+ const overrideStyles = useAnimatedStyles(id);
2657
+ const [isFontLoading, setIsFontLoading] = (0, import_react17.useState)(false);
2658
+ const [renderHandle] = (0, import_react17.useState)(
2659
+ () => (0, import_remotion13.delayRender)(`Loading font: ${data.font?.family}`)
2660
+ );
2661
+ const { isLoaded, error, isReady, fontFamily } = useFont(
2662
+ data.font?.family || "Inter",
2663
+ {
2664
+ weights: data.font?.weights || ["400"],
2665
+ subsets: data.font?.subsets || ["latin"],
2666
+ display: data.font?.display || "swap",
2667
+ preload: data.font?.preload !== false,
2668
+ onLoad: (family, cssValue) => {
2669
+ setIsFontLoading(false);
2670
+ (0, import_remotion13.continueRender)(renderHandle);
2671
+ },
2672
+ onError: (family, error2) => {
2673
+ setIsFontLoading(false);
2674
+ (0, import_remotion13.continueRender)(renderHandle);
2675
+ }
2676
+ }
2677
+ );
2678
+ (0, import_react17.useEffect)(() => {
2679
+ if (data.font?.family) {
2680
+ if (isReady || isLoaded) {
2681
+ setIsFontLoading(false);
2682
+ } else if (!isReady && !isLoaded && !error) {
2683
+ setIsFontLoading(true);
2684
+ }
2685
+ }
2686
+ }, [data.font, isReady, isLoaded, error]);
2687
+ const enhancedStyle = (0, import_react17.useMemo)(() => {
2688
+ const baseStyle = {
2689
+ fontFamily,
2690
+ ...data.style
2691
+ };
2692
+ if (data.gradient) {
2693
+ return {
2694
+ ...baseStyle,
2695
+ backgroundImage: data.gradient,
2696
+ backgroundClip: "text",
2697
+ WebkitBackgroundClip: "text",
2698
+ color: "transparent",
2699
+ ...overrideStyles
2700
+ };
2701
+ }
2702
+ return {
2703
+ ...baseStyle,
2704
+ ...overrideStyles
2705
+ };
2706
+ }, [fontFamily, data.style, data.gradient, overrideStyles]);
2707
+ if (isFontLoading && data.loadingState?.showLoadingIndicator) {
2708
+ return /* @__PURE__ */ import_react17.default.createElement("div", { style: enhancedStyle, className: data.className }, /* @__PURE__ */ import_react17.default.createElement("span", { style: data.loadingState.loadingStyle }, data.loadingState.loadingText || "Loading..."));
2709
+ }
2710
+ if (error && data.errorState?.showErrorIndicator) {
2711
+ return /* @__PURE__ */ import_react17.default.createElement("div", { style: enhancedStyle, className: data.className }, /* @__PURE__ */ import_react17.default.createElement("span", { style: data.errorState.errorStyle }, data.errorState.errorText || data.text));
2712
+ }
2713
+ return /* @__PURE__ */ import_react17.default.createElement(
2714
+ "div",
2715
+ {
2716
+ style: enhancedStyle,
2717
+ className: data.className,
2718
+ "data-font-loading": isFontLoading,
2719
+ "data-font-loaded": isReady || isLoaded,
2720
+ "data-font-error": !!error,
2721
+ "data-font-family": data.font?.family || "system"
2722
+ },
2723
+ data.text
2724
+ );
2725
+ };
2726
+ var config11 = {
2727
+ displayName: "TextAtom",
2728
+ type: "atom",
2729
+ isInnerSequence: false
2730
+ };
2731
+
2732
+ // src/components/atoms/VideoAtom.tsx
2733
+ var import_react18 = __toESM(require("react"));
2734
+ var import_remotion14 = require("remotion");
2735
+ var import_zod2 = require("zod");
2736
+ var VideoAtomDataProps = import_zod2.z.object({
2737
+ src: import_zod2.z.string(),
2738
+ // Video source URL
2739
+ srcDuration: import_zod2.z.number().optional(),
2740
+ // Video duration in seconds (or to say it more accurately, each iteration duration in a loop))
2741
+ style: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.any()).optional(),
2742
+ // CSS styles object
2743
+ containerClassName: import_zod2.z.string().optional(),
2744
+ // CSS class names
2745
+ className: import_zod2.z.string().optional(),
2746
+ // CSS class names
2747
+ startFrom: import_zod2.z.number().optional(),
2748
+ // Start playback from this time (seconds)
2749
+ endAt: import_zod2.z.number().optional(),
2750
+ // End playback at this time (seconds)
2751
+ playbackRate: import_zod2.z.number().optional(),
2752
+ // Playback speed multiplier
2753
+ volume: import_zod2.z.number().optional(),
2754
+ // Volume level (0-1)
2755
+ muted: import_zod2.z.boolean().optional(),
2756
+ // Mute video audio
2757
+ loop: import_zod2.z.boolean().optional(),
2758
+ // Whether to loop the video
2759
+ fit: import_zod2.z.enum(["contain", "cover", "fill", "none", "scale-down"]).optional()
2760
+ // Object fit style
2761
+ });
2762
+ var Atom4 = ({ data, id, context }) => {
2763
+ const { fps } = (0, import_remotion14.useVideoConfig)();
2764
+ const overrideStyles = useAnimatedStyles(id);
2765
+ const frame = (0, import_remotion14.useCurrentFrame)();
2766
+ const source = (0, import_react18.useMemo)(() => {
2767
+ if (data.src.startsWith("http")) {
2768
+ return data.src;
2769
+ }
2770
+ return (0, import_remotion14.staticFile)(data.src);
2771
+ }, [data.src]);
2772
+ const trimBefore = (0, import_react18.useMemo)(() => {
2773
+ return data.startFrom ? data.startFrom * fps : void 0;
2774
+ }, [data.startFrom, fps]);
2775
+ const trimAfter = (0, import_react18.useMemo)(() => {
2776
+ return data.endAt ? data.endAt * fps : void 0;
2777
+ }, [data.endAt, fps]);
2778
+ const videoComponent = /* @__PURE__ */ import_react18.default.createElement(
2779
+ import_remotion14.OffthreadVideo,
2780
+ {
2781
+ className: data.className,
2782
+ src: source,
2783
+ style: data.style ? { ...data.style, ...data.fit ? { objectFit: data.fit } : {} } : {},
2784
+ trimBefore,
2785
+ trimAfter,
2786
+ playbackRate: data.playbackRate,
2787
+ volume: data.volume,
2788
+ muted: data.muted
2789
+ }
2790
+ );
2791
+ const videoWithStyles = data.containerClassName ? videoComponent : /* @__PURE__ */ import_react18.default.createElement(
2792
+ import_remotion14.OffthreadVideo,
2793
+ {
2794
+ className: data.className,
2795
+ src: source,
2796
+ style: data.style ? { ...data.style, ...data.fit ? { objectFit: data.fit } : {}, ...overrideStyles } : overrideStyles,
2797
+ trimBefore,
2798
+ trimAfter,
2799
+ playbackRate: data.playbackRate,
2800
+ volume: data.volume,
2801
+ muted: data.muted
2802
+ }
2803
+ );
2804
+ if (data.loop) {
2805
+ return /* @__PURE__ */ import_react18.default.createElement(import_remotion14.Loop, { times: Infinity, durationInFrames: data.srcDuration ? data.srcDuration * fps : context.timing?.durationInFrames, layout: "none" }, data.containerClassName ? /* @__PURE__ */ import_react18.default.createElement("div", { className: data.containerClassName, style: overrideStyles }, videoComponent) : videoWithStyles);
2806
+ }
2807
+ return data.containerClassName ? /* @__PURE__ */ import_react18.default.createElement("div", { className: data.containerClassName, style: overrideStyles }, videoComponent) : videoWithStyles;
2808
+ };
2809
+ var config12 = {
2810
+ displayName: "VideoAtom",
2811
+ type: "atom",
2812
+ isInnerSequence: false
2813
+ };
2814
+
2815
+ // src/components/atoms/AudioAtom.tsx
2816
+ var import_react19 = __toESM(require("react"));
2817
+ var import_remotion15 = require("remotion");
2818
+ var import_zod3 = require("zod");
2819
+ var AudioAtomMutedRangeProps = import_zod3.z.object({
2820
+ type: import_zod3.z.literal("range"),
2821
+ values: import_zod3.z.array(import_zod3.z.object({
2822
+ start: import_zod3.z.number(),
2823
+ // Start time in seconds
2824
+ end: import_zod3.z.number()
2825
+ // End time in seconds
2826
+ }))
2827
+ });
2828
+ var AudioAtomMutedFullProps = import_zod3.z.object({
2829
+ type: import_zod3.z.literal("full"),
2830
+ value: import_zod3.z.boolean()
2831
+ // true = muted, false = unmuted
2832
+ });
2833
+ var AudioAtomDataProps = import_zod3.z.object({
2834
+ src: import_zod3.z.string(),
2835
+ // Audio source URL
2836
+ startFrom: import_zod3.z.number().optional(),
2837
+ // Start playback from this time (seconds)
2838
+ endAt: import_zod3.z.number().optional(),
2839
+ // End playback at this time (seconds)
2840
+ volume: import_zod3.z.number().optional(),
2841
+ // Volume level (0-1)
2842
+ playbackRate: import_zod3.z.number().optional(),
2843
+ // Playback speed multiplier
2844
+ muted: import_zod3.z.union([AudioAtomMutedFullProps, AudioAtomMutedRangeProps]).optional()
2845
+ // Mute configuration
2846
+ });
2847
+ var Atom5 = ({ data }) => {
2848
+ const { fps } = (0, import_remotion15.useVideoConfig)();
2849
+ const { muted } = data;
2850
+ const frame = (0, import_remotion15.useCurrentFrame)();
2851
+ const isMuted = (0, import_react19.useMemo)(() => {
2852
+ if (muted?.type === "full") {
2853
+ return muted.value;
2854
+ }
2855
+ if (muted?.type === "range") {
2856
+ return muted?.values.some(
2857
+ (value) => frame >= value.start * fps && frame <= value.end * fps
2858
+ );
2859
+ }
2860
+ return false;
2861
+ }, [muted, frame, fps]);
2862
+ const source = (0, import_react19.useMemo)(() => {
2863
+ if (data.src.startsWith("http")) {
2864
+ return data.src;
2865
+ }
2866
+ return (0, import_remotion15.staticFile)(data.src);
2867
+ }, [data.src]);
2868
+ return (
2869
+ // @ts-ignore
2870
+ /* @__PURE__ */ import_react19.default.createElement(
2871
+ import_remotion15.Audio,
2872
+ {
2873
+ src: source,
2874
+ trimBefore: data.startFrom ? data.startFrom * fps : void 0,
2875
+ trimAfter: data.endAt ? data.endAt * fps : void 0,
2876
+ volume: data.volume,
2877
+ playbackRate: data.playbackRate,
2878
+ muted: isMuted
2879
+ }
2880
+ )
2881
+ );
2882
+ };
2883
+ var config13 = {
2884
+ displayName: "AudioAtom",
2885
+ type: "atom",
2886
+ isInnerSequence: false
2887
+ };
2888
+
2889
+ // src/components/atoms/LottieAtom.tsx
2890
+ var import_react20 = __toESM(require("react"));
2891
+ var import_remotion16 = require("remotion");
2892
+ var import_lottie = require("@remotion/lottie");
2893
+ var import_zod4 = require("zod");
2894
+ var LottieAtomDataProps = import_zod4.z.object({
2895
+ src: import_zod4.z.string(),
2896
+ // Lottie JSON source URL or local path
2897
+ style: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.any()).optional(),
2898
+ // CSS styles object
2899
+ className: import_zod4.z.string().optional(),
2900
+ // CSS class names
2901
+ loop: import_zod4.z.boolean().optional(),
2902
+ // Whether to loop the animation (handled by Remotion timeline)
2903
+ playbackRate: import_zod4.z.number().optional(),
2904
+ // Playback speed multiplier (default: 1)
2905
+ direction: import_zod4.z.enum(["forward", "reverse"]).optional()
2906
+ // Animation direction
2907
+ });
2908
+ var useLottieData = (src) => {
2909
+ const [animationData, setAnimationData] = (0, import_react20.useState)(null);
2910
+ const [isLoading, setIsLoading] = (0, import_react20.useState)(true);
2911
+ const [hasError, setHasError] = (0, import_react20.useState)(false);
2912
+ const [handle] = (0, import_react20.useState)(() => (0, import_remotion16.delayRender)("Loading Lottie animation"));
2913
+ (0, import_react20.useEffect)(() => {
2914
+ if (!src) {
2915
+ console.error("LottieAtom: No source provided");
2916
+ setHasError(true);
2917
+ setIsLoading(false);
2918
+ (0, import_remotion16.continueRender)(handle);
2919
+ return;
2920
+ }
2921
+ setIsLoading(true);
2922
+ setHasError(false);
2923
+ const sourceUrl = src.startsWith("http") ? src : (0, import_remotion16.staticFile)(src);
2924
+ fetch(sourceUrl, {
2925
+ mode: "cors",
2926
+ credentials: "omit"
2927
+ }).then((response) => {
2928
+ if (!response.ok) {
2929
+ throw new Error(`HTTP ${response.status}: ${response.statusText} for ${sourceUrl}`);
2930
+ }
2931
+ return response.json();
2932
+ }).then((json) => {
2933
+ if (!json || typeof json !== "object") {
2934
+ throw new Error("Invalid Lottie JSON data");
2935
+ }
2936
+ setAnimationData(json);
2937
+ setIsLoading(false);
2938
+ (0, import_remotion16.continueRender)(handle);
2939
+ }).catch((error) => {
2940
+ console.error(`Failed to load Lottie animation from ${sourceUrl}:`, error.message || error);
2941
+ setHasError(true);
2942
+ setIsLoading(false);
2943
+ (0, import_remotion16.continueRender)(handle);
2944
+ });
2945
+ return () => {
2946
+ };
2947
+ }, [src, handle]);
2948
+ return { animationData, isLoading, hasError };
2949
+ };
2950
+ var Atom6 = ({ data, id }) => {
2951
+ const { fps } = (0, import_remotion16.useVideoConfig)();
2952
+ const frame = (0, import_remotion16.useCurrentFrame)();
2953
+ const overrideStyles = useAnimatedStyles(id);
2954
+ const { animationData, isLoading, hasError } = useLottieData(data.src);
2955
+ const effectiveFrame = (0, import_react20.useMemo)(() => {
2956
+ const playbackRate = data.playbackRate || 1;
2957
+ const direction = data.direction || "forward";
2958
+ if (direction === "reverse") {
2959
+ return frame * playbackRate * -1;
2960
+ }
2961
+ return frame * playbackRate;
2962
+ }, [frame, data.playbackRate, data.direction]);
2963
+ const enhancedStyle = (0, import_react20.useMemo)(() => ({
2964
+ ...data.style,
2965
+ ...overrideStyles
2966
+ }), [data.style, overrideStyles]);
2967
+ if (isLoading) {
2968
+ return /* @__PURE__ */ import_react20.default.createElement(
2969
+ "div",
2970
+ {
2971
+ className: data.className,
2972
+ style: {
2973
+ ...enhancedStyle,
2974
+ display: "flex",
2975
+ alignItems: "center",
2976
+ justifyContent: "center",
2977
+ opacity: 0.5
2978
+ }
2979
+ }
2980
+ );
2981
+ }
2982
+ if (hasError || !animationData) {
2983
+ console.warn(`LottieAtom: Failed to render animation from ${data.src}`);
2984
+ return /* @__PURE__ */ import_react20.default.createElement(
2985
+ "div",
2986
+ {
2987
+ className: data.className,
2988
+ style: {
2989
+ ...enhancedStyle,
2990
+ display: "flex",
2991
+ alignItems: "center",
2992
+ justifyContent: "center",
2993
+ backgroundColor: "rgba(255, 0, 0, 0.1)",
2994
+ border: "2px dashed rgba(255, 0, 0, 0.3)",
2995
+ color: "red",
2996
+ fontSize: 12,
2997
+ textAlign: "center",
2998
+ padding: 10
2999
+ }
3000
+ },
3001
+ "\u26A0\uFE0F Lottie Error"
3002
+ );
3003
+ }
3004
+ return /* @__PURE__ */ import_react20.default.createElement(
3005
+ import_lottie.Lottie,
3006
+ {
3007
+ animationData,
3008
+ style: enhancedStyle,
3009
+ className: data.className
3010
+ }
3011
+ );
3012
+ };
3013
+ var config14 = {
3014
+ displayName: "LottieAtom",
3015
+ type: "atom",
3016
+ isInnerSequence: false
3017
+ };
3018
+
3019
+ // src/components/atoms/index.ts
3020
+ registerComponent(
3021
+ config9.displayName,
3022
+ Atom,
3023
+ "atom",
3024
+ config9
3025
+ );
3026
+ registerComponent(
3027
+ config10.displayName,
3028
+ Atom2,
3029
+ "atom",
3030
+ config10
3031
+ );
3032
+ registerComponent(config11.displayName, Atom3, "atom", config11);
3033
+ registerComponent(
3034
+ config12.displayName,
3035
+ Atom4,
3036
+ "atom",
3037
+ config12
3038
+ );
3039
+ registerComponent(
3040
+ config13.displayName,
3041
+ Atom5,
3042
+ "atom",
3043
+ config13
3044
+ );
3045
+ registerComponent(
3046
+ config14.displayName,
3047
+ Atom6,
3048
+ "atom",
3049
+ config14
3050
+ );
3051
+
3052
+ // src/hooks/useComponentRegistry.ts
3053
+ var import_react21 = require("react");
3054
+ var useComponentRegistry = () => {
3055
+ return (0, import_react21.useMemo)(() => {
3056
+ return {
3057
+ registerComponent: componentRegistry.registerComponent.bind(componentRegistry),
3058
+ registerPackage: componentRegistry.registerPackage.bind(componentRegistry),
3059
+ getComponent: componentRegistry.getComponent.bind(componentRegistry),
3060
+ getAllComponents: componentRegistry.getAllComponents.bind(componentRegistry)
3061
+ };
3062
+ }, []);
3063
+ };
3064
+
3065
+ // src/hooks/useBoundaryCalculation.ts
3066
+ var import_react22 = require("react");
3067
+ var useBoundaryCalculation = ({
3068
+ parentBoundaries,
3069
+ constraints,
3070
+ layout
3071
+ }) => {
3072
+ return (0, import_react22.useMemo)(() => {
3073
+ const { x, y, width, height } = parentBoundaries;
3074
+ const calculatedX = typeof constraints.x === "number" ? constraints.x : x;
3075
+ const calculatedY = typeof constraints.y === "number" ? constraints.y : y;
3076
+ const calculatedWidth = typeof constraints.width === "number" ? constraints.width : width;
3077
+ const calculatedHeight = typeof constraints.height === "number" ? constraints.height : height;
3078
+ return {
3079
+ x: calculatedX,
3080
+ y: calculatedY,
3081
+ width: calculatedWidth,
3082
+ height: calculatedHeight,
3083
+ zIndex: constraints.zIndex || 0
3084
+ };
3085
+ }, [parentBoundaries, constraints, layout]);
3086
+ };
3087
+
3088
+ // src/hooks/buildTransitionHook.ts
3089
+ var import_react24 = require("react");
3090
+
3091
+ // src/core/types/transition.types.ts
3092
+ var import_react23 = require("react");
3093
+ var LayoutContext = (0, import_react23.createContext)(null);
3094
+
3095
+ // src/hooks/buildTransitionHook.ts
3096
+ function buildLayoutHook(schema, defaultValue) {
3097
+ return () => {
3098
+ const context = (0, import_react24.useContext)(LayoutContext);
3099
+ if (!context) {
3100
+ return defaultValue;
3101
+ }
3102
+ try {
3103
+ const validatedData = schema.parse(context);
3104
+ return validatedData;
3105
+ } catch (error) {
3106
+ console.warn("Transition data validation failed, using defaults:", error);
3107
+ return defaultValue;
3108
+ }
3109
+ };
3110
+ }
3111
+
3112
+ // src/utils/contextUtils.ts
3113
+ var createRootContext = (width, height, duration, fps) => {
3114
+ return {
3115
+ boundaries: {
3116
+ left: 0,
3117
+ top: 0,
3118
+ width,
3119
+ height,
3120
+ zIndex: 0
3121
+ },
3122
+ timing: {
3123
+ startInFrames: 0,
3124
+ durationInFrames: duration
3125
+ },
3126
+ hierarchy: {
3127
+ depth: 0,
3128
+ parentIds: []
3129
+ }
3130
+ };
3131
+ };
3132
+ var mergeContexts = (parent, child) => {
3133
+ return {
3134
+ boundaries: {
3135
+ ...parent.boundaries,
3136
+ ...child.boundaries
3137
+ },
3138
+ timing: { ...parent.timing, ...child.timing },
3139
+ hierarchy: {
3140
+ depth: (parent.hierarchy?.depth || 0) + 1,
3141
+ parentIds: [...parent.hierarchy?.parentIds || [], "root"]
3142
+ }
3143
+ };
3144
+ };
3145
+
3146
+ // src/utils/boundaryUtils.ts
3147
+ var calculateGridPosition = (index, columns, cellWidth, cellHeight, spacing) => {
3148
+ const row = Math.floor(index / columns);
3149
+ const col = index % columns;
3150
+ return {
3151
+ x: col * (cellWidth + spacing),
3152
+ y: row * (cellHeight + spacing),
3153
+ width: cellWidth,
3154
+ height: cellHeight
3155
+ };
3156
+ };
3157
+ var calculateCircularPosition = (index, total, radius, centerX, centerY) => {
3158
+ const angle = index / total * 2 * Math.PI;
3159
+ return {
3160
+ x: centerX + radius * Math.cos(angle),
3161
+ y: centerY + radius * Math.sin(angle)
3162
+ };
3163
+ };
3164
+
3165
+ // src/utils/imageProxy.ts
3166
+ var createImageProxyUrl = (imageUrl, proxyEndpoint = "/api/proxy/image") => {
3167
+ return `${proxyEndpoint}?url=${encodeURIComponent(imageUrl)}`;
3168
+ };
3169
+ var createImageDataWithProxy = (src, proxyEndpoint) => {
3170
+ return {
3171
+ src,
3172
+ proxySrc: proxyEndpoint || "/api/proxy/image",
3173
+ style: {},
3174
+ className: ""
3175
+ };
3176
+ };
3177
+ var needsProxying = (url) => {
3178
+ return url.startsWith("http://") || url.startsWith("https://");
3179
+ };
3180
+
3181
+ // src/templates/rings/NextjsLogo.tsx
3182
+ var import_paths = require("@remotion/paths");
3183
+ var import_react26 = __toESM(require("react"));
3184
+ var import_remotion18 = require("remotion");
3185
+
3186
+ // src/templates/rings/RippleOutLayout.tsx
3187
+ var import_react25 = __toESM(require("react"));
3188
+ var import_remotion17 = require("remotion");
3189
+ var import_zod5 = require("zod");
3190
+ var RippleOutTransitionSchema = import_zod5.z.object({
3191
+ progress: import_zod5.z.number().min(0).max(1),
3192
+ logoOut: import_zod5.z.number().min(0).max(1)
3193
+ });
3194
+ var defaultRippleOutData = {
3195
+ progress: 0,
3196
+ logoOut: 0
3197
+ };
3198
+ var useRippleOutLayout = buildLayoutHook(
3199
+ RippleOutTransitionSchema,
3200
+ defaultRippleOutData
3201
+ );
3202
+ var container = {
3203
+ backgroundColor: "white"
3204
+ };
3205
+ var RippleOutLayout = ({ data, context, children }) => {
3206
+ const {
3207
+ transitionStart,
3208
+ transitionDuration
3209
+ } = data || { transitionStart: 2, transitionDuration: 1 };
3210
+ const frame = (0, import_remotion17.useCurrentFrame)();
3211
+ const { fps } = (0, import_remotion17.useVideoConfig)();
3212
+ const { hierarchy } = useRenderContext();
3213
+ import_react25.default.useEffect(() => {
3214
+ loadGoogleFont("Inter", {
3215
+ subsets: ["latin"],
3216
+ weights: ["400", "700"]
3217
+ }).catch(console.warn);
3218
+ }, []);
3219
+ const transitionStartFrame = transitionStart * fps;
3220
+ const transitionDurationFrames = transitionDuration * fps;
3221
+ const logoOut = (0, import_remotion17.spring)({
3222
+ fps,
3223
+ frame,
3224
+ config: {
3225
+ damping: 200
3226
+ },
3227
+ durationInFrames: transitionDurationFrames,
3228
+ delay: transitionStartFrame
3229
+ });
3230
+ const transitionData = {
3231
+ progress: logoOut,
3232
+ logoOut
3233
+ };
3234
+ const childrenArray = import_react25.default.Children.toArray(children).filter(
3235
+ (child) => import_react25.default.isValidElement(child)
3236
+ );
3237
+ const [from, to] = childrenArray;
3238
+ return /* @__PURE__ */ import_react25.default.createElement(LayoutContext.Provider, { value: transitionData }, /* @__PURE__ */ import_react25.default.createElement(import_remotion17.AbsoluteFill, { style: {
3239
+ ...container,
3240
+ ...context?.boundaries
3241
+ } }, /* @__PURE__ */ import_react25.default.createElement(import_remotion17.Sequence, { name: from.props.componentId + " - " + from.props.id, from: 0, durationInFrames: transitionStartFrame + transitionDurationFrames }, from), /* @__PURE__ */ import_react25.default.createElement(import_remotion17.Sequence, { name: to.props.componentId + " - " + to.props.id, from: transitionStartFrame + transitionDurationFrames / 2 }, to)));
3242
+ };
3243
+ var rippleOutLayoutConfig = {
3244
+ displayName: "RippleOutLayout",
3245
+ type: "layout",
3246
+ isInnerSequence: true
3247
+ };
3248
+
3249
+ // src/templates/rings/NextjsLogo.tsx
3250
+ var mask = {
3251
+ maskType: "alpha"
3252
+ };
3253
+ var nStroke = "M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z";
3254
+ var NextjsLogo = () => {
3255
+ const { logoOut } = useRippleOutLayout();
3256
+ const outProgress = logoOut;
3257
+ const { fps } = (0, import_remotion18.useVideoConfig)();
3258
+ const frame = (0, import_remotion18.useCurrentFrame)();
3259
+ const evolve1 = (0, import_remotion18.spring)({
3260
+ fps,
3261
+ frame,
3262
+ config: {
3263
+ damping: 200
3264
+ }
3265
+ });
3266
+ const evolve2 = (0, import_remotion18.spring)({
3267
+ fps,
3268
+ frame: frame - 15,
3269
+ config: {
3270
+ damping: 200
3271
+ }
3272
+ });
3273
+ const evolve3 = (0, import_remotion18.spring)({
3274
+ fps,
3275
+ frame: frame - 30,
3276
+ config: {
3277
+ damping: 200,
3278
+ mass: 3
3279
+ },
3280
+ durationInFrames: 30
3281
+ });
3282
+ const style = (0, import_react26.useMemo)(() => {
3283
+ return {
3284
+ height: 140,
3285
+ borderRadius: 70,
3286
+ scale: String(1 - outProgress)
3287
+ };
3288
+ }, [outProgress]);
3289
+ const firstPath = `M 60.0568 54 v 71.97`;
3290
+ const secondPath = `M 63.47956 56.17496 L 144.7535 161.1825`;
3291
+ const thirdPath = `M 121 54 L 121 126`;
3292
+ const evolution1 = (0, import_paths.evolvePath)(evolve1, firstPath);
3293
+ const evolution2 = (0, import_paths.evolvePath)(evolve2, secondPath);
3294
+ const evolution3 = (0, import_paths.evolvePath)(
3295
+ (0, import_remotion18.interpolate)(evolve3, [0, 1], [0, 0.7]),
3296
+ thirdPath
3297
+ );
3298
+ return /* @__PURE__ */ import_react26.default.createElement("svg", { style, fill: "none", viewBox: "0 0 180 180" }, /* @__PURE__ */ import_react26.default.createElement("mask", { height: "180", id: "mask", style: mask, width: "180", x: "0", y: "0" }, /* @__PURE__ */ import_react26.default.createElement("circle", { cx: "90", cy: "90", fill: "black", r: "90" })), /* @__PURE__ */ import_react26.default.createElement("mask", { id: "n-mask", style: mask }, /* @__PURE__ */ import_react26.default.createElement("path", { d: nStroke, fill: "black" })), /* @__PURE__ */ import_react26.default.createElement("g", { mask: "url(#mask)" }, /* @__PURE__ */ import_react26.default.createElement("circle", { cx: "90", cy: "90", fill: "black", r: "90" }), /* @__PURE__ */ import_react26.default.createElement("g", { stroke: "url(#gradient0)", mask: "url(#n-mask)" }, /* @__PURE__ */ import_react26.default.createElement(
3299
+ "path",
3300
+ {
3301
+ strokeWidth: "12.1136",
3302
+ d: firstPath,
3303
+ strokeDasharray: evolution1.strokeDasharray,
3304
+ strokeDashoffset: evolution1.strokeDashoffset
3305
+ }
3306
+ ), /* @__PURE__ */ import_react26.default.createElement(
3307
+ "path",
3308
+ {
3309
+ strokeWidth: 12.1136,
3310
+ d: secondPath,
3311
+ strokeDasharray: evolution2.strokeDasharray,
3312
+ strokeDashoffset: evolution2.strokeDashoffset
3313
+ }
3314
+ )), /* @__PURE__ */ import_react26.default.createElement(
3315
+ "path",
3316
+ {
3317
+ stroke: "url(#gradient1)",
3318
+ d: thirdPath,
3319
+ strokeDasharray: evolution3.strokeDasharray,
3320
+ strokeDashoffset: evolution3.strokeDashoffset,
3321
+ strokeWidth: "12"
3322
+ }
3323
+ )), /* @__PURE__ */ import_react26.default.createElement("defs", null, /* @__PURE__ */ import_react26.default.createElement(
3324
+ "linearGradient",
3325
+ {
3326
+ gradientUnits: "userSpaceOnUse",
3327
+ id: "gradient0",
3328
+ x1: "109",
3329
+ x2: "144.5",
3330
+ y1: "116.5",
3331
+ y2: "160.5"
3332
+ },
3333
+ /* @__PURE__ */ import_react26.default.createElement("stop", { stopColor: "white" }),
3334
+ /* @__PURE__ */ import_react26.default.createElement("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })
3335
+ ), /* @__PURE__ */ import_react26.default.createElement(
3336
+ "linearGradient",
3337
+ {
3338
+ gradientUnits: "userSpaceOnUse",
3339
+ id: "gradient1",
3340
+ x1: "121",
3341
+ x2: "120.799",
3342
+ y1: "54",
3343
+ y2: "106.875"
3344
+ },
3345
+ /* @__PURE__ */ import_react26.default.createElement("stop", { stopColor: "white" }),
3346
+ /* @__PURE__ */ import_react26.default.createElement("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })
3347
+ )));
3348
+ };
3349
+ var nextjsLogoConfig = {
3350
+ displayName: "NextjsLogo",
3351
+ type: "atom",
3352
+ isInnerSequence: false
3353
+ };
3354
+
3355
+ // src/templates/rings/Rings.tsx
3356
+ var import_react27 = __toESM(require("react"));
3357
+ var import_remotion19 = require("remotion");
3358
+ var RadialGradient = ({ radius, color }) => {
3359
+ const height = radius * 2;
3360
+ const width = radius * 2;
3361
+ return (
3362
+ // @ts-ignore
3363
+ /* @__PURE__ */ import_react27.default.createElement(
3364
+ import_remotion19.AbsoluteFill,
3365
+ {
3366
+ style: {
3367
+ justifyContent: "center",
3368
+ alignItems: "center"
3369
+ }
3370
+ },
3371
+ /* @__PURE__ */ import_react27.default.createElement(
3372
+ "div",
3373
+ {
3374
+ style: {
3375
+ height,
3376
+ width,
3377
+ borderRadius: "50%",
3378
+ backgroundColor: color,
3379
+ position: "absolute",
3380
+ boxShadow: "0 0 100px rgba(0, 0, 0, 0.05)"
3381
+ }
3382
+ }
3383
+ )
3384
+ )
3385
+ );
3386
+ };
3387
+ var Rings = ({ context, data }) => {
3388
+ const { logoOut } = useRippleOutLayout();
3389
+ const outProgress = logoOut;
3390
+ const scale = 1 / (1 - outProgress);
3391
+ const { height } = (0, import_remotion19.useVideoConfig)();
3392
+ return (
3393
+ // @ts-ignore
3394
+ /* @__PURE__ */ import_react27.default.createElement(
3395
+ import_remotion19.AbsoluteFill,
3396
+ {
3397
+ style: {
3398
+ transform: `scale(${scale})`,
3399
+ ...context?.boundaries
3400
+ }
3401
+ },
3402
+ new Array(5).fill(true).map((_, i) => {
3403
+ return /* @__PURE__ */ import_react27.default.createElement(
3404
+ RadialGradient,
3405
+ {
3406
+ key: i,
3407
+ radius: height * 0.3 * i,
3408
+ color: (0, import_remotion19.interpolateColors)(i, [0, 4], ["#fff", "#fff"])
3409
+ }
3410
+ );
3411
+ }).reverse()
3412
+ )
3413
+ );
3414
+ };
3415
+ var ringsConfig = {
3416
+ displayName: "Rings",
3417
+ type: "atom",
3418
+ isInnerSequence: false
3419
+ };
3420
+
3421
+ // src/templates/rings/TextFade.tsx
3422
+ var import_react28 = __toESM(require("react"));
3423
+ var import_remotion20 = require("remotion");
3424
+ var TextFade = (props) => {
3425
+ const { children, context, data } = props;
3426
+ const { animation } = data || {
3427
+ animation: {
3428
+ duration: 1
3429
+ }
3430
+ };
3431
+ const { fps } = (0, import_remotion20.useVideoConfig)();
3432
+ const frame = (0, import_remotion20.useCurrentFrame)();
3433
+ const progress = (0, import_remotion20.spring)({
3434
+ fps,
3435
+ frame,
3436
+ config: {
3437
+ damping: 200
3438
+ },
3439
+ durationInFrames: animation.duration * fps
3440
+ });
3441
+ const rightStop = (0, import_remotion20.interpolate)(progress, [0, 1], [200, 0]);
3442
+ const leftStop = Math.max(0, rightStop - 60);
3443
+ const maskImage = `linear-gradient(-45deg, transparent ${leftStop}%, black ${rightStop}%)`;
3444
+ const container2 = (0, import_react28.useMemo)(() => {
3445
+ return {
3446
+ width: "100%",
3447
+ height: "100%",
3448
+ justifyContent: "center",
3449
+ alignItems: "center"
3450
+ };
3451
+ }, []);
3452
+ const content = (0, import_react28.useMemo)(() => {
3453
+ return {
3454
+ ...context?.boundaries,
3455
+ maskImage,
3456
+ WebkitMaskImage: maskImage,
3457
+ justifyContent: "center",
3458
+ alignItems: "center",
3459
+ display: "flex"
3460
+ };
3461
+ }, [maskImage]);
3462
+ return (
3463
+ // @ts-ignore
3464
+ /* @__PURE__ */ import_react28.default.createElement(import_remotion20.AbsoluteFill, { style: container2 }, /* @__PURE__ */ import_react28.default.createElement("div", { style: content }, children))
3465
+ );
3466
+ };
3467
+ var textFadeConfig = {
3468
+ displayName: "TextFade",
3469
+ type: "layout",
3470
+ isInnerSequence: false
3471
+ };
3472
+
3473
+ // src/templates/rings/index.ts
3474
+ registerComponent(
3475
+ nextjsLogoConfig.displayName,
3476
+ NextjsLogo,
3477
+ "atom",
3478
+ nextjsLogoConfig
3479
+ );
3480
+ registerComponent(
3481
+ textFadeConfig.displayName,
3482
+ TextFade,
3483
+ "layout",
3484
+ textFadeConfig
3485
+ );
3486
+ registerComponent(ringsConfig.displayName, Rings, "atom", ringsConfig);
3487
+ registerComponent(
3488
+ rippleOutLayoutConfig.displayName,
3489
+ RippleOutLayout,
3490
+ "layout",
3491
+ rippleOutLayoutConfig
3492
+ );
3493
+
3494
+ // src/templates/waveform/components/WaveformCircle.tsx
3495
+ var import_react31 = __toESM(require("react"));
3496
+
3497
+ // src/templates/waveform/Waveform.tsx
3498
+ var import_react30 = __toESM(require("react"));
3499
+ var import_remotion22 = require("remotion");
3500
+
3501
+ // src/templates/waveform/hooks/useWaveformData.ts
3502
+ var import_react29 = require("react");
3503
+ var import_media_utils = require("@remotion/media-utils");
3504
+ var import_remotion21 = require("remotion");
3505
+ var isValidPowerOfTwo = (num) => {
3506
+ return num > 0 && (num & num - 1) === 0;
3507
+ };
3508
+ var getClosestPowerOfTwo = (num) => {
3509
+ if (num <= 0) return 32;
3510
+ let power = 1;
3511
+ while (power < num) {
3512
+ power *= 2;
3513
+ }
3514
+ const lower = power / 2;
3515
+ const upper = power;
3516
+ return Math.abs(num - lower) < Math.abs(num - upper) ? lower : upper;
3517
+ };
3518
+ var useWaveformData = (config15) => {
3519
+ const {
3520
+ audioSrc,
3521
+ numberOfSamples,
3522
+ windowInSeconds,
3523
+ dataOffsetInSeconds = 0,
3524
+ normalize = false,
3525
+ frame,
3526
+ fps,
3527
+ posterize,
3528
+ includeFrequencyData = false,
3529
+ minDb = -100,
3530
+ maxDb = -30
3531
+ } = config15;
3532
+ const { root } = useComposition();
3533
+ const validatedNumberOfSamples = (0, import_react29.useMemo)(() => {
3534
+ if (!isValidPowerOfTwo(numberOfSamples)) {
3535
+ console.warn(
3536
+ `numberOfSamples must be a power of 2. Adjusting ${numberOfSamples} to ${getClosestPowerOfTwo(numberOfSamples)}`
3537
+ );
3538
+ return getClosestPowerOfTwo(numberOfSamples);
3539
+ }
3540
+ return numberOfSamples;
3541
+ }, [numberOfSamples]);
3542
+ const { source, audioStartsFrom } = (0, import_react29.useMemo)(() => {
3543
+ if (audioSrc.startsWith("http")) {
3544
+ return { source: audioSrc, audioStartsFrom: void 0 };
3545
+ }
3546
+ if (audioSrc.startsWith("ref:")) {
3547
+ const matchingComponent = findMatchingComponents(root, [
3548
+ audioSrc.replace("ref:", "")
3549
+ ]);
3550
+ if (matchingComponent.length > 0) {
3551
+ const firstMatchingComponent = matchingComponent[0];
3552
+ if (firstMatchingComponent.componentId === "AudioAtom") {
3553
+ return {
3554
+ source: firstMatchingComponent.data.src,
3555
+ audioStartsFrom: firstMatchingComponent.data?.startFrom ?? void 0
3556
+ };
3557
+ }
3558
+ if (firstMatchingComponent.type === "layout" || firstMatchingComponent.type === "scene") {
3559
+ const audioComponents = findMatchingComponentsByQuery(
3560
+ firstMatchingComponent.childrenData,
3561
+ { componentId: "AudioAtom" }
3562
+ );
3563
+ if (audioComponents.length > 0) {
3564
+ return {
3565
+ source: audioComponents[0].data.src,
3566
+ audioStartsFrom: audioComponents[0].data?.startFrom ?? void 0
3567
+ };
3568
+ }
3569
+ }
3570
+ }
3571
+ }
3572
+ return { source: (0, import_remotion21.staticFile)(audioSrc), audioStartsFrom: void 0 };
3573
+ }, [audioSrc]);
3574
+ const audioData = (0, import_media_utils.useAudioData)(source);
3575
+ const adjustedFrame = (0, import_react29.useMemo)(() => {
3576
+ if (posterize && posterize > 1) {
3577
+ return Math.round(frame / posterize) * posterize;
3578
+ }
3579
+ let offset = 0;
3580
+ if (audioStartsFrom && audioStartsFrom != 0) {
3581
+ offset += Math.round(audioStartsFrom * fps);
3582
+ }
3583
+ if (dataOffsetInSeconds != 0) {
3584
+ offset += Math.round(dataOffsetInSeconds * fps);
3585
+ }
3586
+ return frame + offset;
3587
+ }, [frame, posterize, dataOffsetInSeconds, audioStartsFrom]);
3588
+ const waveformData = (0, import_react29.useMemo)(() => {
3589
+ if (!audioData) return null;
3590
+ try {
3591
+ const waveform = (0, import_media_utils.visualizeAudioWaveform)({
3592
+ fps,
3593
+ frame: adjustedFrame,
3594
+ audioData,
3595
+ numberOfSamples: validatedNumberOfSamples,
3596
+ windowInSeconds,
3597
+ dataOffsetInSeconds: 0,
3598
+ normalize
3599
+ });
3600
+ return waveform;
3601
+ } catch (error2) {
3602
+ console.error("Error generating waveform:", error2);
3603
+ return null;
3604
+ }
3605
+ }, [
3606
+ audioData,
3607
+ adjustedFrame,
3608
+ fps,
3609
+ validatedNumberOfSamples,
3610
+ windowInSeconds,
3611
+ dataOffsetInSeconds,
3612
+ normalize
3613
+ ]);
3614
+ const {
3615
+ frequencyData,
3616
+ amplitudes,
3617
+ bass,
3618
+ mid,
3619
+ treble,
3620
+ bassValues,
3621
+ midValues,
3622
+ trebleValues
3623
+ } = (0, import_react29.useMemo)(() => {
3624
+ if (!audioData || !includeFrequencyData) {
3625
+ return {
3626
+ frequencyData: null,
3627
+ amplitudes: null,
3628
+ bass: null,
3629
+ mid: null,
3630
+ treble: null,
3631
+ bassValues: null,
3632
+ midValues: null,
3633
+ trebleValues: null
3634
+ };
3635
+ }
3636
+ try {
3637
+ const frequencyData2 = (0, import_media_utils.visualizeAudio)({
3638
+ fps,
3639
+ frame: adjustedFrame,
3640
+ audioData,
3641
+ numberOfSamples: validatedNumberOfSamples
3642
+ });
3643
+ const { sampleRate } = audioData;
3644
+ const bassValues2 = [];
3645
+ const midValues2 = [];
3646
+ const trebleValues2 = [];
3647
+ for (let i = 0; i < frequencyData2.length; i++) {
3648
+ const freq = i * sampleRate / (2 * frequencyData2.length);
3649
+ const value = frequencyData2[i];
3650
+ if (freq >= 0 && freq < 250) {
3651
+ bassValues2.push(value * 2.5);
3652
+ } else if (freq >= 250 && freq < 4e3) {
3653
+ midValues2.push(value * 3);
3654
+ midValues2.push(value * 4.5);
3655
+ midValues2.push(value * 5);
3656
+ } else if (freq >= 4e3 && freq < sampleRate / 2) {
3657
+ trebleValues2.push(value * 30);
3658
+ }
3659
+ }
3660
+ const getAverage = (arr) => arr.length > 0 ? arr.reduce((a, b) => a + b, 0) / arr.length : 0;
3661
+ const bass2 = getAverage(bassValues2);
3662
+ const mid2 = getAverage(midValues2);
3663
+ const treble2 = getAverage(trebleValues2);
3664
+ const amplitudes2 = frequencyData2.map((value) => {
3665
+ const db = 20 * Math.log10(value);
3666
+ const scaled = (db - minDb) / (maxDb - minDb);
3667
+ return Math.max(0, Math.min(1, scaled));
3668
+ });
3669
+ return {
3670
+ frequencyData: frequencyData2,
3671
+ amplitudes: amplitudes2,
3672
+ bass: bass2,
3673
+ mid: mid2,
3674
+ treble: treble2,
3675
+ bassValues: bassValues2,
3676
+ midValues: midValues2,
3677
+ trebleValues: trebleValues2.reverse()
3678
+ };
3679
+ } catch (error2) {
3680
+ console.error("Error generating frequency data:", error2);
3681
+ return {
3682
+ frequencyData: null,
3683
+ amplitudes: null,
3684
+ bass: null,
3685
+ mid: null,
3686
+ treble: null
3687
+ };
3688
+ }
3689
+ }, [
3690
+ audioData,
3691
+ includeFrequencyData,
3692
+ adjustedFrame,
3693
+ fps,
3694
+ validatedNumberOfSamples,
3695
+ windowInSeconds,
3696
+ dataOffsetInSeconds,
3697
+ minDb,
3698
+ maxDb
3699
+ ]);
3700
+ const isLoading = !audioData;
3701
+ const error = audioData === null && !isLoading ? "Failed to load audio data" : null;
3702
+ return {
3703
+ waveformData,
3704
+ frequencyData,
3705
+ amplitudes,
3706
+ audioData,
3707
+ isLoading,
3708
+ error,
3709
+ bass,
3710
+ bassValues,
3711
+ mid,
3712
+ midValues,
3713
+ treble,
3714
+ trebleValues
3715
+ };
3716
+ };
3717
+
3718
+ // src/templates/waveform/Waveform.tsx
3719
+ var WaveformContext = (0, import_react30.createContext)(null);
3720
+ var useWaveformContext = () => {
3721
+ const context = (0, import_react30.useContext)(WaveformContext);
3722
+ if (!context) {
3723
+ throw new Error("useWaveformContext must be used within a Waveform component");
3724
+ }
3725
+ return context;
3726
+ };
3727
+ var Waveform = ({
3728
+ config: config15,
3729
+ children,
3730
+ className = "",
3731
+ style = {}
3732
+ }) => {
3733
+ const frame = (0, import_remotion22.useCurrentFrame)();
3734
+ const { width: videoWidth, height: videoHeight, fps } = (0, import_remotion22.useVideoConfig)();
3735
+ const { waveformData, frequencyData, amplitudes, audioData, bass, mid, treble, bassValues, midValues, trebleValues } = useWaveformData({
3736
+ audioSrc: config15.audioSrc,
3737
+ numberOfSamples: config15.numberOfSamples || 128,
3738
+ windowInSeconds: config15.windowInSeconds || 1 / fps,
3739
+ dataOffsetInSeconds: config15.dataOffsetInSeconds || 0,
3740
+ normalize: config15.normalize || false,
3741
+ frame,
3742
+ fps,
3743
+ posterize: config15.posterize,
3744
+ includeFrequencyData: config15.useFrequencyData || false
3745
+ });
3746
+ const width = config15.width || videoWidth;
3747
+ const height = config15.height || videoHeight;
3748
+ const contextValue = {
3749
+ waveformData,
3750
+ frequencyData,
3751
+ amplitudes,
3752
+ audioData,
3753
+ frame,
3754
+ fps,
3755
+ config: config15,
3756
+ width,
3757
+ height,
3758
+ bass,
3759
+ mid,
3760
+ treble,
3761
+ bassValues,
3762
+ midValues,
3763
+ trebleValues
3764
+ };
3765
+ return /* @__PURE__ */ import_react30.default.createElement(WaveformContext.Provider, { value: contextValue }, /* @__PURE__ */ import_react30.default.createElement(
3766
+ "div",
3767
+ {
3768
+ className: `relative ${className}`,
3769
+ style: {
3770
+ width,
3771
+ height,
3772
+ position: "relative",
3773
+ backgroundColor: config15.backgroundColor || "transparent",
3774
+ ...style
3775
+ }
3776
+ },
3777
+ children
3778
+ ));
3779
+ };
3780
+
3781
+ // src/templates/waveform/components/WaveformCircle.tsx
3782
+ var WaveformCircle = ({ data }) => {
3783
+ const {
3784
+ config: config15,
3785
+ className = "",
3786
+ style = {},
3787
+ strokeColor = "#FF6B6B",
3788
+ strokeWidth = 3,
3789
+ fill = "none",
3790
+ opacity = 1,
3791
+ radius = 80,
3792
+ centerX = 50,
3793
+ centerY = 50,
3794
+ startAngle = 0,
3795
+ endAngle = 360,
3796
+ amplitude = 1,
3797
+ rotationSpeed = 0,
3798
+ gradientStartColor,
3799
+ gradientEndColor
3800
+ } = data;
3801
+ return /* @__PURE__ */ import_react31.default.createElement(Waveform, { config: config15, className, style }, /* @__PURE__ */ import_react31.default.createElement(
3802
+ WaveformCircleContent,
3803
+ {
3804
+ strokeColor,
3805
+ strokeWidth,
3806
+ fill,
3807
+ opacity,
3808
+ radius,
3809
+ centerX,
3810
+ centerY,
3811
+ startAngle,
3812
+ endAngle,
3813
+ amplitude,
3814
+ rotationSpeed,
3815
+ gradientStartColor,
3816
+ gradientEndColor
3817
+ }
3818
+ ));
3819
+ };
3820
+ var WaveformCircleContent = ({
3821
+ strokeColor,
3822
+ strokeWidth,
3823
+ fill,
3824
+ opacity,
3825
+ radius,
3826
+ centerX,
3827
+ centerY,
3828
+ startAngle,
3829
+ endAngle,
3830
+ amplitude,
3831
+ rotationSpeed,
3832
+ gradientStartColor,
3833
+ gradientEndColor
3834
+ }) => {
3835
+ const { waveformData, width, height, frame } = useWaveformContext();
3836
+ const circleRadius = Math.min(width, height) * (radius || 80) / 100;
3837
+ const circleCenterX = width * (centerX || 50) / 100;
3838
+ const circleCenterY = height * (centerY || 50) / 100;
3839
+ const rotation = frame * (rotationSpeed || 0) % 360;
3840
+ const circularPath = (0, import_react31.useMemo)(() => {
3841
+ if (!waveformData) return "";
3842
+ const totalAngle = (endAngle || 360) - (startAngle || 0);
3843
+ const angleStep = totalAngle / waveformData.length;
3844
+ let path = "";
3845
+ waveformData.forEach((value, index) => {
3846
+ const angle = ((startAngle || 0) + index * angleStep + rotation) * (Math.PI / 180);
3847
+ const waveRadius = circleRadius + value * (amplitude || 1) * circleRadius * 0.3;
3848
+ const x = circleCenterX + waveRadius * Math.cos(angle);
3849
+ const y = circleCenterY + waveRadius * Math.sin(angle);
3850
+ if (index === 0) {
3851
+ path += `M ${x} ${y}`;
3852
+ } else {
3853
+ path += ` L ${x} ${y}`;
3854
+ }
3855
+ });
3856
+ if (Math.abs((endAngle || 360) - (startAngle || 0)) >= 360) {
3857
+ path += " Z";
3858
+ }
3859
+ return path;
3860
+ }, [waveformData, circleRadius, circleCenterX, circleCenterY, startAngle, endAngle, rotation, amplitude]);
3861
+ if (!waveformData) {
3862
+ return /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center justify-center w-full h-full text-gray-500" }, "Loading circular waveform...");
3863
+ }
3864
+ const gradientId = "circle-waveform-gradient";
3865
+ const hasGradient = gradientStartColor && gradientEndColor;
3866
+ return /* @__PURE__ */ import_react31.default.createElement(
3867
+ "svg",
3868
+ {
3869
+ width,
3870
+ height,
3871
+ className: "absolute inset-0",
3872
+ style: { pointerEvents: "none" }
3873
+ },
3874
+ hasGradient && /* @__PURE__ */ import_react31.default.createElement("defs", null, /* @__PURE__ */ import_react31.default.createElement("linearGradient", { id: gradientId, x1: "0%", y1: "0%", x2: "100%", y2: "0%" }, /* @__PURE__ */ import_react31.default.createElement("stop", { offset: "0%", stopColor: gradientStartColor }), /* @__PURE__ */ import_react31.default.createElement("stop", { offset: "100%", stopColor: gradientEndColor }))),
3875
+ /* @__PURE__ */ import_react31.default.createElement(
3876
+ "path",
3877
+ {
3878
+ d: circularPath,
3879
+ stroke: hasGradient ? `url(#${gradientId})` : strokeColor,
3880
+ strokeWidth,
3881
+ fill,
3882
+ opacity,
3883
+ strokeLinecap: "round",
3884
+ strokeLinejoin: "round"
3885
+ }
3886
+ )
3887
+ );
3888
+ };
3889
+
3890
+ // src/templates/waveform/components/WaveformHistogram.tsx
3891
+ var import_react32 = __toESM(require("react"));
3892
+ var WaveformHistogram = ({ data }) => {
3893
+ const {
3894
+ config: config15,
3895
+ className = "",
3896
+ style = {},
3897
+ barColor = "#FF6B6B",
3898
+ barWidth = 4,
3899
+ barSpacing = 2,
3900
+ barBorderRadius = 2,
3901
+ opacity = 1,
3902
+ horizontalSymmetry = true,
3903
+ verticalMirror = false,
3904
+ histogramStyle = "centered",
3905
+ amplitude = 1,
3906
+ multiplier = 1,
3907
+ gradientStartColor,
3908
+ gradientEndColor,
3909
+ gradientDirection = "vertical",
3910
+ gradientStyle = "normal",
3911
+ waveDirection = "right-to-left"
3912
+ } = data;
3913
+ return /* @__PURE__ */ import_react32.default.createElement(Waveform, { config: config15, className, style }, /* @__PURE__ */ import_react32.default.createElement(
3914
+ WaveformHistogramContent,
3915
+ {
3916
+ barColor,
3917
+ barWidth,
3918
+ barSpacing,
3919
+ barBorderRadius,
3920
+ opacity,
3921
+ horizontalSymmetry,
3922
+ verticalMirror,
3923
+ histogramStyle,
3924
+ amplitude,
3925
+ gradientStartColor,
3926
+ gradientEndColor,
3927
+ gradientDirection,
3928
+ multiplier,
3929
+ gradientStyle,
3930
+ waveDirection
3931
+ }
3932
+ ));
3933
+ };
3934
+ var WaveformHistogramContent = ({
3935
+ barColor,
3936
+ barWidth,
3937
+ barSpacing,
3938
+ barBorderRadius,
3939
+ opacity,
3940
+ horizontalSymmetry,
3941
+ verticalMirror,
3942
+ histogramStyle,
3943
+ amplitude,
3944
+ gradientStartColor,
3945
+ gradientEndColor,
3946
+ gradientDirection,
3947
+ multiplier,
3948
+ gradientStyle,
3949
+ waveDirection
3950
+ }) => {
3951
+ const { waveformData, frequencyData, amplitudes, width, height } = useWaveformContext();
3952
+ const dataToUse = amplitudes || waveformData;
3953
+ if (!dataToUse) {
3954
+ return /* @__PURE__ */ import_react32.default.createElement("div", { className: "flex items-center justify-center w-full h-full text-gray-500" }, "Loading histogram...");
3955
+ }
3956
+ let directedData = waveDirection === "left-to-right" ? dataToUse.slice(1).reverse() : dataToUse;
3957
+ const frequencies = horizontalSymmetry ? [...directedData, ...directedData.slice(1).reverse()] : Array(multiplier).fill(directedData).flat();
3958
+ const Bars = ({ growUpwards }) => {
3959
+ const styleGradientProp = gradientStartColor && gradientEndColor ? {
3960
+ background: `linear-gradient(${gradientDirection === "horizontal" ? gradientStyle === "mirrored" ? "to right" : growUpwards ? "to right" : "to left" : gradientStyle === "normal" ? growUpwards ? "to top" : "to bottom" : "to bottom"}, ${gradientStartColor}, ${gradientEndColor})`
3961
+ } : { backgroundColor: barColor };
3962
+ const containerStyle2 = {
3963
+ display: "flex",
3964
+ flexDirection: "row",
3965
+ alignItems: growUpwards ? "flex-end" : "flex-start",
3966
+ height: "100%",
3967
+ width: "100%",
3968
+ ...histogramStyle === "centered" && {
3969
+ justifyContent: "center",
3970
+ gap: `${barSpacing}px`
3971
+ },
3972
+ ...histogramStyle === "full-width" && {
3973
+ gap: `${barSpacing}px`,
3974
+ justifyContent: "space-between"
3975
+ },
3976
+ opacity: gradientStyle === "mirrored" && !growUpwards ? 0.25 : 1
3977
+ };
3978
+ return /* @__PURE__ */ import_react32.default.createElement("div", { style: containerStyle2 }, frequencies.map((value, index) => /* @__PURE__ */ import_react32.default.createElement(
3979
+ "div",
3980
+ {
3981
+ key: index,
3982
+ style: {
3983
+ ...histogramStyle === "full-width" ? { width: `${barWidth}px` } : { width: `${barWidth}px` },
3984
+ ...styleGradientProp,
3985
+ height: `${Math.min(
3986
+ height / 2,
3987
+ Math.abs(value) * (height / 2) * (amplitude || 1)
3988
+ )}px`,
3989
+ borderRadius: growUpwards ? `${barBorderRadius}px ${barBorderRadius}px 0 0` : `0 0 ${barBorderRadius}px ${barBorderRadius}px`,
3990
+ opacity
3991
+ }
3992
+ }
3993
+ )));
3994
+ };
3995
+ if (verticalMirror) {
3996
+ const topHalfStyle = {
3997
+ position: "absolute",
3998
+ bottom: `calc(100% - ${height / 2}px)`,
3999
+ height: `${height / 2}px`,
4000
+ width: "100%",
4001
+ left: 0
4002
+ };
4003
+ const bottomHalfStyle = {
4004
+ position: "absolute",
4005
+ top: `${height / 2}px`,
4006
+ height: `${height / 2}px`,
4007
+ width: "100%",
4008
+ left: 0
4009
+ };
4010
+ return /* @__PURE__ */ import_react32.default.createElement(import_react32.default.Fragment, null, /* @__PURE__ */ import_react32.default.createElement("div", { style: topHalfStyle }, /* @__PURE__ */ import_react32.default.createElement(Bars, { growUpwards: true })), /* @__PURE__ */ import_react32.default.createElement("div", { style: bottomHalfStyle }, /* @__PURE__ */ import_react32.default.createElement(Bars, { growUpwards: false })));
4011
+ }
4012
+ const containerStyle = {
4013
+ width: "100%",
4014
+ position: "absolute",
4015
+ top: `${height / 2 - height / 4}px`,
4016
+ height: `${height / 2}px`,
4017
+ left: 0
4018
+ };
4019
+ return /* @__PURE__ */ import_react32.default.createElement("div", { style: containerStyle }, /* @__PURE__ */ import_react32.default.createElement(Bars, { growUpwards: true }));
4020
+ };
4021
+
4022
+ // src/templates/waveform/components/WaveformHistogramRanged.tsx
4023
+ var import_react33 = __toESM(require("react"));
4024
+ var WaveformHistogramRanged = ({ data }) => {
4025
+ const {
4026
+ config: config15,
4027
+ className = "",
4028
+ style = {},
4029
+ barColor = "#FF6B6B",
4030
+ barWidth = 4,
4031
+ barSpacing = 2,
4032
+ barBorderRadius = 2,
4033
+ opacity = 1,
4034
+ verticalMirror = false,
4035
+ histogramStyle = "centered",
4036
+ amplitude = 1,
4037
+ showFrequencyRanges = true,
4038
+ rangeDividerColor = "#666",
4039
+ rangeLabels = false,
4040
+ bassBarColor = "#5DADE2",
4041
+ midBarColor = "#58D68D",
4042
+ trebleBarColor = "#F5B041",
4043
+ gradientStartColor,
4044
+ gradientEndColor,
4045
+ gradientDirection = "vertical",
4046
+ gradientStyle = "normal",
4047
+ horizontalSymmetry = false,
4048
+ waveDirection = "right-to-left"
4049
+ } = data;
4050
+ return /* @__PURE__ */ import_react33.default.createElement(Waveform, { config: config15, className, style }, /* @__PURE__ */ import_react33.default.createElement(
4051
+ WaveformHistogramRangedContent,
4052
+ {
4053
+ barColor,
4054
+ barWidth,
4055
+ barSpacing,
4056
+ barBorderRadius,
4057
+ opacity,
4058
+ verticalMirror,
4059
+ histogramStyle,
4060
+ amplitude,
4061
+ showFrequencyRanges,
4062
+ rangeDividerColor,
4063
+ rangeLabels,
4064
+ bassBarColor,
4065
+ midBarColor,
4066
+ trebleBarColor,
4067
+ gradientStartColor,
4068
+ gradientEndColor,
4069
+ gradientDirection,
4070
+ gradientStyle,
4071
+ horizontalSymmetry,
4072
+ waveDirection
4073
+ }
4074
+ ));
4075
+ };
4076
+ var WaveformHistogramRangedContent = ({
4077
+ barColor,
4078
+ barWidth,
4079
+ barSpacing,
4080
+ barBorderRadius,
4081
+ opacity,
4082
+ verticalMirror,
4083
+ histogramStyle,
4084
+ amplitude,
4085
+ showFrequencyRanges,
4086
+ rangeDividerColor,
4087
+ rangeLabels,
4088
+ bassBarColor,
4089
+ midBarColor,
4090
+ trebleBarColor,
4091
+ gradientStartColor,
4092
+ gradientEndColor,
4093
+ gradientDirection,
4094
+ gradientStyle,
4095
+ horizontalSymmetry,
4096
+ waveDirection
4097
+ }) => {
4098
+ const { amplitudes, bassValues, midValues, trebleValues, height } = useWaveformContext();
4099
+ if (!amplitudes || !bassValues || !midValues || !trebleValues) {
4100
+ return /* @__PURE__ */ import_react33.default.createElement("div", { className: "flex items-center justify-center w-full h-full text-gray-500" }, "Loading frequency data...");
4101
+ }
4102
+ const bassFrequencies = bassValues;
4103
+ const midFrequencies = midValues;
4104
+ const trebleFrequencies = trebleValues;
4105
+ const allFrequencies = waveDirection === "right-to-left" ? [bassFrequencies, midFrequencies, trebleFrequencies].flat() : [trebleFrequencies, midFrequencies, bassFrequencies].flat();
4106
+ const unifiedWaveform = horizontalSymmetry ? [...allFrequencies.slice(1).reverse(), ...allFrequencies] : allFrequencies;
4107
+ const Bars = ({ growUpwards }) => {
4108
+ const containerStyle2 = {
4109
+ display: "flex",
4110
+ flexDirection: "row",
4111
+ alignItems: growUpwards ? "flex-end" : "flex-start",
4112
+ height: "100%",
4113
+ width: "100%",
4114
+ ...histogramStyle === "centered" && {
4115
+ justifyContent: "center",
4116
+ gap: `${barSpacing}px`
4117
+ },
4118
+ ...histogramStyle === "full-width" && {
4119
+ gap: `${barSpacing}px`,
4120
+ justifyContent: "space-between"
4121
+ },
4122
+ opacity: gradientStyle === "mirrored" && !growUpwards ? 0.25 : 1
4123
+ };
4124
+ return /* @__PURE__ */ import_react33.default.createElement("div", { style: containerStyle2 }, unifiedWaveform.map((value, index) => {
4125
+ const rangeName = index === 0 ? "Bass" : index === 1 ? "Mid" : "Treble";
4126
+ const styleGradientProp = gradientStartColor && gradientEndColor ? {
4127
+ background: `linear-gradient(${gradientDirection === "horizontal" ? gradientStyle === "mirrored" ? "to right" : growUpwards ? "to right" : "to left" : gradientStyle === "normal" ? growUpwards ? "to top" : "to bottom" : "to bottom"}, ${gradientStartColor}, ${gradientEndColor})`
4128
+ } : { backgroundColor: barColor };
4129
+ return /* @__PURE__ */ import_react33.default.createElement(
4130
+ "div",
4131
+ {
4132
+ key: index,
4133
+ style: {
4134
+ width: `${barWidth || 4}px`,
4135
+ // Wider bars for the three ranges
4136
+ ...styleGradientProp,
4137
+ height: `${Math.min(
4138
+ height / 2,
4139
+ Math.abs(value) * (height / 2) * (amplitude || 1)
4140
+ )}px`,
4141
+ borderRadius: growUpwards ? `${barBorderRadius}px ${barBorderRadius}px 0 0` : `0 0 ${barBorderRadius}px ${barBorderRadius}px`,
4142
+ opacity,
4143
+ position: "relative"
4144
+ },
4145
+ title: `${rangeName}: ${(value * 100).toFixed(1)}%`
4146
+ },
4147
+ rangeLabels && /* @__PURE__ */ import_react33.default.createElement("div", { style: {
4148
+ position: "absolute",
4149
+ bottom: growUpwards ? "-20px" : "auto",
4150
+ top: growUpwards ? "auto" : "-20px",
4151
+ left: "50%",
4152
+ transform: "translateX(-50%)",
4153
+ fontSize: "10px",
4154
+ color: rangeDividerColor,
4155
+ whiteSpace: "nowrap"
4156
+ } }, rangeName)
4157
+ );
4158
+ }));
4159
+ };
4160
+ if (verticalMirror) {
4161
+ const topHalfStyle = {
4162
+ position: "absolute",
4163
+ bottom: `calc(100% - ${height / 2}px)`,
4164
+ height: `${height / 2}px`,
4165
+ width: "100%",
4166
+ left: 0
4167
+ };
4168
+ const bottomHalfStyle = {
4169
+ position: "absolute",
4170
+ top: `${height / 2}px`,
4171
+ height: `${height / 2}px`,
4172
+ width: "100%",
4173
+ left: 0
4174
+ };
4175
+ return /* @__PURE__ */ import_react33.default.createElement(import_react33.default.Fragment, null, /* @__PURE__ */ import_react33.default.createElement("div", { style: topHalfStyle }, /* @__PURE__ */ import_react33.default.createElement(Bars, { growUpwards: true })), /* @__PURE__ */ import_react33.default.createElement("div", { style: bottomHalfStyle }, /* @__PURE__ */ import_react33.default.createElement(Bars, { growUpwards: false })));
4176
+ }
4177
+ const containerStyle = {
4178
+ width: "100%",
4179
+ position: "absolute",
4180
+ top: `${height / 2 - height / 4}px`,
4181
+ height: `${height / 2}px`,
4182
+ left: 0
4183
+ };
4184
+ return /* @__PURE__ */ import_react33.default.createElement("div", { style: containerStyle }, /* @__PURE__ */ import_react33.default.createElement(Bars, { growUpwards: true }));
4185
+ };
4186
+
4187
+ // src/templates/waveform/components/WaveformLine.tsx
4188
+ var import_react34 = __toESM(require("react"));
4189
+ var import_media_utils2 = require("@remotion/media-utils");
4190
+ var import_remotion23 = require("remotion");
4191
+ var detectBeat = (frequencyData, amplitudes, threshold = 0.7, bpm, frame = 0, fps = 30) => {
4192
+ if (!frequencyData || !amplitudes || frequencyData.length === 0) return false;
4193
+ if (bpm) {
4194
+ const beatInterval = 60 / bpm * fps;
4195
+ const beatFrame = Math.round(frame / beatInterval) * beatInterval;
4196
+ return Math.abs(frame - beatFrame) < 2;
4197
+ }
4198
+ const bassFrequencies = amplitudes.slice(0, Math.floor(amplitudes.length * 0.15));
4199
+ const midFrequencies = amplitudes.slice(Math.floor(amplitudes.length * 0.15), Math.floor(amplitudes.length * 0.4));
4200
+ const bassEnergy = Math.sqrt(bassFrequencies.reduce((sum, val) => sum + val * val, 0) / bassFrequencies.length);
4201
+ const midEnergy = Math.sqrt(midFrequencies.reduce((sum, val) => sum + val * val, 0) / midFrequencies.length);
4202
+ const bassPeak = Math.max(...bassFrequencies);
4203
+ const midPeak = Math.max(...midFrequencies);
4204
+ const totalEnergy = bassEnergy * 0.6 + midEnergy * 0.2 + bassPeak * 0.15 + midPeak * 0.05;
4205
+ const normalizedEnergy = Math.min(totalEnergy, 1);
4206
+ return normalizedEnergy > threshold;
4207
+ };
4208
+ var easingFunctions = {
4209
+ linear: (t) => t,
4210
+ "ease-in": (t) => t * t,
4211
+ "ease-out": (t) => 1 - (1 - t) * (1 - t),
4212
+ "ease-in-out": (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2,
4213
+ bounce: (t) => {
4214
+ if (t < 1 / 2.75) return 7.5625 * t * t;
4215
+ if (t < 2 / 2.75) return 7.5625 * (t -= 1.5 / 2.75) * t + 0.75;
4216
+ if (t < 2.5 / 2.75) return 7.5625 * (t -= 2.25 / 2.75) * t + 0.9375;
4217
+ return 7.5625 * (t -= 2.625 / 2.75) * t + 0.984375;
4218
+ }
4219
+ };
4220
+ var WaveformLine = ({ data }) => {
4221
+ const {
4222
+ config: config15,
4223
+ className = "",
4224
+ style = {},
4225
+ strokeColor = "#FF6B6B",
4226
+ strokeWidth = 3,
4227
+ strokeLinecap = "round",
4228
+ strokeLinejoin = "round",
4229
+ fill = "none",
4230
+ opacity = 1,
4231
+ centerLine = false,
4232
+ centerLineColor = "#666",
4233
+ centerLineWidth = 1,
4234
+ beatSync = false,
4235
+ bpm,
4236
+ beatThreshold = 0.7,
4237
+ beatAmplitudeMultiplier = 1.2,
4238
+ beatAnimationDuration = 30,
4239
+ smoothAnimation = true,
4240
+ waveSpacing = 0.1,
4241
+ waveSegments = 1,
4242
+ waveOffset = 0,
4243
+ waveDirection = "horizontal",
4244
+ amplitudeCurve = "ease-out",
4245
+ animationSpeed = 0.5,
4246
+ pulseOnBeat = false,
4247
+ pulseColor = "#FFD700",
4248
+ pulseScale = 1.2
4249
+ } = data;
4250
+ return /* @__PURE__ */ import_react34.default.createElement(Waveform, { config: config15, className, style }, /* @__PURE__ */ import_react34.default.createElement(
4251
+ WaveformLineContent,
4252
+ {
4253
+ strokeColor,
4254
+ strokeWidth,
4255
+ strokeLinecap,
4256
+ strokeLinejoin,
4257
+ fill,
4258
+ opacity,
4259
+ centerLine,
4260
+ centerLineColor,
4261
+ centerLineWidth,
4262
+ beatSync,
4263
+ bpm,
4264
+ beatThreshold,
4265
+ beatAmplitudeMultiplier,
4266
+ beatAnimationDuration,
4267
+ smoothAnimation,
4268
+ waveSpacing,
4269
+ waveSegments,
4270
+ waveOffset,
4271
+ waveDirection,
4272
+ amplitudeCurve,
4273
+ animationSpeed,
4274
+ pulseOnBeat,
4275
+ pulseColor,
4276
+ pulseScale
4277
+ }
4278
+ ));
4279
+ };
4280
+ var WaveformLineContent = ({
4281
+ strokeColor,
4282
+ strokeWidth,
4283
+ strokeLinecap,
4284
+ strokeLinejoin,
4285
+ fill,
4286
+ opacity,
4287
+ centerLine,
4288
+ centerLineColor,
4289
+ centerLineWidth,
4290
+ beatSync,
4291
+ bpm,
4292
+ beatThreshold,
4293
+ beatAmplitudeMultiplier,
4294
+ beatAnimationDuration,
4295
+ smoothAnimation,
4296
+ waveSpacing,
4297
+ waveSegments,
4298
+ waveOffset,
4299
+ waveDirection,
4300
+ amplitudeCurve,
4301
+ animationSpeed,
4302
+ pulseOnBeat,
4303
+ pulseColor,
4304
+ pulseScale
4305
+ }) => {
4306
+ const { waveformData, frequencyData, amplitudes, width, height, config: config15, frame, fps } = useWaveformContext();
4307
+ const currentFrame = (0, import_remotion23.useCurrentFrame)();
4308
+ const videoConfig = (0, import_remotion23.useVideoConfig)();
4309
+ const isBeat = (0, import_react34.useMemo)(() => {
4310
+ if (!beatSync || !frequencyData || !amplitudes) return false;
4311
+ return detectBeat(frequencyData, amplitudes, beatThreshold, bpm, currentFrame, fps);
4312
+ }, [beatSync, frequencyData, amplitudes, beatThreshold, bpm, currentFrame, fps]);
4313
+ const beatProgress = (0, import_react34.useMemo)(() => {
4314
+ if (!isBeat || !beatAnimationDuration) return 0;
4315
+ const beatStartFrame = Math.floor(currentFrame / beatAnimationDuration) * beatAnimationDuration;
4316
+ const progress = (currentFrame - beatStartFrame) / beatAnimationDuration;
4317
+ const clampedProgress = Math.max(0, Math.min(1, progress));
4318
+ if (smoothAnimation) {
4319
+ return 1 - Math.pow(1 - clampedProgress, 3);
4320
+ }
4321
+ return clampedProgress;
4322
+ }, [isBeat, currentFrame, beatAnimationDuration, smoothAnimation]);
4323
+ const currentBeatMultiplier = (0, import_react34.useMemo)(() => {
4324
+ if (!beatSync || !isBeat || !beatAmplitudeMultiplier || !amplitudeCurve) return 1;
4325
+ const easing = easingFunctions[amplitudeCurve];
4326
+ const easedProgress = easing(beatProgress);
4327
+ return 1 + (beatAmplitudeMultiplier - 1) * (1 - easedProgress);
4328
+ }, [beatSync, isBeat, beatProgress, beatAmplitudeMultiplier, amplitudeCurve]);
4329
+ const smoothFactor = (0, import_react34.useMemo)(() => {
4330
+ if (!beatSync) {
4331
+ return 0.3;
4332
+ }
4333
+ return smoothAnimation ? 0.7 : 1;
4334
+ }, [beatSync, smoothAnimation]);
4335
+ const waveformPaths = (0, import_react34.useMemo)(() => {
4336
+ if (!waveformData) return [];
4337
+ const paths = [];
4338
+ const segments = waveSegments || 1;
4339
+ const spacing = waveSpacing || 0.1;
4340
+ const offset = waveOffset || 0;
4341
+ const speed = animationSpeed || 1;
4342
+ const segmentWidth = width / segments;
4343
+ const segmentSpacing = segmentWidth * spacing;
4344
+ for (let i = 0; i < segments; i++) {
4345
+ const segmentStart = i * segmentWidth;
4346
+ const segmentEnd = (i + 1) * segmentWidth;
4347
+ const segmentDataWidth = segmentEnd - segmentStart;
4348
+ const points = waveformData.map((y, index) => {
4349
+ const progress = index / (waveformData.length - 1);
4350
+ const x = segmentStart + progress * segmentDataWidth + offset;
4351
+ let animatedAmplitude = y * (config15.amplitude || 1) * currentBeatMultiplier * speed;
4352
+ const baseAmplitude = y * (config15.amplitude || 1) * speed;
4353
+ const beatAmplitude = animatedAmplitude - baseAmplitude;
4354
+ animatedAmplitude = baseAmplitude + beatAmplitude * smoothFactor;
4355
+ const yPos = waveDirection === "horizontal" ? animatedAmplitude * height / 2 + height / 2 : animatedAmplitude * width / 2 + width / 2;
4356
+ return waveDirection === "horizontal" ? { x, y: yPos } : { x: yPos, y: x };
4357
+ });
4358
+ const path = (0, import_media_utils2.createSmoothSvgPath)({ points });
4359
+ paths.push({ path, segmentIndex: i });
4360
+ }
4361
+ return paths;
4362
+ }, [waveformData, width, height, config15.amplitude, currentBeatMultiplier, animationSpeed, waveSegments, waveSpacing, waveOffset, waveDirection, smoothFactor]);
4363
+ if (!waveformData) {
4364
+ return /* @__PURE__ */ import_react34.default.createElement("div", { className: "flex items-center justify-center w-full h-full text-gray-500" }, "Loading waveform...");
4365
+ }
4366
+ return /* @__PURE__ */ import_react34.default.createElement(
4367
+ "svg",
4368
+ {
4369
+ width,
4370
+ height,
4371
+ className: "absolute inset-0",
4372
+ style: { pointerEvents: "none" }
4373
+ },
4374
+ centerLine && /* @__PURE__ */ import_react34.default.createElement(
4375
+ "line",
4376
+ {
4377
+ x1: waveDirection === "horizontal" ? 0 : width / 2,
4378
+ y1: waveDirection === "horizontal" ? height / 2 : 0,
4379
+ x2: waveDirection === "horizontal" ? width : width / 2,
4380
+ y2: waveDirection === "horizontal" ? height / 2 : height,
4381
+ stroke: centerLineColor,
4382
+ strokeWidth: centerLineWidth,
4383
+ opacity: 0.3
4384
+ }
4385
+ ),
4386
+ waveformPaths.map(({ path, segmentIndex }) => /* @__PURE__ */ import_react34.default.createElement("g", { key: segmentIndex }, pulseOnBeat && isBeat && /* @__PURE__ */ import_react34.default.createElement(
4387
+ "path",
4388
+ {
4389
+ d: path,
4390
+ stroke: pulseColor,
4391
+ strokeWidth: (strokeWidth || 3) * (pulseScale || 1.2),
4392
+ strokeLinecap,
4393
+ strokeLinejoin,
4394
+ fill: "none",
4395
+ opacity: (opacity || 1) * (1 - beatProgress)
4396
+ }
4397
+ ), /* @__PURE__ */ import_react34.default.createElement(
4398
+ "path",
4399
+ {
4400
+ d: path,
4401
+ stroke: strokeColor,
4402
+ strokeWidth,
4403
+ strokeLinecap,
4404
+ strokeLinejoin,
4405
+ fill,
4406
+ opacity
4407
+ }
4408
+ )))
4409
+ );
4410
+ };
4411
+
4412
+ // src/templates/waveform/utils.ts
4413
+ var WaveformPresets = {
4414
+ stopgapLine: (props) => {
4415
+ return {
4416
+ componentId: "WaveformLine",
4417
+ type: "atom",
4418
+ data: {
4419
+ strokeColor: "#58C4DC",
4420
+ strokeWidth: 8,
4421
+ strokeLinecap: "round",
4422
+ opacity: 1,
4423
+ amplitudeCurve: "ease-in-out",
4424
+ animationSpeed: 0.15,
4425
+ smoothAnimation: true,
4426
+ ...props,
4427
+ config: {
4428
+ numberOfSamples: 64,
4429
+ // Increased for better frequency resolution
4430
+ windowInSeconds: 1 / 30,
4431
+ amplitude: 4,
4432
+ height: 300,
4433
+ width: 1920 * 3,
4434
+ posterize: 4,
4435
+ ...props.config
4436
+ }
4437
+ }
4438
+ };
4439
+ }
4440
+ };
4441
+
4442
+ // src/templates/waveform/index.ts
4443
+ registerComponent("WaveformLine", WaveformLine, "atom", {
4444
+ displayName: "WaveformLine"
4445
+ });
4446
+ registerComponent("WaveformHistogram", WaveformHistogram, "atom", {
4447
+ displayName: "WaveformHistogram"
4448
+ });
4449
+ registerComponent("WaveformHistogramRanged", WaveformHistogramRanged, "atom", {
4450
+ displayName: "WaveformHistogramRanged"
4451
+ });
4452
+ registerComponent("WaveformCircle", WaveformCircle, "atom", {
4453
+ displayName: "WaveformCircle"
4454
+ });
4455
+
4456
+ // src/components/Composition.tsx
4457
+ var import_player = require("@remotion/player");
4458
+ var import_react35 = __toESM(require("react"));
4459
+ var import_remotion24 = require("remotion");
4460
+ var import_zod6 = __toESM(require("zod"));
4461
+ var CompositionLayout = ({ childrenData, style, config: config15 }) => {
4462
+ return /* @__PURE__ */ import_react35.default.createElement(
4463
+ CompositionProvider,
4464
+ {
4465
+ value: {
4466
+ root: childrenData,
4467
+ duration: config15.duration
4468
+ }
4469
+ },
4470
+ /* @__PURE__ */ import_react35.default.createElement(import_remotion24.AbsoluteFill, { style }, childrenData?.map((component) => /* @__PURE__ */ import_react35.default.createElement(
4471
+ ComponentRenderer,
4472
+ {
4473
+ key: component.id,
4474
+ ...component
4475
+ }
4476
+ )))
4477
+ );
4478
+ };
4479
+ var calculateCompositionLayoutMetadata = async ({ props, defaultProps, abortSignal, isRendering }) => {
4480
+ const updatedProps = await setDurationsInContext(props);
4481
+ let calculatedDuration = void 0;
4482
+ if (props.config?.fitDurationTo?.length > 0) {
4483
+ calculatedDuration = await calculateDuration(updatedProps.childrenData, {
4484
+ fitDurationTo: updatedProps.config.fitDurationTo
4485
+ });
4486
+ }
4487
+ const duration = calculatedDuration ?? props.config.duration ?? defaultProps.config.duration;
4488
+ const fps = props.config.fps ?? defaultProps.config.fps;
4489
+ const durationInFrames = Math.round(duration * fps);
4490
+ return {
4491
+ // Change the metadata
4492
+ durationInFrames,
4493
+ // or transform some props
4494
+ props: updatedProps,
4495
+ // // or add per-composition default codec
4496
+ // defaultCodec: 'h264',
4497
+ // // or add per-composition default video image format
4498
+ // defaultVideoImageFormat: 'png',
4499
+ // // or add per-composition default pixel format
4500
+ // defaultPixelFormat: 'yuv420p',
4501
+ width: props.config?.width || defaultProps.config.width,
4502
+ height: props.config?.height || defaultProps.config.height,
4503
+ fps,
4504
+ duration
4505
+ };
4506
+ };
4507
+ var Composition = ({
4508
+ id,
4509
+ childrenData,
4510
+ config: config15,
4511
+ style
4512
+ }) => {
4513
+ return /* @__PURE__ */ import_react35.default.createElement(
4514
+ import_remotion24.Composition,
4515
+ {
4516
+ id,
4517
+ component: CompositionLayout,
4518
+ durationInFrames: Math.round(config15.duration * config15.fps),
4519
+ fps: config15.fps,
4520
+ width: config15.width ?? 1080,
4521
+ height: config15.height ?? 1920,
4522
+ defaultProps: { childrenData, style, config: config15 },
4523
+ calculateMetadata: calculateCompositionLayoutMetadata,
4524
+ schema: import_zod6.default.object({})
4525
+ }
4526
+ );
4527
+ };
4528
+ var Player = (props) => {
4529
+ return /* @__PURE__ */ import_react35.default.createElement(
4530
+ import_player.Player,
4531
+ {
4532
+ component: CompositionLayout,
4533
+ durationInFrames: props.durationInFrames > 0 ? props.durationInFrames : 20,
4534
+ compositionWidth: props.compositionWidth > 0 ? props.compositionWidth : 1920,
4535
+ compositionHeight: props.compositionHeight > 0 ? props.compositionHeight : 1080,
4536
+ fps: props.fps > 0 ? props.fps : 30,
4537
+ ...props
4538
+ }
4539
+ );
4540
+ };
4541
+ // Annotate the CommonJS export names for ESM import in node:
4542
+ 0 && (module.exports = {
4543
+ AudioAtom,
4544
+ AudioAtomConfig,
4545
+ BaseLayout,
4546
+ BaseLayoutConfig,
4547
+ BlurEffect,
4548
+ BlurEffectConfig,
4549
+ ComponentRenderer,
4550
+ Composition,
4551
+ CompositionLayout,
4552
+ CompositionProvider,
4553
+ Frame,
4554
+ GenericEffectPresets,
4555
+ ImageAtom,
4556
+ ImageAtomConfig,
4557
+ LoopEffect,
4558
+ LoopEffectConfig,
4559
+ LottieAtom,
4560
+ LottieAtomConfig,
4561
+ NextjsLogo,
4562
+ PanEffect,
4563
+ PanEffectConfig,
4564
+ Player,
4565
+ Rings,
4566
+ RippleOutLayout,
4567
+ SceneFrame,
4568
+ ShakeEffect,
4569
+ ShakeEffectConfig,
4570
+ ShapeAtom,
4571
+ ShapeAtomConfig,
4572
+ StretchEffect,
4573
+ StretchEffectConfig,
4574
+ TextAtom,
4575
+ TextAtomConfig,
4576
+ TextFade,
4577
+ UniversalEffect,
4578
+ UniversalEffectProvider,
4579
+ VideoAtom,
4580
+ VideoAtomConfig,
4581
+ Waveform,
4582
+ WaveformCircle,
4583
+ WaveformHistogram,
4584
+ WaveformHistogramRanged,
4585
+ WaveformLine,
4586
+ WaveformPresets,
4587
+ ZoomEffect,
4588
+ ZoomEffectConfig,
4589
+ buildLayoutHook,
4590
+ calculateCircularPosition,
4591
+ calculateComponentDuration,
4592
+ calculateCompositionLayoutMetadata,
4593
+ calculateDuration,
4594
+ calculateGridPosition,
4595
+ calculateHierarchy,
4596
+ calculateTimingWithInheritance,
4597
+ clearFontCache,
4598
+ componentRegistry,
4599
+ createImageDataWithProxy,
4600
+ createImageProxyUrl,
4601
+ createRootContext,
4602
+ findComponentById,
4603
+ findMatchingComponents,
4604
+ findMatchingComponentsByQuery,
4605
+ findParentComponent,
4606
+ getComponent,
4607
+ getComponentConfig,
4608
+ getComponentWithConfig,
4609
+ getLoadedFontFamily,
4610
+ getLoadedFonts,
4611
+ getNormalizedFontName,
4612
+ isFontAvailable,
4613
+ isFontLoaded,
4614
+ loadGoogleFont,
4615
+ loadMultipleFonts,
4616
+ mergeContexts,
4617
+ needsProxying,
4618
+ nextjsLogoConfig,
4619
+ preloadCommonFonts,
4620
+ registerComponent,
4621
+ registerEffect,
4622
+ registerPackage,
4623
+ ringsConfig,
4624
+ rippleOutLayoutConfig,
4625
+ setDurationsInContext,
4626
+ textFadeConfig,
4627
+ useAnimatedStyles,
4628
+ useBoundaryCalculation,
4629
+ useComponentRegistry,
4630
+ useComposition,
4631
+ useFont,
4632
+ useFontLoader,
4633
+ useHasUniversalEffectProvider,
4634
+ useRenderContext,
4635
+ useRippleOutLayout,
4636
+ useUniversalEffect,
4637
+ useUniversalEffectOptional,
4638
+ useWaveformContext,
4639
+ useWaveformData
4640
+ });
4641
+ //# sourceMappingURL=index.js.map