@microfox/remotion 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs DELETED
@@ -1,3218 +0,0 @@
1
- // src/core/registry/componentRegistry.ts
2
- var ComponentRegistryManager = class {
3
- constructor() {
4
- this.registry = {};
5
- this.packageRegistry = {};
6
- }
7
- registerComponent(name, component, type, config12 = { displayName: "" }, packageName) {
8
- this.registry[name] = { component, config: config12 };
9
- if (packageName) {
10
- if (!this.packageRegistry[packageName]) {
11
- this.packageRegistry[packageName] = {};
12
- }
13
- this.packageRegistry[packageName][name] = { component, config: config12 };
14
- }
15
- }
16
- registerEffect(name, component, config12 = { displayName: "" }, packageName) {
17
- this.registerComponent(
18
- name?.includes("effect-") ? name : `effect-${name}`,
19
- component,
20
- "layout",
21
- config12,
22
- packageName
23
- );
24
- }
25
- getComponent(name) {
26
- return this.registry[name]?.component;
27
- }
28
- getComponentConfig(name) {
29
- return this.registry[name]?.config;
30
- }
31
- getComponentWithConfig(name) {
32
- return this.registry[name];
33
- }
34
- registerPackage(packageName, components) {
35
- this.packageRegistry[packageName] = components;
36
- Object.entries(components).forEach(([name, { component, config: config12 }]) => {
37
- this.registry[`${packageName}:${name}`] = { component, config: config12 };
38
- });
39
- }
40
- getPackageComponents(packageName) {
41
- return this.packageRegistry[packageName];
42
- }
43
- getAllComponents() {
44
- return { ...this.registry };
45
- }
46
- clear() {
47
- this.registry = {};
48
- this.packageRegistry = {};
49
- }
50
- };
51
- var componentRegistry = new ComponentRegistryManager();
52
- var registerComponent = (name, component, type, config12 = { displayName: "" }, packageName) => {
53
- componentRegistry.registerComponent(
54
- name,
55
- component,
56
- type,
57
- config12,
58
- packageName
59
- );
60
- };
61
- var registerEffect = (name, component, config12 = { displayName: "" }, packageName) => {
62
- componentRegistry.registerEffect(name, component, config12, packageName);
63
- };
64
- var registerPackage = (packageName, components) => {
65
- componentRegistry.registerPackage(packageName, components);
66
- };
67
- var getComponent = (name) => componentRegistry.getComponent(name);
68
- var getComponentConfig = (name) => componentRegistry.getComponentConfig(name);
69
- var getComponentWithConfig = (name) => componentRegistry.getComponentWithConfig(name);
70
-
71
- // src/core/context/CompositionContext.tsx
72
- import React, { createContext, useContext } from "react";
73
- var CompositionContext = createContext(null);
74
- var CompositionProvider = ({ children, value }) => {
75
- return /* @__PURE__ */ React.createElement(CompositionContext.Provider, { value }, children);
76
- };
77
- var useComposition = () => {
78
- const context = useContext(CompositionContext);
79
- if (!context) {
80
- throw new Error("useComposition must be used within a CompositionProvider");
81
- }
82
- return context;
83
- };
84
-
85
- // src/components/base/ComponentRenderer.tsx
86
- import React3, { createContext as createContext2, useContext as useContext2 } from "react";
87
- import { Sequence, Series, useVideoConfig } from "remotion";
88
-
89
- // src/core/utils/timing.ts
90
- var calculateTiming = (type, context, videoConfig) => {
91
- let newTiming;
92
- if (type !== "atom" && context?.timing) {
93
- const { start = 0, duration = 0 } = context.timing;
94
- newTiming = {
95
- startInFrames: Math.round(
96
- context.timing?.startInFrames ? context.timing.startInFrames : type === "scene" ? start * videoConfig.fps : start * videoConfig.fps
97
- ),
98
- durationInFrames: Math.round(
99
- context.timing?.durationInFrames ? context.timing.durationInFrames : type === "scene" ? duration * videoConfig.fps : duration * videoConfig.fps
100
- ),
101
- duration,
102
- start
103
- };
104
- } else {
105
- newTiming = {
106
- startInFrames: context.timing?.startInFrames ? context.timing.startInFrames : context.timing?.start ? Math.round(videoConfig.fps * (context.timing.start || 0)) : 0,
107
- durationInFrames: Math.round(
108
- context.timing?.durationInFrames ? context.timing.durationInFrames : context.timing?.duration ? Math.round(videoConfig.fps * (context.timing.duration || 0)) : 0
109
- ),
110
- duration: context.timing?.duration,
111
- start: context.timing?.start
112
- };
113
- }
114
- return newTiming;
115
- };
116
-
117
- // src/core/utils/hierarchyUtils.ts
118
- var findComponentById = (root, targetId) => {
119
- if (!root) return null;
120
- const search = (components) => {
121
- for (const component of components) {
122
- if (component.id === targetId) {
123
- return component;
124
- }
125
- if (component.childrenData && component.childrenData.length > 0) {
126
- const found = search(component.childrenData);
127
- if (found) return found;
128
- }
129
- }
130
- return null;
131
- };
132
- return search(root);
133
- };
134
- var findParentComponent = (root, targetId) => {
135
- if (!root) return null;
136
- const search = (components, parent) => {
137
- for (const component of components) {
138
- if (component.childrenData && component.childrenData.length > 0) {
139
- const hasTargetChild = component.childrenData.some(
140
- (child) => child.id === targetId
141
- );
142
- if (hasTargetChild) {
143
- return component;
144
- }
145
- const found = search(component.childrenData, component);
146
- if (found) return found;
147
- }
148
- }
149
- return null;
150
- };
151
- return search(root, null);
152
- };
153
- var calculateHierarchy = (root, componentId, currentContext) => {
154
- if (!root) {
155
- return {
156
- depth: (currentContext?.hierarchy?.depth || 0) + 1,
157
- parentIds: [...currentContext?.hierarchy?.parentIds || [], componentId]
158
- };
159
- }
160
- const parentIds = [];
161
- let depth = 0;
162
- const traverse = (components, currentDepth) => {
163
- for (const component of components) {
164
- if (component.id === componentId) {
165
- depth = currentDepth;
166
- return true;
167
- }
168
- if (component.childrenData && component.childrenData.length > 0) {
169
- parentIds.push(component.id);
170
- const found = traverse(component.childrenData, currentDepth + 1);
171
- if (found) return true;
172
- parentIds.pop();
173
- }
174
- }
175
- return false;
176
- };
177
- traverse(root, 0);
178
- return {
179
- depth,
180
- parentIds: [...parentIds]
181
- };
182
- };
183
- var calculateTimingWithInheritance = (component, root, videoConfig) => {
184
- const currentContext = component.context || {};
185
- const baseTiming = calculateTiming(
186
- component.type,
187
- currentContext,
188
- videoConfig
189
- );
190
- if (!baseTiming.durationInFrames || baseTiming.durationInFrames <= 0) {
191
- const findParentWithTiming = (targetId) => {
192
- const parent = findParentComponent(root, targetId);
193
- if (!parent) return null;
194
- const parentContext = parent.context || {};
195
- const parentTiming = calculateTiming(
196
- parent.type,
197
- parentContext,
198
- videoConfig
199
- );
200
- if (parentTiming.durationInFrames && parentTiming.durationInFrames > 0) {
201
- return parentTiming;
202
- }
203
- return findParentWithTiming(parent.id);
204
- };
205
- const inheritedTiming = findParentWithTiming(component.id);
206
- if (inheritedTiming) {
207
- return {
208
- ...baseTiming,
209
- durationInFrames: inheritedTiming.durationInFrames ? inheritedTiming.durationInFrames : inheritedTiming.duration ? inheritedTiming.duration * videoConfig.fps : 0,
210
- duration: inheritedTiming.duration
211
- };
212
- }
213
- }
214
- return baseTiming;
215
- };
216
-
217
- // src/components/base/EffectWrapper.tsx
218
- import React2 from "react";
219
- var EffectWrapper = ({
220
- effects,
221
- children,
222
- context
223
- }) => {
224
- if (!effects || effects.length === 0) {
225
- return children;
226
- }
227
- let wrappedContent = children;
228
- effects.forEach((effect, index) => {
229
- const effectId = typeof effect === "string" ? `effect-${effect}` : `effect-${effect.componentId}`;
230
- const EffectComponent = getComponent(effectId);
231
- if (!EffectComponent) {
232
- console.warn(`Effect component ${effectId} not found in registry`);
233
- return;
234
- }
235
- const effectData = typeof effect === "string" ? {} : effect.data || {};
236
- const effectContext = typeof effect === "string" ? context : effect.context || context;
237
- const effectProps = {
238
- id: typeof effect === "string" ? `effect-${index}` : effect.id,
239
- componentId: effectId,
240
- type: "layout",
241
- // Effects use the same rendering logic as layout
242
- data: effectData,
243
- context: effectContext,
244
- children: wrappedContent
245
- };
246
- wrappedContent = /* @__PURE__ */ React2.createElement(EffectComponent, { ...effectProps });
247
- });
248
- return /* @__PURE__ */ React2.createElement(React2.Fragment, null, wrappedContent);
249
- };
250
-
251
- // src/components/base/ComponentRenderer.tsx
252
- var RenderContext = createContext2(null);
253
- var useRenderContext = () => {
254
- const context = useContext2(RenderContext);
255
- if (!context) {
256
- throw new Error("useRenderContext must be used within a ComponentRenderer");
257
- }
258
- return context;
259
- };
260
- var ComponentRenderer = ({
261
- id,
262
- componentId,
263
- type,
264
- data,
265
- childrenData,
266
- context,
267
- effects
268
- }) => {
269
- const videoConfig = useVideoConfig();
270
- const { root } = useComposition();
271
- const defaultContext = {
272
- boundaries: {
273
- left: 0,
274
- top: 0,
275
- width: videoConfig.width,
276
- height: videoConfig.height,
277
- zIndex: 0
278
- },
279
- timing: {
280
- startInFrames: 0,
281
- durationInFrames: videoConfig.durationInFrames
282
- },
283
- hierarchy: {
284
- depth: 0,
285
- parentIds: []
286
- }
287
- };
288
- if (!context) {
289
- context = {};
290
- }
291
- const newHierarchy = calculateHierarchy(root, id, context ?? defaultContext);
292
- const componentData = {
293
- id,
294
- componentId,
295
- type,
296
- data,
297
- childrenData,
298
- context,
299
- effects
300
- };
301
- let newTiming = calculateTimingWithInheritance(componentData, root, videoConfig);
302
- const newContext = {
303
- ...context,
304
- boundaries: context?.boundaries,
305
- hierarchy: newHierarchy,
306
- timing: newTiming
307
- };
308
- const ComponentClass = getComponent(componentId);
309
- if (type === "scene") {
310
- return /* @__PURE__ */ React3.createElement(RenderContext.Provider, { value: newContext }, /* @__PURE__ */ React3.createElement(Series, null, childrenData?.map((child) => {
311
- const childTiming = calculateTimingWithInheritance(child, root, videoConfig);
312
- return /* @__PURE__ */ React3.createElement(
313
- Series.Sequence,
314
- {
315
- key: child.id,
316
- name: child.componentId + " - " + child.id,
317
- offset: childTiming.startInFrames ?? 0,
318
- durationInFrames: childTiming.durationInFrames ?? 0
319
- },
320
- child.effects && child.effects.length > 0 ? /* @__PURE__ */ React3.createElement(EffectWrapper, { effects: child.effects, context: newContext }, /* @__PURE__ */ React3.createElement(ComponentRenderer, { key: child.id, ...child })) : /* @__PURE__ */ React3.createElement(ComponentRenderer, { key: child.id, ...child })
321
- );
322
- })));
323
- }
324
- if (!ComponentClass) {
325
- console.warn(`Component type ${id} not found in registry`);
326
- return null;
327
- }
328
- const props = {
329
- id,
330
- componentId,
331
- data,
332
- context
333
- };
334
- if (type === "layout") {
335
- const config12 = getComponentConfig(componentId);
336
- const isInnerSequence = config12?.isInnerSequence;
337
- if (isInnerSequence) {
338
- return /* @__PURE__ */ React3.createElement(RenderContext.Provider, { value: newContext }, /* @__PURE__ */ React3.createElement(ComponentClass, { ...props }, effects && effects.length > 0 ? /* @__PURE__ */ React3.createElement(EffectWrapper, { effects, context: newContext }, childrenData?.map((child) => /* @__PURE__ */ React3.createElement(ComponentRenderer, { key: child.id, ...child }))) : childrenData?.map((child) => /* @__PURE__ */ React3.createElement(ComponentRenderer, { key: child.id, ...child }))));
339
- }
340
- return /* @__PURE__ */ React3.createElement(RenderContext.Provider, { value: newContext }, /* @__PURE__ */ React3.createElement(Sequence, { layout: "none", name: componentId + " - " + id, from: newTiming.startInFrames, durationInFrames: newTiming.durationInFrames }, /* @__PURE__ */ React3.createElement(ComponentClass, { ...props }, effects && effects.length > 0 ? /* @__PURE__ */ React3.createElement(EffectWrapper, { effects, context: newContext }, childrenData?.map((child) => /* @__PURE__ */ React3.createElement(ComponentRenderer, { key: child.id, ...child }))) : childrenData?.map((child) => /* @__PURE__ */ React3.createElement(ComponentRenderer, { key: child.id, ...child })))));
341
- }
342
- if (type === "atom") {
343
- if (newTiming.durationInFrames && newTiming.durationInFrames > 0) {
344
- return /* @__PURE__ */ React3.createElement(RenderContext.Provider, { value: newContext }, /* @__PURE__ */ React3.createElement(Sequence, { layout: "none", name: componentId + " - " + id, from: newTiming.startInFrames, durationInFrames: newTiming.durationInFrames }, effects && effects.length > 0 ? /* @__PURE__ */ React3.createElement(EffectWrapper, { effects, context: newContext }, /* @__PURE__ */ React3.createElement(ComponentClass, { ...props })) : /* @__PURE__ */ React3.createElement(ComponentClass, { ...props })));
345
- }
346
- return /* @__PURE__ */ React3.createElement(RenderContext.Provider, { value: newContext }, effects && effects.length > 0 ? /* @__PURE__ */ React3.createElement(EffectWrapper, { effects, context: newContext }, /* @__PURE__ */ React3.createElement(ComponentClass, { ...props })) : /* @__PURE__ */ React3.createElement(ComponentClass, { ...props }));
347
- }
348
- };
349
-
350
- // src/components/frames/Frame.tsx
351
- import React4 from "react";
352
- import { AbsoluteFill } from "remotion";
353
- var Frame = ({ children, data }) => {
354
- return /* @__PURE__ */ React4.createElement(AbsoluteFill, { style: data?.style }, children);
355
- };
356
-
357
- // src/components/frames/SceneFrame.tsx
358
- import React5 from "react";
359
- import { AbsoluteFill as AbsoluteFill2 } from "remotion";
360
- var SceneFrame = ({ children }) => {
361
- return /* @__PURE__ */ React5.createElement(AbsoluteFill2, null, children);
362
- };
363
-
364
- // src/components/layouts/BaseLayout.tsx
365
- import React6, { Children } from "react";
366
- import { AbsoluteFill as AbsoluteFill3 } from "remotion";
367
- var Layout = ({ id, children, data, context }) => {
368
- const { containerProps, childrenProps } = data || {
369
- containerProps: {},
370
- childrenProps: []
371
- };
372
- const childrenArray = Children.toArray(children);
373
- return (
374
- // @ts-ignore
375
- /* @__PURE__ */ React6.createElement(
376
- AbsoluteFill3,
377
- {
378
- ...containerProps,
379
- style: {
380
- ...context?.boundaries,
381
- ...containerProps.style
382
- }
383
- },
384
- childrenArray.map((child, index) => /* @__PURE__ */ React6.createElement(
385
- "div",
386
- {
387
- key: index,
388
- ...index < childrenProps.length && childrenProps[index]
389
- },
390
- child
391
- ))
392
- )
393
- );
394
- };
395
- var config = {
396
- displayName: "BaseLayout",
397
- type: "layout",
398
- isInnerSequence: false
399
- };
400
-
401
- // src/components/layouts/index.ts
402
- registerComponent(
403
- config.displayName,
404
- Layout,
405
- "layout",
406
- config
407
- );
408
-
409
- // src/components/atoms/ShapeAtom.tsx
410
- import React7 from "react";
411
- import { Easing, interpolate, useCurrentFrame } from "remotion";
412
- var Atom = ({ data }) => {
413
- const frame = useCurrentFrame();
414
- const { shape, color, rotation, style } = data;
415
- const rotationStyle = rotation ? {
416
- transform: `rotate(${interpolate(
417
- frame % rotation.duration,
418
- [0, rotation.duration],
419
- [0, 360],
420
- {
421
- extrapolateLeft: "clamp",
422
- extrapolateRight: "clamp",
423
- easing: Easing.linear
424
- }
425
- )}deg)`
426
- } : {};
427
- const baseStyle = {
428
- width: "100%",
429
- height: "100%",
430
- ...style,
431
- ...rotationStyle
432
- };
433
- switch (shape) {
434
- case "circle":
435
- return /* @__PURE__ */ React7.createElement("div", { style: { ...baseStyle, backgroundColor: color, borderRadius: "50%" } });
436
- case "rectangle":
437
- return /* @__PURE__ */ React7.createElement("div", { style: { ...baseStyle, backgroundColor: color } });
438
- default:
439
- return null;
440
- }
441
- };
442
- var config2 = {
443
- displayName: "ShapeAtom",
444
- type: "atom",
445
- isInnerSequence: false
446
- };
447
-
448
- // src/components/atoms/ImageAtom.tsx
449
- import React8, { useMemo } from "react";
450
- import { Img, staticFile } from "remotion";
451
- var Atom2 = ({ data }) => {
452
- const source = useMemo(() => {
453
- if (data.src.startsWith("http")) {
454
- return data.src;
455
- }
456
- return staticFile(data.src);
457
- }, [data.src]);
458
- return /* @__PURE__ */ React8.createElement(Img, { className: data.className, src: source, style: data.style, crossOrigin: "anonymous" });
459
- };
460
- var config3 = {
461
- displayName: "ImageAtom",
462
- type: "atom",
463
- isInnerSequence: false
464
- };
465
-
466
- // src/components/atoms/TextAtom.tsx
467
- import React9, { useEffect as useEffect2, useState as useState2 } from "react";
468
-
469
- // src/hooks/useFontLoader.ts
470
- import { useState, useEffect, useCallback } from "react";
471
-
472
- // src/utils/fontUtils.ts
473
- import { getAvailableFonts } from "@remotion/google-fonts";
474
- var availableFonts = getAvailableFonts();
475
- var loadedFonts = /* @__PURE__ */ new Map();
476
- var loadGoogleFont = async (fontFamily2, options = {}) => {
477
- if (!fontFamily2 || typeof fontFamily2 !== "string" || fontFamily2 === "") {
478
- console.warn("Invalid fontFamily provided:", fontFamily2);
479
- return "sans-serif";
480
- }
481
- const fontKey = `${fontFamily2}-${JSON.stringify(options)}`;
482
- if (loadedFonts.has(fontKey)) {
483
- return loadedFonts.get(fontKey);
484
- }
485
- try {
486
- console.log("availableFonts", availableFonts);
487
- const thisFont = availableFonts.find(
488
- (font) => font.importName === fontFamily2
489
- );
490
- console.log("thisFont", thisFont);
491
- if (thisFont?.load) {
492
- const fontPackage = await thisFont.load();
493
- const allFontStuff = fontPackage.loadFont("normal", {
494
- subsets: options.subsets || ["latin"],
495
- weights: options.weights || ["400"]
496
- });
497
- console.log("loadedFontFamily", allFontStuff.fontFamily);
498
- await allFontStuff.waitUntilDone();
499
- loadedFonts.set(fontKey, allFontStuff.fontFamily);
500
- return allFontStuff.fontFamily;
501
- } else {
502
- throw new Error(
503
- `Font Package @remotion/google-fonts/${fontFamily2} does not have loadFont method`
504
- );
505
- }
506
- } catch (error) {
507
- console.warn(`Failed to load font ${fontFamily2}:`, error);
508
- try {
509
- const alternativeNames = [
510
- fontFamily2.toLowerCase().replace(/\s+/g, ""),
511
- fontFamily2.toLowerCase().replace(/\s+/g, "-"),
512
- fontFamily2.toLowerCase().replace(/\s+/g, "_")
513
- ];
514
- for (const altName of alternativeNames) {
515
- if (altName === fontFamily2.toLowerCase().replace(/\s+/g, "-")) {
516
- continue;
517
- }
518
- try {
519
- const altFontPackage = await import(`@remotion/google-fonts/${altName}`);
520
- if (altFontPackage.loadFont) {
521
- const { fontFamily: loadedFontFamily } = await altFontPackage.loadFont("normal", {
522
- subsets: options.subsets || ["latin"],
523
- weights: options.weights || ["400"],
524
- display: options.display || "swap",
525
- preload: options.preload !== false
526
- });
527
- loadedFonts.set(fontKey, loadedFontFamily);
528
- return loadedFontFamily;
529
- }
530
- } catch (altError) {
531
- continue;
532
- }
533
- }
534
- } catch (altError) {
535
- }
536
- const fallbackFontFamily = `"${fontFamily2}"`;
537
- loadedFonts.set(fontKey, fallbackFontFamily);
538
- return fallbackFontFamily;
539
- }
540
- };
541
- var loadMultipleFonts = async (fonts) => {
542
- const loadPromises = fonts.map(async ({ family, options }) => {
543
- const fontFamily2 = await loadGoogleFont(family, options);
544
- return { family, fontFamily: fontFamily2 };
545
- });
546
- const results = await Promise.all(loadPromises);
547
- const fontMap = /* @__PURE__ */ new Map();
548
- results.forEach(({ family, fontFamily: fontFamily2 }) => {
549
- fontMap.set(family, fontFamily2);
550
- });
551
- return fontMap;
552
- };
553
- var getLoadedFontFamily = (fontFamily2, options = {}) => {
554
- const fontKey = `${fontFamily2}-${JSON.stringify(options)}`;
555
- return loadedFonts.get(fontKey);
556
- };
557
- var preloadCommonFonts = async () => {
558
- const commonFonts = [
559
- { family: "Inter", options: { weights: ["400", "500", "600", "700"] } },
560
- { family: "Roboto", options: { weights: ["400", "500", "700"] } },
561
- { family: "Open Sans", options: { weights: ["400", "600", "700"] } },
562
- { family: "Lato", options: { weights: ["400", "700"] } }
563
- ];
564
- return await loadMultipleFonts(commonFonts);
565
- };
566
- var isFontLoaded = (fontFamily2, options = {}) => {
567
- const fontKey = `${fontFamily2}-${JSON.stringify(options)}`;
568
- return loadedFonts.has(fontKey);
569
- };
570
- var clearFontCache = () => {
571
- loadedFonts.clear();
572
- };
573
- var getLoadedFonts = () => {
574
- return new Map(loadedFonts);
575
- };
576
- var isFontAvailable = async (fontFamily2) => {
577
- if (!fontFamily2 || typeof fontFamily2 !== "string") {
578
- return false;
579
- }
580
- try {
581
- const normalizedFontName = fontFamily2.trim().replace(/\s+/g, "-").toLowerCase();
582
- const fontPackage = await import(`@remotion/google-fonts/${normalizedFontName}`);
583
- return !!fontPackage.loadFont;
584
- } catch (error) {
585
- return false;
586
- }
587
- };
588
- var getNormalizedFontName = (fontFamily2) => {
589
- if (!fontFamily2 || typeof fontFamily2 !== "string") {
590
- return "";
591
- }
592
- return fontFamily2.trim().replace(/\s+/g, "-").toLowerCase();
593
- };
594
-
595
- // src/hooks/useFontLoader.ts
596
- var useFontLoader = (options = {}) => {
597
- const [state, setState] = useState({
598
- loadedFonts: /* @__PURE__ */ new Map(),
599
- loadingFonts: /* @__PURE__ */ new Set(),
600
- errorFonts: /* @__PURE__ */ new Map()
601
- });
602
- const loadFont2 = useCallback(
603
- async (fontFamily2, fontOptions = {}) => {
604
- const fontKey = `${fontFamily2}-${JSON.stringify(fontOptions)}`;
605
- if (state.loadedFonts.has(fontKey) || state.loadingFonts.has(fontFamily2)) {
606
- return state.loadedFonts.get(fontKey) || `"${fontFamily2}", sans-serif`;
607
- }
608
- setState((prev) => ({
609
- ...prev,
610
- loadingFonts: new Set(prev.loadingFonts).add(fontFamily2)
611
- }));
612
- try {
613
- const cssValue = await loadGoogleFont(fontFamily2, fontOptions);
614
- if (cssValue !== null) {
615
- setState((prev) => ({
616
- ...prev,
617
- loadedFonts: new Map(prev.loadedFonts).set(fontKey, cssValue),
618
- loadingFonts: new Set(
619
- [...prev.loadingFonts].filter((f) => f !== fontFamily2)
620
- )
621
- }));
622
- options.onLoad?.(fontFamily2, cssValue);
623
- return cssValue;
624
- } else {
625
- throw new Error(
626
- `Font Package @remotion/google-fonts/${fontFamily2} not found`
627
- );
628
- }
629
- } catch (error) {
630
- const errorObj = error instanceof Error ? error : new Error(String(error));
631
- setState((prev) => ({
632
- ...prev,
633
- errorFonts: new Map(prev.errorFonts).set(fontFamily2, errorObj),
634
- loadingFonts: new Set(
635
- [...prev.loadingFonts].filter((f) => f !== fontFamily2)
636
- )
637
- }));
638
- options.onError?.(fontFamily2, errorObj);
639
- const fallbackValue = `"${fontFamily2}", sans-serif`;
640
- return fallbackValue;
641
- }
642
- },
643
- [state.loadedFonts, state.loadingFonts, options]
644
- );
645
- const loadMultipleFonts2 = useCallback(
646
- async (fonts) => {
647
- const fontsToLoad = fonts.filter(({ family, options: options2 = {} }) => {
648
- const fontKey = `${family}-${JSON.stringify(options2)}`;
649
- return !state.loadedFonts.has(fontKey) && !state.loadingFonts.has(family);
650
- });
651
- if (fontsToLoad.length === 0) {
652
- return state.loadedFonts;
653
- }
654
- setState((prev) => ({
655
- ...prev,
656
- loadingFonts: /* @__PURE__ */ new Set([
657
- ...prev.loadingFonts,
658
- ...fontsToLoad.map((f) => f.family)
659
- ])
660
- }));
661
- try {
662
- const fontMap = await loadMultipleFonts(fontsToLoad);
663
- const newFontsMap = /* @__PURE__ */ new Map();
664
- fontsToLoad.forEach(({ family, options: options2 = {} }) => {
665
- const fontKey = `${family}-${JSON.stringify(options2)}`;
666
- const cssValue = fontMap.get(family);
667
- if (cssValue) {
668
- newFontsMap.set(fontKey, cssValue);
669
- }
670
- });
671
- setState((prev) => ({
672
- ...prev,
673
- loadedFonts: new Map([...prev.loadedFonts, ...newFontsMap]),
674
- loadingFonts: new Set(
675
- [...prev.loadingFonts].filter(
676
- (f) => !fontsToLoad.some((ftl) => ftl.family === f)
677
- )
678
- )
679
- }));
680
- fontsToLoad.forEach(({ family }) => {
681
- const cssValue = fontMap.get(family);
682
- if (cssValue) {
683
- options.onLoad?.(family, cssValue);
684
- }
685
- });
686
- return fontMap;
687
- } catch (error) {
688
- const errorObj = error instanceof Error ? error : new Error(String(error));
689
- setState((prev) => ({
690
- ...prev,
691
- errorFonts: new Map(prev.errorFonts).set("multiple", errorObj),
692
- loadingFonts: new Set(
693
- [...prev.loadingFonts].filter(
694
- (f) => !fontsToLoad.some((ftl) => ftl.family === f)
695
- )
696
- )
697
- }));
698
- options.onError?.("multiple", errorObj);
699
- return state.loadedFonts;
700
- }
701
- },
702
- [state.loadedFonts, state.loadingFonts, options]
703
- );
704
- const isFontReady = useCallback(
705
- (fontFamily2, options2 = {}) => {
706
- const fontKey = `${fontFamily2}-${JSON.stringify(options2)}`;
707
- return state.loadedFonts.has(fontKey);
708
- },
709
- [state.loadedFonts]
710
- );
711
- const areFontsReady = useCallback(
712
- (fontFamilies) => {
713
- return fontFamilies.every(({ family, options: options2 = {} }) => {
714
- const fontKey = `${family}-${JSON.stringify(options2)}`;
715
- return state.loadedFonts.has(fontKey);
716
- });
717
- },
718
- [state.loadedFonts]
719
- );
720
- const getFontFamily = useCallback(
721
- (fontFamily2, options2 = {}) => {
722
- const fontKey = `${fontFamily2}-${JSON.stringify(options2)}`;
723
- return state.loadedFonts.get(fontKey);
724
- },
725
- [state.loadedFonts]
726
- );
727
- const getFontError = useCallback(
728
- (fontFamily2) => {
729
- return state.errorFonts.get(fontFamily2);
730
- },
731
- [state.errorFonts]
732
- );
733
- const clearErrors = useCallback(() => {
734
- setState((prev) => ({
735
- ...prev,
736
- errorFonts: /* @__PURE__ */ new Map()
737
- }));
738
- }, []);
739
- return {
740
- // State
741
- loadedFonts: state.loadedFonts,
742
- loadingFonts: state.loadingFonts,
743
- errorFonts: state.errorFonts,
744
- // Actions
745
- loadFont: loadFont2,
746
- loadMultipleFonts: loadMultipleFonts2,
747
- isFontReady,
748
- areFontsReady,
749
- getFontFamily,
750
- getFontError,
751
- clearErrors
752
- };
753
- };
754
- var useFont = (fontFamily2, options = {}) => {
755
- const { loadFont: loadFont2, isFontReady, getFontFamily, getFontError, ...rest } = useFontLoader(options);
756
- const [isLoaded, setIsLoaded] = useState(false);
757
- const [error, setError] = useState(null);
758
- const initialFontFamily = getFontFamily(fontFamily2, options) || `"${fontFamily2}", sans-serif`;
759
- const [fontFamilyValue, setFontFamilyValue] = useState(initialFontFamily);
760
- useEffect(() => {
761
- const loadFontAsync = async () => {
762
- try {
763
- const cssValue = await loadFont2(fontFamily2, options);
764
- setFontFamilyValue(cssValue);
765
- setIsLoaded(true);
766
- setError(null);
767
- } catch (err) {
768
- setError(err instanceof Error ? err : new Error(String(err)));
769
- setIsLoaded(false);
770
- }
771
- };
772
- if (!isFontReady(fontFamily2, options)) {
773
- loadFontAsync();
774
- } else {
775
- const cachedValue = getFontFamily(fontFamily2, options);
776
- if (cachedValue) {
777
- setFontFamilyValue(cachedValue);
778
- }
779
- setIsLoaded(true);
780
- }
781
- }, [fontFamily2, loadFont2, isFontReady, getFontFamily, options]);
782
- return {
783
- isLoaded,
784
- error,
785
- isReady: isFontReady(fontFamily2, options),
786
- fontFamily: fontFamilyValue,
787
- ...rest
788
- };
789
- };
790
-
791
- // src/components/atoms/TextAtom.tsx
792
- var Atom3 = ({ data }) => {
793
- const [isFontLoading, setIsFontLoading] = useState2(false);
794
- const { isLoaded, error, isReady, fontFamily: fontFamily2 } = useFont(
795
- data.font?.family || "Inter",
796
- {
797
- weights: data.font?.weights || ["400"],
798
- subsets: data.font?.subsets || ["latin"],
799
- display: data.font?.display || "swap",
800
- preload: data.font?.preload !== false
801
- }
802
- );
803
- useEffect2(() => {
804
- if (data.font?.family) {
805
- setIsFontLoading(true);
806
- if (isReady || isLoaded) {
807
- setIsFontLoading(false);
808
- }
809
- }
810
- }, [data.font, isReady, isLoaded]);
811
- const enhancedStyle = {
812
- fontFamily: fontFamily2,
813
- opacity: isFontLoading ? 0.8 : 1,
814
- // Slight opacity during loading
815
- transition: "opacity 0.2s ease-in-out",
816
- ...data.style
817
- };
818
- if (error) {
819
- console.warn(`Font loading error for ${data.font?.family}:`, error);
820
- }
821
- return /* @__PURE__ */ React9.createElement(
822
- "div",
823
- {
824
- style: enhancedStyle,
825
- className: data.className,
826
- "data-font-loading": isFontLoading,
827
- "data-font-loaded": isReady || isLoaded
828
- },
829
- data.text
830
- );
831
- };
832
- var config4 = {
833
- displayName: "TextAtom",
834
- type: "atom",
835
- isInnerSequence: false
836
- };
837
-
838
- // src/components/atoms/VideoAtom.tsx
839
- import React10, { useMemo as useMemo2 } from "react";
840
- import { staticFile as staticFile2, Video, useCurrentFrame as useCurrentFrame2, useVideoConfig as useVideoConfig2 } from "remotion";
841
- import { z } from "zod";
842
- var VideoAtomDataProps = z.object({
843
- src: z.string(),
844
- // Video source URL
845
- style: z.record(z.any()).optional(),
846
- // CSS styles object
847
- className: z.string().optional(),
848
- // CSS class names
849
- startFrom: z.number().optional(),
850
- // Start playback from this time (seconds)
851
- endAt: z.number().optional(),
852
- // End playback at this time (seconds)
853
- playbackRate: z.number().optional(),
854
- // Playback speed multiplier
855
- volume: z.number().optional(),
856
- // Volume level (0-1)
857
- muted: z.boolean().optional(),
858
- // Mute video audio
859
- loop: z.boolean().optional(),
860
- // Whether to loop the video
861
- fit: z.enum(["contain", "cover", "fill", "none", "scale-down"]).optional()
862
- // Object fit style
863
- });
864
- var Atom4 = ({ data }) => {
865
- const { fps } = useVideoConfig2();
866
- const frame = useCurrentFrame2();
867
- const source = useMemo2(() => {
868
- if (data.src.startsWith("http")) {
869
- return data.src;
870
- }
871
- return staticFile2(data.src);
872
- }, [data.src]);
873
- const trimBefore = useMemo2(() => {
874
- return data.startFrom ? data.startFrom * fps : void 0;
875
- }, [data.startFrom, fps]);
876
- const trimAfter = useMemo2(() => {
877
- return data.endAt ? data.endAt * fps : void 0;
878
- }, [data.endAt, fps]);
879
- const combinedStyle = useMemo2(() => {
880
- const baseStyle = data.style || {};
881
- const objectFit = data.fit ? { objectFit: data.fit } : {};
882
- return { ...baseStyle, ...objectFit };
883
- }, [data.style, data.fit]);
884
- return (
885
- // @ts-ignore
886
- /* @__PURE__ */ React10.createElement(
887
- Video,
888
- {
889
- className: data.className,
890
- src: source,
891
- style: combinedStyle,
892
- trimBefore,
893
- trimAfter,
894
- playbackRate: data.playbackRate,
895
- volume: data.volume,
896
- muted: data.muted,
897
- loop: data.loop
898
- }
899
- )
900
- );
901
- };
902
- var config5 = {
903
- displayName: "VideoAtom",
904
- type: "atom",
905
- isInnerSequence: false
906
- };
907
-
908
- // src/components/atoms/AudioAtom.tsx
909
- import React11, { useMemo as useMemo3 } from "react";
910
- import { Audio, staticFile as staticFile3, useCurrentFrame as useCurrentFrame3, useVideoConfig as useVideoConfig3 } from "remotion";
911
- import { z as z2 } from "zod";
912
- var AudioAtomMutedRangeProps = z2.object({
913
- type: z2.literal("range"),
914
- values: z2.array(z2.object({
915
- start: z2.number(),
916
- // Start time in seconds
917
- end: z2.number()
918
- // End time in seconds
919
- }))
920
- });
921
- var AudioAtomMutedFullProps = z2.object({
922
- type: z2.literal("full"),
923
- value: z2.boolean()
924
- // true = muted, false = unmuted
925
- });
926
- var AudioAtomDataProps = z2.object({
927
- src: z2.string(),
928
- // Audio source URL
929
- startFrom: z2.number().optional(),
930
- // Start playback from this time (seconds)
931
- endAt: z2.number().optional(),
932
- // End playback at this time (seconds)
933
- volume: z2.number().optional(),
934
- // Volume level (0-1)
935
- playbackRate: z2.number().optional(),
936
- // Playback speed multiplier
937
- muted: z2.union([AudioAtomMutedFullProps, AudioAtomMutedRangeProps]).optional()
938
- // Mute configuration
939
- });
940
- var Atom5 = ({ data }) => {
941
- const { fps } = useVideoConfig3();
942
- const { muted } = data;
943
- const frame = useCurrentFrame3();
944
- const isMuted = useMemo3(() => {
945
- if (muted?.type === "full") {
946
- return muted.value;
947
- }
948
- if (muted?.type === "range") {
949
- return muted?.values.some(
950
- (value) => frame >= value.start * fps && frame <= value.end * fps
951
- );
952
- }
953
- return false;
954
- }, [muted, frame, fps]);
955
- const source = useMemo3(() => {
956
- if (data.src.startsWith("http")) {
957
- return data.src;
958
- }
959
- return staticFile3(data.src);
960
- }, [data.src]);
961
- return (
962
- // @ts-ignore
963
- /* @__PURE__ */ React11.createElement(
964
- Audio,
965
- {
966
- src: source,
967
- trimBefore: data.startFrom ? data.startFrom * fps : void 0,
968
- trimAfter: data.endAt ? data.endAt * fps : void 0,
969
- volume: data.volume,
970
- playbackRate: data.playbackRate,
971
- muted: isMuted
972
- }
973
- )
974
- );
975
- };
976
- var config6 = {
977
- displayName: "AudioAtom",
978
- type: "atom",
979
- isInnerSequence: false
980
- };
981
-
982
- // src/components/atoms/TextAtomWithFonts.tsx
983
- import React12, { useEffect as useEffect3, useState as useState3 } from "react";
984
- var Atom6 = ({ data }) => {
985
- const [isFontLoading, setIsFontLoading] = useState3(false);
986
- const { isLoaded, error, isReady, fontFamily: fontFamily2 } = useFont(
987
- data.font?.family || "Inter",
988
- {
989
- weights: data.font?.weights || ["400"],
990
- subsets: data.font?.subsets || ["latin"],
991
- display: data.font?.display || "swap",
992
- preload: data.font?.preload !== false,
993
- onLoad: (family, cssValue) => {
994
- console.log(`Font ${family} loaded successfully with CSS value: ${cssValue}`);
995
- setIsFontLoading(false);
996
- },
997
- onError: (family, error2) => {
998
- console.warn(`Font ${family} failed to load:`, error2);
999
- setIsFontLoading(false);
1000
- }
1001
- }
1002
- );
1003
- useEffect3(() => {
1004
- if (data.font?.family) {
1005
- if (isReady || isLoaded) {
1006
- setIsFontLoading(false);
1007
- } else if (!isReady && !isLoaded && !error) {
1008
- setIsFontLoading(true);
1009
- }
1010
- }
1011
- }, [data.font, isReady, isLoaded, error]);
1012
- const enhancedStyle = {
1013
- fontFamily: fontFamily2,
1014
- opacity: isFontLoading ? 0.8 : 1,
1015
- transition: "opacity 0.3s ease-in-out, font-family 0.2s ease-in-out",
1016
- ...data.style
1017
- };
1018
- if (isFontLoading && data.loadingState?.showLoadingIndicator) {
1019
- return /* @__PURE__ */ React12.createElement("div", { style: enhancedStyle, className: data.className }, /* @__PURE__ */ React12.createElement("span", { style: data.loadingState.loadingStyle }, data.loadingState.loadingText || "Loading..."));
1020
- }
1021
- if (error && data.errorState?.showErrorIndicator) {
1022
- return /* @__PURE__ */ React12.createElement("div", { style: enhancedStyle, className: data.className }, /* @__PURE__ */ React12.createElement("span", { style: data.errorState.errorStyle }, data.errorState.errorText || data.text));
1023
- }
1024
- return /* @__PURE__ */ React12.createElement(
1025
- "div",
1026
- {
1027
- style: enhancedStyle,
1028
- className: data.className,
1029
- "data-font-loading": isFontLoading,
1030
- "data-font-loaded": isReady || isLoaded,
1031
- "data-font-error": !!error,
1032
- "data-font-family": data.font?.family || "system"
1033
- },
1034
- data.text
1035
- );
1036
- };
1037
- var config7 = {
1038
- displayName: "TextAtomWithFonts",
1039
- type: "atom",
1040
- isInnerSequence: false
1041
- };
1042
-
1043
- // src/components/atoms/index.ts
1044
- registerComponent(
1045
- config2.displayName,
1046
- Atom,
1047
- "atom",
1048
- config2
1049
- );
1050
- registerComponent(
1051
- config3.displayName,
1052
- Atom2,
1053
- "atom",
1054
- config3
1055
- );
1056
- registerComponent(config4.displayName, Atom3, "atom", config4);
1057
- registerComponent(
1058
- config5.displayName,
1059
- Atom4,
1060
- "atom",
1061
- config5
1062
- );
1063
- registerComponent(
1064
- config6.displayName,
1065
- Atom5,
1066
- "atom",
1067
- config6
1068
- );
1069
- registerComponent(
1070
- config7.displayName,
1071
- Atom6,
1072
- "atom",
1073
- config7
1074
- );
1075
-
1076
- // src/components/effects/BlurEffect.tsx
1077
- import React13 from "react";
1078
- var BlurEffect = ({
1079
- data,
1080
- children
1081
- }) => {
1082
- const blurAmount = data?.blur || 5;
1083
- return /* @__PURE__ */ React13.createElement("div", { style: {
1084
- filter: `blur(${blurAmount}px)`,
1085
- width: "100%",
1086
- height: "100%"
1087
- } }, children);
1088
- };
1089
- var config8 = {
1090
- displayName: "blur",
1091
- description: "Applies a blur effect to its children",
1092
- category: "effects",
1093
- props: {
1094
- blur: {
1095
- type: "number",
1096
- description: "Blur amount in pixels",
1097
- default: 5
1098
- }
1099
- }
1100
- };
1101
-
1102
- // src/components/effects/Loop.tsx
1103
- import React14 from "react";
1104
- import { Loop } from "remotion";
1105
- var LoopEffect = ({
1106
- data,
1107
- children,
1108
- context
1109
- }) => {
1110
- const { timing } = context ?? {};
1111
- const loopData = data;
1112
- const durationInFrames = loopData?.durationInFrames || timing?.durationInFrames || 50;
1113
- const times = loopData?.times ?? Infinity;
1114
- const layout = loopData?.layout || "absolute-fill";
1115
- return (
1116
- // @ts-ignore
1117
- /* @__PURE__ */ React14.createElement(
1118
- Loop,
1119
- {
1120
- durationInFrames,
1121
- times,
1122
- layout
1123
- },
1124
- /* @__PURE__ */ React14.createElement(React14.Fragment, null, children)
1125
- )
1126
- );
1127
- };
1128
- var config9 = {
1129
- displayName: "loop",
1130
- type: "layout",
1131
- isInnerSequence: false,
1132
- props: {
1133
- durationInFrames: {
1134
- type: "number",
1135
- description: "How many frames one iteration of the loop should be long",
1136
- default: 50
1137
- },
1138
- times: {
1139
- type: "number",
1140
- description: "How many times to loop the content (defaults to Infinity)",
1141
- default: void 0
1142
- },
1143
- layout: {
1144
- type: "string",
1145
- description: 'Either "absolute-fill" (default) or "none"',
1146
- default: "absolute-fill"
1147
- }
1148
- }
1149
- };
1150
-
1151
- // src/components/effects/Pan.tsx
1152
- import React15, { useMemo as useMemo4 } from "react";
1153
- import { useCurrentFrame as useCurrentFrame4, useVideoConfig as useVideoConfig4, interpolate as interpolate2, spring, Easing as Easing2 } from "remotion";
1154
- var parseDuration = (duration, contextDuration, fps) => {
1155
- if (!duration) return contextDuration;
1156
- if (typeof duration === "number") {
1157
- return duration * fps;
1158
- }
1159
- if (typeof duration === "string" && duration.endsWith("%")) {
1160
- const percentage = parseFloat(duration.replace("%", "")) / 100;
1161
- return Math.floor(contextDuration * percentage);
1162
- }
1163
- return contextDuration;
1164
- };
1165
- var parseDelay = (delay, contextDuration, fps) => {
1166
- if (!delay) return 0;
1167
- if (typeof delay === "number") {
1168
- return delay * fps;
1169
- }
1170
- if (typeof delay === "string" && delay.endsWith("%")) {
1171
- const percentage = parseFloat(delay) / 100;
1172
- return Math.floor(contextDuration * percentage);
1173
- }
1174
- return 0;
1175
- };
1176
- var getPanDistance = (progress, panDistance) => {
1177
- if (typeof panDistance === "number") {
1178
- return panDistance;
1179
- }
1180
- if (Array.isArray(panDistance)) {
1181
- if (panDistance.length === 0) return 0;
1182
- if (panDistance.length === 1) return panDistance[0][1];
1183
- for (let i = 0; i < panDistance.length - 1; i++) {
1184
- const [currentProgress, currentDistance] = panDistance[i];
1185
- const [nextProgress, nextDistance] = panDistance[i + 1];
1186
- if (progress >= currentProgress && progress <= nextProgress) {
1187
- const localProgress = (progress - currentProgress) / (nextProgress - currentProgress);
1188
- return interpolate2(localProgress, [0, 1], [currentDistance, nextDistance]);
1189
- }
1190
- }
1191
- return panDistance[panDistance.length - 1][1];
1192
- }
1193
- return 0;
1194
- };
1195
- var getPosition = (position) => {
1196
- if (!position) return [0.5, 0.5];
1197
- if (Array.isArray(position)) {
1198
- return position;
1199
- }
1200
- const positions = {
1201
- "top-left": [0, 0],
1202
- "top": [0.5, 0],
1203
- "top-right": [1, 0],
1204
- "left": [0, 0.5],
1205
- "center": [0.5, 0.5],
1206
- "right": [1, 0.5],
1207
- "bottom-left": [0, 1],
1208
- "bottom": [0.5, 1],
1209
- "bottom-right": [1, 1]
1210
- };
1211
- return positions[position] || [0.5, 0.5];
1212
- };
1213
- var getEasingFunction = (animationType) => {
1214
- switch (animationType) {
1215
- case "linear":
1216
- return Easing2.linear;
1217
- case "ease-in":
1218
- return Easing2.in(Easing2.ease);
1219
- case "ease-out":
1220
- return Easing2.out(Easing2.ease);
1221
- case "ease-in-out":
1222
- return Easing2.inOut(Easing2.ease);
1223
- default:
1224
- return Easing2.linear;
1225
- }
1226
- };
1227
- var getPanVector = (direction, distance) => {
1228
- switch (direction) {
1229
- case "left":
1230
- return [-distance, 0];
1231
- case "right":
1232
- return [distance, 0];
1233
- case "up":
1234
- return [0, -distance];
1235
- case "down":
1236
- return [0, distance];
1237
- case "diagonal":
1238
- return [distance * 0.707, distance * 0.707];
1239
- // 45-degree diagonal
1240
- default:
1241
- return [0, 0];
1242
- }
1243
- };
1244
- var PanEffect = ({
1245
- data,
1246
- children,
1247
- context
1248
- }) => {
1249
- const frame = useCurrentFrame4();
1250
- const { fps } = useVideoConfig4();
1251
- const panData = data;
1252
- const { timing } = context ?? {};
1253
- const contextDuration = timing?.durationInFrames || 50;
1254
- const effectTiming = panData?.effectTiming || "start";
1255
- const panDuration = parseDuration(panData?.panDuration, contextDuration, fps);
1256
- const panStartDelay = parseDelay(panData?.panStartDelay, contextDuration, fps);
1257
- const panEndDelay = parseDelay(panData?.panEndDelay, contextDuration, fps);
1258
- const panDirection = panData?.panDirection || "right";
1259
- let panDistance = panData?.panDistance || 100;
1260
- const loopTimes = panData?.loopTimes || 0;
1261
- const panStartPosition = getPosition(panData?.panStartPosition);
1262
- const panEndPosition = getPosition(panData?.panEndPosition);
1263
- const animationType = panData?.animationType || "linear";
1264
- if (loopTimes > 0 && typeof panDistance === "number") {
1265
- const loopedPanDistance = [];
1266
- for (let i = 0; i < loopTimes; i++) {
1267
- const loopProgress = i / loopTimes;
1268
- const nextLoopProgress = (i + 1) / loopTimes;
1269
- loopedPanDistance.push([loopProgress, 0]);
1270
- loopedPanDistance.push([loopProgress + (nextLoopProgress - loopProgress) * 0.5, panDistance]);
1271
- loopedPanDistance.push([nextLoopProgress, 0]);
1272
- }
1273
- panDistance = loopedPanDistance;
1274
- }
1275
- let progress;
1276
- if (animationType === "spring") {
1277
- progress = spring({
1278
- frame,
1279
- fps,
1280
- config: {
1281
- stiffness: 100,
1282
- damping: 10,
1283
- mass: 1
1284
- },
1285
- durationInFrames: panDuration,
1286
- delay: effectTiming === "start" ? panStartDelay : contextDuration - panEndDelay - panDuration
1287
- });
1288
- } else {
1289
- let animationFrame;
1290
- if (effectTiming === "start") {
1291
- animationFrame = frame - panStartDelay;
1292
- } else {
1293
- animationFrame = frame - (contextDuration - panEndDelay - panDuration);
1294
- }
1295
- const easing = getEasingFunction(animationType);
1296
- progress = interpolate2(
1297
- animationFrame,
1298
- [0, panDuration],
1299
- [0, 1],
1300
- {
1301
- easing,
1302
- extrapolateLeft: "clamp",
1303
- extrapolateRight: "clamp"
1304
- }
1305
- );
1306
- }
1307
- let panOffset;
1308
- if (panDirection === "custom") {
1309
- const [startX, startY] = panStartPosition;
1310
- const [endX, endY] = panEndPosition;
1311
- const offsetX = (endX - startX) * 100;
1312
- const offsetY = (endY - startY) * 100;
1313
- panOffset = [
1314
- interpolate2(progress, [0, 1], [0, offsetX]),
1315
- interpolate2(progress, [0, 1], [0, offsetY])
1316
- ];
1317
- } else {
1318
- const distance = getPanDistance(progress, panDistance);
1319
- const [vectorX, vectorY] = getPanVector(panDirection, distance);
1320
- panOffset = [vectorX, vectorY];
1321
- }
1322
- const style = useMemo4(() => {
1323
- return {
1324
- width: "100%",
1325
- height: "100%",
1326
- transform: `translate(${panOffset[0]}px, ${panOffset[1]}px)`
1327
- };
1328
- }, [panOffset]);
1329
- return /* @__PURE__ */ React15.createElement("div", { style }, children);
1330
- };
1331
- var config10 = {
1332
- displayName: "pan",
1333
- type: "layout",
1334
- isInnerSequence: false,
1335
- props: {
1336
- effectTiming: {
1337
- type: "string",
1338
- description: 'When the pan effect should occur: "start" or "end"',
1339
- default: "start"
1340
- },
1341
- panDuration: {
1342
- type: "string",
1343
- description: 'Duration of the pan animation in seconds or percentage (e.g., "2" or "50%")',
1344
- default: void 0
1345
- },
1346
- panStart: {
1347
- type: "number",
1348
- description: "Start time of pan in seconds",
1349
- default: 0
1350
- },
1351
- panEnd: {
1352
- type: "number",
1353
- description: "End time of pan in seconds",
1354
- default: void 0
1355
- },
1356
- panStartDelay: {
1357
- type: "string",
1358
- description: "Delay before pan starts in seconds or percentage",
1359
- default: 0
1360
- },
1361
- panEndDelay: {
1362
- type: "string",
1363
- description: "Delay before video ends in seconds or percentage",
1364
- default: 0
1365
- },
1366
- panDirection: {
1367
- type: "string",
1368
- description: 'Direction of pan: "left", "right", "up", "down", "diagonal", or "custom"',
1369
- default: "right"
1370
- },
1371
- panDistance: {
1372
- type: "string",
1373
- description: "Pan distance in pixels or array of [progress, distance] pairs",
1374
- default: 100
1375
- },
1376
- panStartPosition: {
1377
- type: "string",
1378
- description: "Starting position: [x, y] coordinates or position string (top-left, center, etc.)",
1379
- default: "center"
1380
- },
1381
- panEndPosition: {
1382
- type: "string",
1383
- description: "Ending position: [x, y] coordinates or position string (top-left, center, etc.)",
1384
- default: "center"
1385
- },
1386
- animationType: {
1387
- type: "string",
1388
- description: 'Animation curve: "linear", "spring", "ease-in", "ease-out", "ease-in-out"',
1389
- default: "linear"
1390
- }
1391
- }
1392
- };
1393
-
1394
- // src/components/effects/Zoom.tsx
1395
- import React16, { useMemo as useMemo5 } from "react";
1396
- import { useCurrentFrame as useCurrentFrame5, useVideoConfig as useVideoConfig5, interpolate as interpolate3, spring as spring2, Easing as Easing3 } from "remotion";
1397
- var parseDuration2 = (duration, contextDuration, fps) => {
1398
- if (!duration) return contextDuration;
1399
- if (typeof duration === "number") {
1400
- return duration * fps;
1401
- }
1402
- if (typeof duration === "string" && duration.endsWith("%")) {
1403
- const percentage = parseFloat(duration.replace("%", "")) / 100;
1404
- return Math.floor(contextDuration * percentage);
1405
- }
1406
- return contextDuration;
1407
- };
1408
- var parseDelay2 = (delay, contextDuration, fps) => {
1409
- if (!delay) return 0;
1410
- if (typeof delay === "number") {
1411
- return delay * fps;
1412
- }
1413
- if (typeof delay === "string" && delay.endsWith("%")) {
1414
- const percentage = parseFloat(delay) / 100;
1415
- return Math.floor(contextDuration * percentage);
1416
- }
1417
- return 0;
1418
- };
1419
- var getZoomScale = (progress, zoomDepth) => {
1420
- if (typeof zoomDepth === "number") {
1421
- return zoomDepth;
1422
- }
1423
- if (Array.isArray(zoomDepth)) {
1424
- if (zoomDepth.length === 0) return 1;
1425
- if (zoomDepth.length === 1) return zoomDepth[0][1];
1426
- for (let i = 0; i < zoomDepth.length - 1; i++) {
1427
- const [currentProgress, currentScale] = zoomDepth[i];
1428
- const [nextProgress, nextScale] = zoomDepth[i + 1];
1429
- if (progress >= currentProgress && progress <= nextProgress) {
1430
- const localProgress = (progress - currentProgress) / (nextProgress - currentProgress);
1431
- return interpolate3(localProgress, [0, 1], [currentScale, nextScale]);
1432
- }
1433
- }
1434
- return zoomDepth[zoomDepth.length - 1][1];
1435
- }
1436
- return 1;
1437
- };
1438
- var getZoomPosition = (position) => {
1439
- if (!position) return [0.5, 0.5];
1440
- if (Array.isArray(position)) {
1441
- return position;
1442
- }
1443
- const positions = {
1444
- "top-left": [0, 0],
1445
- "top": [0.5, 0],
1446
- "top-right": [1, 0],
1447
- "left": [0, 0.5],
1448
- "center": [0.5, 0.5],
1449
- "right": [1, 0.5],
1450
- "bottom-left": [0, 1],
1451
- "bottom": [0.5, 1],
1452
- "bottom-right": [1, 1]
1453
- };
1454
- return positions[position] || [0.5, 0.5];
1455
- };
1456
- var getEasingFunction2 = (animationType) => {
1457
- switch (animationType) {
1458
- case "linear":
1459
- return Easing3.linear;
1460
- case "ease-in":
1461
- return Easing3.in(Easing3.ease);
1462
- case "ease-out":
1463
- return Easing3.out(Easing3.ease);
1464
- case "ease-in-out":
1465
- return Easing3.inOut(Easing3.ease);
1466
- default:
1467
- return Easing3.linear;
1468
- }
1469
- };
1470
- var ZoomEffect = ({
1471
- data,
1472
- children,
1473
- context
1474
- }) => {
1475
- const frame = useCurrentFrame5();
1476
- const { fps } = useVideoConfig5();
1477
- const zoomData = data;
1478
- const { timing } = context ?? {};
1479
- const contextDuration = timing?.durationInFrames || 50;
1480
- console.log(contextDuration);
1481
- const effectTiming = zoomData?.effectTiming || "start";
1482
- const zoomDuration = parseDuration2(zoomData?.zoomDuration, contextDuration, fps);
1483
- const zoomStartDelay = parseDelay2(zoomData?.zoomStartDelay, contextDuration, fps);
1484
- const zoomEndDelay = parseDelay2(zoomData?.zoomEndDelay, contextDuration, fps);
1485
- const zoomDirection = zoomData?.zoomDirection || "in";
1486
- let zoomDepth = zoomData?.zoomDepth || 1.5;
1487
- const loopTimes = zoomData?.loopTimes || 0;
1488
- if (loopTimes > 1 && Array.isArray(zoomDepth)) {
1489
- const loopedZoomDepth = [];
1490
- for (let i = 0; i < loopTimes; i++) {
1491
- const loopProgress = i / loopTimes;
1492
- const nextLoopProgress = (i + 1) / loopTimes;
1493
- zoomDepth.forEach(([x, y]) => {
1494
- const mappedX = loopProgress + x * (nextLoopProgress - loopProgress);
1495
- loopedZoomDepth.push([mappedX, y]);
1496
- });
1497
- }
1498
- zoomDepth = loopedZoomDepth;
1499
- } else if (loopTimes > 0 && typeof zoomDepth === "number") {
1500
- const loopedZoomDepth = [];
1501
- for (let i = 0; i < loopTimes; i++) {
1502
- const loopProgress = i / loopTimes;
1503
- const nextLoopProgress = (i + 1) / loopTimes;
1504
- loopedZoomDepth.push([loopProgress, 1]);
1505
- loopedZoomDepth.push([loopProgress + (nextLoopProgress - loopProgress) * 0.5, zoomDepth]);
1506
- loopedZoomDepth.push([nextLoopProgress, 1]);
1507
- }
1508
- zoomDepth = loopedZoomDepth;
1509
- }
1510
- const zoomPosition = getZoomPosition(zoomData?.zoomPosition);
1511
- const animationType = zoomData?.animationType || "linear";
1512
- let progress;
1513
- if (animationType === "spring") {
1514
- progress = spring2({
1515
- frame,
1516
- fps,
1517
- config: {
1518
- stiffness: 100,
1519
- damping: 10,
1520
- mass: 1
1521
- },
1522
- durationInFrames: zoomDuration,
1523
- delay: effectTiming === "start" ? zoomStartDelay : contextDuration - zoomEndDelay - zoomDuration
1524
- });
1525
- } else {
1526
- let animationFrame;
1527
- if (effectTiming === "start") {
1528
- animationFrame = frame - zoomStartDelay;
1529
- } else {
1530
- animationFrame = frame - (contextDuration - zoomEndDelay - zoomDuration);
1531
- }
1532
- const easing = getEasingFunction2(animationType);
1533
- progress = interpolate3(
1534
- animationFrame,
1535
- [0, zoomDuration],
1536
- [0, 1],
1537
- {
1538
- easing,
1539
- extrapolateLeft: "clamp",
1540
- extrapolateRight: "clamp"
1541
- }
1542
- );
1543
- }
1544
- let scale;
1545
- if (typeof zoomDepth === "number") {
1546
- const baseScale = zoomDirection === "in" ? 1 : zoomDepth;
1547
- const targetScale = zoomDirection === "in" ? zoomDepth : 1;
1548
- scale = interpolate3(progress, [0, 1], [baseScale, targetScale]);
1549
- } else if (Array.isArray(zoomDepth)) {
1550
- scale = getZoomScale(progress, zoomDepth);
1551
- } else {
1552
- const baseScale = zoomDirection === "in" ? 1 : 1.5;
1553
- const targetScale = zoomDirection === "in" ? 1.5 : 1;
1554
- scale = interpolate3(progress, [0, 1], [baseScale, targetScale]);
1555
- }
1556
- const [originX, originY] = zoomPosition;
1557
- const transformOrigin = `${originX * 100}% ${originY * 100}%`;
1558
- const style = useMemo5(() => {
1559
- return {
1560
- width: "100%",
1561
- height: "100%",
1562
- transform: `scale(${scale})`,
1563
- transformOrigin
1564
- };
1565
- }, [scale, transformOrigin]);
1566
- return /* @__PURE__ */ React16.createElement("div", { style }, children);
1567
- };
1568
- var config11 = {
1569
- displayName: "zoom",
1570
- type: "layout",
1571
- isInnerSequence: false,
1572
- props: {
1573
- effectTiming: {
1574
- type: "string",
1575
- description: 'When the zoom effect should occur: "start" or "end"',
1576
- default: "start"
1577
- },
1578
- zoomDuration: {
1579
- type: "string",
1580
- description: 'Duration of the zoom animation in seconds or percentage (e.g., "2" or "50%")',
1581
- default: void 0
1582
- },
1583
- zoomStart: {
1584
- type: "number",
1585
- description: "Start time of zoom in seconds",
1586
- default: 0
1587
- },
1588
- zoomEnd: {
1589
- type: "number",
1590
- description: "End time of zoom in seconds",
1591
- default: void 0
1592
- },
1593
- zoomStartDelay: {
1594
- type: "string",
1595
- description: "Delay before zoom starts in seconds or percentage",
1596
- default: 0
1597
- },
1598
- zoomEndDelay: {
1599
- type: "string",
1600
- description: "Delay before video ends in seconds or percentage",
1601
- default: 0
1602
- },
1603
- zoomDirection: {
1604
- type: "string",
1605
- description: 'Direction of zoom: "in" or "out"',
1606
- default: "in"
1607
- },
1608
- zoomDepth: {
1609
- type: "string",
1610
- description: "Zoom scale factor or array of [progress, scale] pairs",
1611
- default: 1.5
1612
- },
1613
- zoomPosition: {
1614
- type: "string",
1615
- description: "Zoom anchor point: [x, y] coordinates or position string (top-left, center, etc.)",
1616
- default: "center"
1617
- },
1618
- animationType: {
1619
- type: "string",
1620
- description: 'Animation curve: "linear", "spring", "ease-in", "ease-out", "ease-in-out"',
1621
- default: "linear"
1622
- }
1623
- }
1624
- };
1625
-
1626
- // src/components/effects/index.ts
1627
- registerEffect(config8.displayName, BlurEffect, config8);
1628
- registerEffect(config9.displayName, LoopEffect, config9);
1629
- registerEffect(config10.displayName, PanEffect, config10);
1630
- registerEffect(config11.displayName, ZoomEffect, config11);
1631
-
1632
- // src/hooks/useComponentRegistry.ts
1633
- import { useMemo as useMemo6 } from "react";
1634
- var useComponentRegistry = () => {
1635
- return useMemo6(() => {
1636
- return {
1637
- registerComponent: componentRegistry.registerComponent.bind(componentRegistry),
1638
- registerPackage: componentRegistry.registerPackage.bind(componentRegistry),
1639
- getComponent: componentRegistry.getComponent.bind(componentRegistry),
1640
- getAllComponents: componentRegistry.getAllComponents.bind(componentRegistry)
1641
- };
1642
- }, []);
1643
- };
1644
-
1645
- // src/hooks/useBoundaryCalculation.ts
1646
- import { useMemo as useMemo7 } from "react";
1647
- var useBoundaryCalculation = ({
1648
- parentBoundaries,
1649
- constraints,
1650
- layout
1651
- }) => {
1652
- return useMemo7(() => {
1653
- const { x, y, width, height } = parentBoundaries;
1654
- const calculatedX = typeof constraints.x === "number" ? constraints.x : x;
1655
- const calculatedY = typeof constraints.y === "number" ? constraints.y : y;
1656
- const calculatedWidth = typeof constraints.width === "number" ? constraints.width : width;
1657
- const calculatedHeight = typeof constraints.height === "number" ? constraints.height : height;
1658
- return {
1659
- x: calculatedX,
1660
- y: calculatedY,
1661
- width: calculatedWidth,
1662
- height: calculatedHeight,
1663
- zIndex: constraints.zIndex || 0
1664
- };
1665
- }, [parentBoundaries, constraints, layout]);
1666
- };
1667
-
1668
- // src/hooks/buildTransitionHook.ts
1669
- import { useContext as useContext4 } from "react";
1670
-
1671
- // src/core/types/transition.types.ts
1672
- import { createContext as createContext3, useContext as useContext3 } from "react";
1673
- var LayoutContext = createContext3(null);
1674
-
1675
- // src/hooks/buildTransitionHook.ts
1676
- function buildLayoutHook(schema, defaultValue) {
1677
- return () => {
1678
- const context = useContext4(LayoutContext);
1679
- if (!context) {
1680
- return defaultValue;
1681
- }
1682
- try {
1683
- const validatedData = schema.parse(context);
1684
- return validatedData;
1685
- } catch (error) {
1686
- console.warn("Transition data validation failed, using defaults:", error);
1687
- return defaultValue;
1688
- }
1689
- };
1690
- }
1691
-
1692
- // src/utils/contextUtils.ts
1693
- var createRootContext = (width, height, duration, fps) => {
1694
- return {
1695
- boundaries: {
1696
- left: 0,
1697
- top: 0,
1698
- width,
1699
- height,
1700
- zIndex: 0
1701
- },
1702
- timing: {
1703
- startInFrames: 0,
1704
- durationInFrames: duration
1705
- },
1706
- hierarchy: {
1707
- depth: 0,
1708
- parentIds: []
1709
- }
1710
- };
1711
- };
1712
- var mergeContexts = (parent, child) => {
1713
- return {
1714
- boundaries: {
1715
- ...parent.boundaries,
1716
- ...child.boundaries
1717
- },
1718
- timing: { ...parent.timing, ...child.timing },
1719
- hierarchy: {
1720
- depth: (parent.hierarchy?.depth || 0) + 1,
1721
- parentIds: [...parent.hierarchy?.parentIds || [], "root"]
1722
- }
1723
- };
1724
- };
1725
-
1726
- // src/utils/boundaryUtils.ts
1727
- var calculateGridPosition = (index, columns, cellWidth, cellHeight, spacing) => {
1728
- const row = Math.floor(index / columns);
1729
- const col = index % columns;
1730
- return {
1731
- x: col * (cellWidth + spacing),
1732
- y: row * (cellHeight + spacing),
1733
- width: cellWidth,
1734
- height: cellHeight
1735
- };
1736
- };
1737
- var calculateCircularPosition = (index, total, radius, centerX, centerY) => {
1738
- const angle = index / total * 2 * Math.PI;
1739
- return {
1740
- x: centerX + radius * Math.cos(angle),
1741
- y: centerY + radius * Math.sin(angle)
1742
- };
1743
- };
1744
-
1745
- // src/templates/rings/NextjsLogo.tsx
1746
- import { evolvePath } from "@remotion/paths";
1747
- import React19, { useMemo as useMemo8 } from "react";
1748
- import { interpolate as interpolate4, spring as spring4, useCurrentFrame as useCurrentFrame7, useVideoConfig as useVideoConfig7 } from "remotion";
1749
-
1750
- // src/templates/rings/RippleOutLayout.tsx
1751
- import React18 from "react";
1752
- import { spring as spring3, useCurrentFrame as useCurrentFrame6, useVideoConfig as useVideoConfig6, Sequence as Sequence2, AbsoluteFill as AbsoluteFill4 } from "remotion";
1753
- import { z as z3 } from "zod";
1754
- import { loadFont } from "@remotion/google-fonts/Inter";
1755
- loadFont("normal", {
1756
- subsets: ["latin"],
1757
- weights: ["400", "700"]
1758
- });
1759
- var RippleOutTransitionSchema = z3.object({
1760
- progress: z3.number().min(0).max(1),
1761
- logoOut: z3.number().min(0).max(1)
1762
- });
1763
- var defaultRippleOutData = {
1764
- progress: 0,
1765
- logoOut: 0
1766
- };
1767
- var useRippleOutLayout = buildLayoutHook(
1768
- RippleOutTransitionSchema,
1769
- defaultRippleOutData
1770
- );
1771
- var container = {
1772
- backgroundColor: "white"
1773
- };
1774
- var RippleOutLayout = ({ data, context, children }) => {
1775
- const {
1776
- transitionStart,
1777
- transitionDuration
1778
- } = data || { transitionStart: 2, transitionDuration: 1 };
1779
- const frame = useCurrentFrame6();
1780
- const { fps } = useVideoConfig6();
1781
- const { hierarchy } = useRenderContext();
1782
- const transitionStartFrame = transitionStart * fps;
1783
- const transitionDurationFrames = transitionDuration * fps;
1784
- const logoOut = spring3({
1785
- fps,
1786
- frame,
1787
- config: {
1788
- damping: 200
1789
- },
1790
- durationInFrames: transitionDurationFrames,
1791
- delay: transitionStartFrame
1792
- });
1793
- const transitionData = {
1794
- progress: logoOut,
1795
- logoOut
1796
- };
1797
- const childrenArray = React18.Children.toArray(children).filter(
1798
- (child) => React18.isValidElement(child)
1799
- );
1800
- const [from, to] = childrenArray;
1801
- return /* @__PURE__ */ React18.createElement(LayoutContext.Provider, { value: transitionData }, /* @__PURE__ */ React18.createElement(AbsoluteFill4, { style: {
1802
- ...container,
1803
- ...context?.boundaries
1804
- } }, /* @__PURE__ */ React18.createElement(Sequence2, { name: from.props.componentId + " - " + from.props.id, from: 0, durationInFrames: transitionStartFrame + transitionDurationFrames }, from), /* @__PURE__ */ React18.createElement(Sequence2, { name: to.props.componentId + " - " + to.props.id, from: transitionStartFrame + transitionDurationFrames / 2 }, to)));
1805
- };
1806
- var rippleOutLayoutConfig = {
1807
- displayName: "RippleOutLayout",
1808
- type: "layout",
1809
- isInnerSequence: true
1810
- };
1811
-
1812
- // src/templates/rings/NextjsLogo.tsx
1813
- var mask = {
1814
- maskType: "alpha"
1815
- };
1816
- 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";
1817
- var NextjsLogo = () => {
1818
- const { logoOut } = useRippleOutLayout();
1819
- const outProgress = logoOut;
1820
- const { fps } = useVideoConfig7();
1821
- const frame = useCurrentFrame7();
1822
- const evolve1 = spring4({
1823
- fps,
1824
- frame,
1825
- config: {
1826
- damping: 200
1827
- }
1828
- });
1829
- const evolve2 = spring4({
1830
- fps,
1831
- frame: frame - 15,
1832
- config: {
1833
- damping: 200
1834
- }
1835
- });
1836
- const evolve3 = spring4({
1837
- fps,
1838
- frame: frame - 30,
1839
- config: {
1840
- damping: 200,
1841
- mass: 3
1842
- },
1843
- durationInFrames: 30
1844
- });
1845
- const style = useMemo8(() => {
1846
- return {
1847
- height: 140,
1848
- borderRadius: 70,
1849
- scale: String(1 - outProgress)
1850
- };
1851
- }, [outProgress]);
1852
- const firstPath = `M 60.0568 54 v 71.97`;
1853
- const secondPath = `M 63.47956 56.17496 L 144.7535 161.1825`;
1854
- const thirdPath = `M 121 54 L 121 126`;
1855
- const evolution1 = evolvePath(evolve1, firstPath);
1856
- const evolution2 = evolvePath(evolve2, secondPath);
1857
- const evolution3 = evolvePath(
1858
- interpolate4(evolve3, [0, 1], [0, 0.7]),
1859
- thirdPath
1860
- );
1861
- return /* @__PURE__ */ React19.createElement("svg", { style, fill: "none", viewBox: "0 0 180 180" }, /* @__PURE__ */ React19.createElement("mask", { height: "180", id: "mask", style: mask, width: "180", x: "0", y: "0" }, /* @__PURE__ */ React19.createElement("circle", { cx: "90", cy: "90", fill: "black", r: "90" })), /* @__PURE__ */ React19.createElement("mask", { id: "n-mask", style: mask }, /* @__PURE__ */ React19.createElement("path", { d: nStroke, fill: "black" })), /* @__PURE__ */ React19.createElement("g", { mask: "url(#mask)" }, /* @__PURE__ */ React19.createElement("circle", { cx: "90", cy: "90", fill: "black", r: "90" }), /* @__PURE__ */ React19.createElement("g", { stroke: "url(#gradient0)", mask: "url(#n-mask)" }, /* @__PURE__ */ React19.createElement(
1862
- "path",
1863
- {
1864
- strokeWidth: "12.1136",
1865
- d: firstPath,
1866
- strokeDasharray: evolution1.strokeDasharray,
1867
- strokeDashoffset: evolution1.strokeDashoffset
1868
- }
1869
- ), /* @__PURE__ */ React19.createElement(
1870
- "path",
1871
- {
1872
- strokeWidth: 12.1136,
1873
- d: secondPath,
1874
- strokeDasharray: evolution2.strokeDasharray,
1875
- strokeDashoffset: evolution2.strokeDashoffset
1876
- }
1877
- )), /* @__PURE__ */ React19.createElement(
1878
- "path",
1879
- {
1880
- stroke: "url(#gradient1)",
1881
- d: thirdPath,
1882
- strokeDasharray: evolution3.strokeDasharray,
1883
- strokeDashoffset: evolution3.strokeDashoffset,
1884
- strokeWidth: "12"
1885
- }
1886
- )), /* @__PURE__ */ React19.createElement("defs", null, /* @__PURE__ */ React19.createElement(
1887
- "linearGradient",
1888
- {
1889
- gradientUnits: "userSpaceOnUse",
1890
- id: "gradient0",
1891
- x1: "109",
1892
- x2: "144.5",
1893
- y1: "116.5",
1894
- y2: "160.5"
1895
- },
1896
- /* @__PURE__ */ React19.createElement("stop", { stopColor: "white" }),
1897
- /* @__PURE__ */ React19.createElement("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })
1898
- ), /* @__PURE__ */ React19.createElement(
1899
- "linearGradient",
1900
- {
1901
- gradientUnits: "userSpaceOnUse",
1902
- id: "gradient1",
1903
- x1: "121",
1904
- x2: "120.799",
1905
- y1: "54",
1906
- y2: "106.875"
1907
- },
1908
- /* @__PURE__ */ React19.createElement("stop", { stopColor: "white" }),
1909
- /* @__PURE__ */ React19.createElement("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })
1910
- )));
1911
- };
1912
- var nextjsLogoConfig = {
1913
- displayName: "NextjsLogo",
1914
- type: "atom",
1915
- isInnerSequence: false
1916
- };
1917
-
1918
- // src/templates/rings/Rings.tsx
1919
- import React20 from "react";
1920
- import { AbsoluteFill as AbsoluteFill5, interpolateColors, useVideoConfig as useVideoConfig8 } from "remotion";
1921
- var RadialGradient = ({ radius, color }) => {
1922
- const height = radius * 2;
1923
- const width = radius * 2;
1924
- return (
1925
- // @ts-ignore
1926
- /* @__PURE__ */ React20.createElement(
1927
- AbsoluteFill5,
1928
- {
1929
- style: {
1930
- justifyContent: "center",
1931
- alignItems: "center"
1932
- }
1933
- },
1934
- /* @__PURE__ */ React20.createElement(
1935
- "div",
1936
- {
1937
- style: {
1938
- height,
1939
- width,
1940
- borderRadius: "50%",
1941
- backgroundColor: color,
1942
- position: "absolute",
1943
- boxShadow: "0 0 100px rgba(0, 0, 0, 0.05)"
1944
- }
1945
- }
1946
- )
1947
- )
1948
- );
1949
- };
1950
- var Rings = ({ context, data }) => {
1951
- const { logoOut } = useRippleOutLayout();
1952
- const outProgress = logoOut;
1953
- const scale = 1 / (1 - outProgress);
1954
- const { height } = useVideoConfig8();
1955
- return (
1956
- // @ts-ignore
1957
- /* @__PURE__ */ React20.createElement(
1958
- AbsoluteFill5,
1959
- {
1960
- style: {
1961
- transform: `scale(${scale})`,
1962
- ...context?.boundaries
1963
- }
1964
- },
1965
- new Array(5).fill(true).map((_, i) => {
1966
- return /* @__PURE__ */ React20.createElement(
1967
- RadialGradient,
1968
- {
1969
- key: i,
1970
- radius: height * 0.3 * i,
1971
- color: interpolateColors(i, [0, 4], ["#fff", "#fff"])
1972
- }
1973
- );
1974
- }).reverse()
1975
- )
1976
- );
1977
- };
1978
- var ringsConfig = {
1979
- displayName: "Rings",
1980
- type: "atom",
1981
- isInnerSequence: false
1982
- };
1983
-
1984
- // src/templates/rings/TextFade.tsx
1985
- import React21, { useMemo as useMemo9 } from "react";
1986
- import {
1987
- AbsoluteFill as AbsoluteFill6,
1988
- interpolate as interpolate5,
1989
- spring as spring5,
1990
- useCurrentFrame as useCurrentFrame8,
1991
- useVideoConfig as useVideoConfig9
1992
- } from "remotion";
1993
- var TextFade = (props) => {
1994
- const { children, context, data } = props;
1995
- const { animation } = data || {
1996
- animation: {
1997
- duration: 1
1998
- }
1999
- };
2000
- const { fps } = useVideoConfig9();
2001
- const frame = useCurrentFrame8();
2002
- const progress = spring5({
2003
- fps,
2004
- frame,
2005
- config: {
2006
- damping: 200
2007
- },
2008
- durationInFrames: animation.duration * fps
2009
- });
2010
- const rightStop = interpolate5(progress, [0, 1], [200, 0]);
2011
- const leftStop = Math.max(0, rightStop - 60);
2012
- const maskImage = `linear-gradient(-45deg, transparent ${leftStop}%, black ${rightStop}%)`;
2013
- const container2 = useMemo9(() => {
2014
- return {
2015
- width: "100%",
2016
- height: "100%",
2017
- justifyContent: "center",
2018
- alignItems: "center"
2019
- };
2020
- }, []);
2021
- const content = useMemo9(() => {
2022
- return {
2023
- ...context?.boundaries,
2024
- maskImage,
2025
- WebkitMaskImage: maskImage,
2026
- justifyContent: "center",
2027
- alignItems: "center",
2028
- display: "flex"
2029
- };
2030
- }, [maskImage]);
2031
- return (
2032
- // @ts-ignore
2033
- /* @__PURE__ */ React21.createElement(AbsoluteFill6, { style: container2 }, /* @__PURE__ */ React21.createElement("div", { style: content }, children))
2034
- );
2035
- };
2036
- var textFadeConfig = {
2037
- displayName: "TextFade",
2038
- type: "layout",
2039
- isInnerSequence: false
2040
- };
2041
-
2042
- // src/templates/rings/index.ts
2043
- registerComponent(
2044
- nextjsLogoConfig.displayName,
2045
- NextjsLogo,
2046
- "atom",
2047
- nextjsLogoConfig
2048
- );
2049
- registerComponent(
2050
- textFadeConfig.displayName,
2051
- TextFade,
2052
- "layout",
2053
- textFadeConfig
2054
- );
2055
- registerComponent(ringsConfig.displayName, Rings, "atom", ringsConfig);
2056
- registerComponent(
2057
- rippleOutLayoutConfig.displayName,
2058
- RippleOutLayout,
2059
- "layout",
2060
- rippleOutLayoutConfig
2061
- );
2062
-
2063
- // src/templates/waveform/components/WaveformCircle.tsx
2064
- import React23, { useMemo as useMemo11 } from "react";
2065
-
2066
- // src/templates/waveform/Waveform.tsx
2067
- import React22, { createContext as createContext4, useContext as useContext5 } from "react";
2068
- import { useCurrentFrame as useCurrentFrame9, useVideoConfig as useVideoConfig10 } from "remotion";
2069
-
2070
- // src/templates/waveform/hooks/useWaveformData.ts
2071
- import { useMemo as useMemo10 } from "react";
2072
- import {
2073
- useAudioData,
2074
- visualizeAudioWaveform,
2075
- visualizeAudio
2076
- } from "@remotion/media-utils";
2077
- import { staticFile as staticFile4 } from "remotion";
2078
- var isValidPowerOfTwo = (num) => {
2079
- return num > 0 && (num & num - 1) === 0;
2080
- };
2081
- var getClosestPowerOfTwo = (num) => {
2082
- if (num <= 0) return 32;
2083
- let power = 1;
2084
- while (power < num) {
2085
- power *= 2;
2086
- }
2087
- const lower = power / 2;
2088
- const upper = power;
2089
- return Math.abs(num - lower) < Math.abs(num - upper) ? lower : upper;
2090
- };
2091
- var useWaveformData = (config12) => {
2092
- const {
2093
- audioSrc,
2094
- numberOfSamples,
2095
- windowInSeconds,
2096
- dataOffsetInSeconds = 0,
2097
- normalize = false,
2098
- frame,
2099
- fps,
2100
- posterize,
2101
- includeFrequencyData = false,
2102
- minDb = -100,
2103
- maxDb = -30
2104
- } = config12;
2105
- const validatedNumberOfSamples = useMemo10(() => {
2106
- if (!isValidPowerOfTwo(numberOfSamples)) {
2107
- console.warn(
2108
- `numberOfSamples must be a power of 2. Adjusting ${numberOfSamples} to ${getClosestPowerOfTwo(numberOfSamples)}`
2109
- );
2110
- return getClosestPowerOfTwo(numberOfSamples);
2111
- }
2112
- return numberOfSamples;
2113
- }, [numberOfSamples]);
2114
- const source = useMemo10(() => {
2115
- if (audioSrc.startsWith("http")) {
2116
- return audioSrc;
2117
- }
2118
- return staticFile4(audioSrc);
2119
- }, [audioSrc]);
2120
- const audioData = useAudioData(source);
2121
- const adjustedFrame = useMemo10(() => {
2122
- if (posterize && posterize > 1) {
2123
- return Math.round(frame / posterize) * posterize;
2124
- }
2125
- return frame;
2126
- }, [frame, posterize]);
2127
- const waveformData = useMemo10(() => {
2128
- if (!audioData) return null;
2129
- try {
2130
- const waveform = visualizeAudioWaveform({
2131
- fps,
2132
- frame: adjustedFrame,
2133
- audioData,
2134
- numberOfSamples: validatedNumberOfSamples,
2135
- windowInSeconds,
2136
- dataOffsetInSeconds,
2137
- normalize
2138
- });
2139
- return waveform;
2140
- } catch (error2) {
2141
- console.error("Error generating waveform:", error2);
2142
- return null;
2143
- }
2144
- }, [
2145
- audioData,
2146
- adjustedFrame,
2147
- fps,
2148
- validatedNumberOfSamples,
2149
- windowInSeconds,
2150
- dataOffsetInSeconds,
2151
- normalize
2152
- ]);
2153
- const {
2154
- frequencyData,
2155
- amplitudes,
2156
- bass,
2157
- mid,
2158
- treble,
2159
- bassValues,
2160
- midValues,
2161
- trebleValues
2162
- } = useMemo10(() => {
2163
- if (!audioData || !includeFrequencyData) {
2164
- return {
2165
- frequencyData: null,
2166
- amplitudes: null,
2167
- bass: null,
2168
- mid: null,
2169
- treble: null,
2170
- bassValues: null,
2171
- midValues: null,
2172
- trebleValues: null
2173
- };
2174
- }
2175
- try {
2176
- const frequencyData2 = visualizeAudio({
2177
- fps,
2178
- frame: adjustedFrame,
2179
- audioData,
2180
- numberOfSamples: validatedNumberOfSamples
2181
- });
2182
- const { sampleRate } = audioData;
2183
- const bassValues2 = [];
2184
- const midValues2 = [];
2185
- const trebleValues2 = [];
2186
- for (let i = 0; i < frequencyData2.length; i++) {
2187
- const freq = i * sampleRate / (2 * frequencyData2.length);
2188
- const value = frequencyData2[i];
2189
- if (freq >= 0 && freq < 250) {
2190
- bassValues2.push(value * 2.5);
2191
- } else if (freq >= 250 && freq < 4e3) {
2192
- midValues2.push(value * 3);
2193
- midValues2.push(value * 4.5);
2194
- midValues2.push(value * 5);
2195
- } else if (freq >= 4e3 && freq < sampleRate / 2) {
2196
- trebleValues2.push(value * 30);
2197
- }
2198
- }
2199
- const getAverage = (arr) => arr.length > 0 ? arr.reduce((a, b) => a + b, 0) / arr.length : 0;
2200
- const bass2 = getAverage(bassValues2);
2201
- const mid2 = getAverage(midValues2);
2202
- const treble2 = getAverage(trebleValues2);
2203
- const amplitudes2 = frequencyData2.map((value) => {
2204
- const db = 20 * Math.log10(value);
2205
- const scaled = (db - minDb) / (maxDb - minDb);
2206
- return Math.max(0, Math.min(1, scaled));
2207
- });
2208
- return {
2209
- frequencyData: frequencyData2,
2210
- amplitudes: amplitudes2,
2211
- bass: bass2,
2212
- mid: mid2,
2213
- treble: treble2,
2214
- bassValues: bassValues2,
2215
- midValues: midValues2,
2216
- trebleValues: trebleValues2.reverse()
2217
- };
2218
- } catch (error2) {
2219
- console.error("Error generating frequency data:", error2);
2220
- return {
2221
- frequencyData: null,
2222
- amplitudes: null,
2223
- bass: null,
2224
- mid: null,
2225
- treble: null
2226
- };
2227
- }
2228
- }, [
2229
- audioData,
2230
- includeFrequencyData,
2231
- adjustedFrame,
2232
- fps,
2233
- validatedNumberOfSamples,
2234
- windowInSeconds,
2235
- dataOffsetInSeconds,
2236
- minDb,
2237
- maxDb
2238
- ]);
2239
- const isLoading = !audioData;
2240
- const error = audioData === null && !isLoading ? "Failed to load audio data" : null;
2241
- return {
2242
- waveformData,
2243
- frequencyData,
2244
- amplitudes,
2245
- audioData,
2246
- isLoading,
2247
- error,
2248
- bass,
2249
- bassValues,
2250
- mid,
2251
- midValues,
2252
- treble,
2253
- trebleValues
2254
- };
2255
- };
2256
-
2257
- // src/templates/waveform/Waveform.tsx
2258
- var WaveformContext = createContext4(null);
2259
- var useWaveformContext = () => {
2260
- const context = useContext5(WaveformContext);
2261
- if (!context) {
2262
- throw new Error("useWaveformContext must be used within a Waveform component");
2263
- }
2264
- return context;
2265
- };
2266
- var Waveform = ({
2267
- config: config12,
2268
- children,
2269
- className = "",
2270
- style = {}
2271
- }) => {
2272
- const frame = useCurrentFrame9();
2273
- const { width: videoWidth, height: videoHeight, fps } = useVideoConfig10();
2274
- const { waveformData, frequencyData, amplitudes, audioData, bass, mid, treble, bassValues, midValues, trebleValues } = useWaveformData({
2275
- audioSrc: config12.audioSrc,
2276
- numberOfSamples: config12.numberOfSamples || 128,
2277
- windowInSeconds: config12.windowInSeconds || 1 / fps,
2278
- dataOffsetInSeconds: config12.dataOffsetInSeconds || 0,
2279
- normalize: config12.normalize || false,
2280
- frame,
2281
- fps,
2282
- posterize: config12.posterize,
2283
- includeFrequencyData: config12.useFrequencyData || false
2284
- });
2285
- const width = config12.width || videoWidth;
2286
- const height = config12.height || videoHeight;
2287
- const contextValue = {
2288
- waveformData,
2289
- frequencyData,
2290
- amplitudes,
2291
- audioData,
2292
- frame,
2293
- fps,
2294
- config: config12,
2295
- width,
2296
- height,
2297
- bass,
2298
- mid,
2299
- treble,
2300
- bassValues,
2301
- midValues,
2302
- trebleValues
2303
- };
2304
- return /* @__PURE__ */ React22.createElement(WaveformContext.Provider, { value: contextValue }, /* @__PURE__ */ React22.createElement(
2305
- "div",
2306
- {
2307
- className: `relative ${className}`,
2308
- style: {
2309
- width,
2310
- height,
2311
- position: "relative",
2312
- backgroundColor: config12.backgroundColor || "transparent",
2313
- ...style
2314
- }
2315
- },
2316
- children
2317
- ));
2318
- };
2319
-
2320
- // src/templates/waveform/components/WaveformCircle.tsx
2321
- var WaveformCircle = ({ data }) => {
2322
- const {
2323
- config: config12,
2324
- className = "",
2325
- style = {},
2326
- strokeColor = "#FF6B6B",
2327
- strokeWidth = 3,
2328
- fill = "none",
2329
- opacity = 1,
2330
- radius = 80,
2331
- centerX = 50,
2332
- centerY = 50,
2333
- startAngle = 0,
2334
- endAngle = 360,
2335
- amplitude = 1,
2336
- rotationSpeed = 0,
2337
- gradientStartColor,
2338
- gradientEndColor
2339
- } = data;
2340
- return /* @__PURE__ */ React23.createElement(Waveform, { config: config12, className, style }, /* @__PURE__ */ React23.createElement(
2341
- WaveformCircleContent,
2342
- {
2343
- strokeColor,
2344
- strokeWidth,
2345
- fill,
2346
- opacity,
2347
- radius,
2348
- centerX,
2349
- centerY,
2350
- startAngle,
2351
- endAngle,
2352
- amplitude,
2353
- rotationSpeed,
2354
- gradientStartColor,
2355
- gradientEndColor
2356
- }
2357
- ));
2358
- };
2359
- var WaveformCircleContent = ({
2360
- strokeColor,
2361
- strokeWidth,
2362
- fill,
2363
- opacity,
2364
- radius,
2365
- centerX,
2366
- centerY,
2367
- startAngle,
2368
- endAngle,
2369
- amplitude,
2370
- rotationSpeed,
2371
- gradientStartColor,
2372
- gradientEndColor
2373
- }) => {
2374
- const { waveformData, width, height, frame } = useWaveformContext();
2375
- const circleRadius = Math.min(width, height) * (radius || 80) / 100;
2376
- const circleCenterX = width * (centerX || 50) / 100;
2377
- const circleCenterY = height * (centerY || 50) / 100;
2378
- const rotation = frame * (rotationSpeed || 0) % 360;
2379
- const circularPath = useMemo11(() => {
2380
- if (!waveformData) return "";
2381
- const totalAngle = (endAngle || 360) - (startAngle || 0);
2382
- const angleStep = totalAngle / waveformData.length;
2383
- let path = "";
2384
- waveformData.forEach((value, index) => {
2385
- const angle = ((startAngle || 0) + index * angleStep + rotation) * (Math.PI / 180);
2386
- const waveRadius = circleRadius + value * (amplitude || 1) * circleRadius * 0.3;
2387
- const x = circleCenterX + waveRadius * Math.cos(angle);
2388
- const y = circleCenterY + waveRadius * Math.sin(angle);
2389
- if (index === 0) {
2390
- path += `M ${x} ${y}`;
2391
- } else {
2392
- path += ` L ${x} ${y}`;
2393
- }
2394
- });
2395
- if (Math.abs((endAngle || 360) - (startAngle || 0)) >= 360) {
2396
- path += " Z";
2397
- }
2398
- return path;
2399
- }, [waveformData, circleRadius, circleCenterX, circleCenterY, startAngle, endAngle, rotation, amplitude]);
2400
- if (!waveformData) {
2401
- return /* @__PURE__ */ React23.createElement("div", { className: "flex items-center justify-center w-full h-full text-gray-500" }, "Loading circular waveform...");
2402
- }
2403
- const gradientId = "circle-waveform-gradient";
2404
- const hasGradient = gradientStartColor && gradientEndColor;
2405
- return /* @__PURE__ */ React23.createElement(
2406
- "svg",
2407
- {
2408
- width,
2409
- height,
2410
- className: "absolute inset-0",
2411
- style: { pointerEvents: "none" }
2412
- },
2413
- hasGradient && /* @__PURE__ */ React23.createElement("defs", null, /* @__PURE__ */ React23.createElement("linearGradient", { id: gradientId, x1: "0%", y1: "0%", x2: "100%", y2: "0%" }, /* @__PURE__ */ React23.createElement("stop", { offset: "0%", stopColor: gradientStartColor }), /* @__PURE__ */ React23.createElement("stop", { offset: "100%", stopColor: gradientEndColor }))),
2414
- /* @__PURE__ */ React23.createElement(
2415
- "path",
2416
- {
2417
- d: circularPath,
2418
- stroke: hasGradient ? `url(#${gradientId})` : strokeColor,
2419
- strokeWidth,
2420
- fill,
2421
- opacity,
2422
- strokeLinecap: "round",
2423
- strokeLinejoin: "round"
2424
- }
2425
- )
2426
- );
2427
- };
2428
-
2429
- // src/templates/waveform/components/WaveformHistogram.tsx
2430
- import React24 from "react";
2431
- var WaveformHistogram = ({ data }) => {
2432
- const {
2433
- config: config12,
2434
- className = "",
2435
- style = {},
2436
- barColor = "#FF6B6B",
2437
- barWidth = 4,
2438
- barSpacing = 2,
2439
- barBorderRadius = 2,
2440
- opacity = 1,
2441
- horizontalSymmetry = true,
2442
- verticalMirror = false,
2443
- histogramStyle = "centered",
2444
- amplitude = 1,
2445
- multiplier = 1,
2446
- gradientStartColor,
2447
- gradientEndColor,
2448
- gradientDirection = "vertical",
2449
- gradientStyle = "normal",
2450
- waveDirection = "right-to-left"
2451
- } = data;
2452
- return /* @__PURE__ */ React24.createElement(Waveform, { config: config12, className, style }, /* @__PURE__ */ React24.createElement(
2453
- WaveformHistogramContent,
2454
- {
2455
- barColor,
2456
- barWidth,
2457
- barSpacing,
2458
- barBorderRadius,
2459
- opacity,
2460
- horizontalSymmetry,
2461
- verticalMirror,
2462
- histogramStyle,
2463
- amplitude,
2464
- gradientStartColor,
2465
- gradientEndColor,
2466
- gradientDirection,
2467
- multiplier,
2468
- gradientStyle,
2469
- waveDirection
2470
- }
2471
- ));
2472
- };
2473
- var WaveformHistogramContent = ({
2474
- barColor,
2475
- barWidth,
2476
- barSpacing,
2477
- barBorderRadius,
2478
- opacity,
2479
- horizontalSymmetry,
2480
- verticalMirror,
2481
- histogramStyle,
2482
- amplitude,
2483
- gradientStartColor,
2484
- gradientEndColor,
2485
- gradientDirection,
2486
- multiplier,
2487
- gradientStyle,
2488
- waveDirection
2489
- }) => {
2490
- const { waveformData, frequencyData, amplitudes, width, height } = useWaveformContext();
2491
- const dataToUse = amplitudes || waveformData;
2492
- if (!dataToUse) {
2493
- return /* @__PURE__ */ React24.createElement("div", { className: "flex items-center justify-center w-full h-full text-gray-500" }, "Loading histogram...");
2494
- }
2495
- let directedData = waveDirection === "left-to-right" ? dataToUse.slice(1).reverse() : dataToUse;
2496
- const frequencies = horizontalSymmetry ? [...directedData, ...directedData.slice(1).reverse()] : Array(multiplier).fill(directedData).flat();
2497
- const Bars = ({ growUpwards }) => {
2498
- const styleGradientProp = gradientStartColor && gradientEndColor ? {
2499
- 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})`
2500
- } : { backgroundColor: barColor };
2501
- const containerStyle2 = {
2502
- display: "flex",
2503
- flexDirection: "row",
2504
- alignItems: growUpwards ? "flex-end" : "flex-start",
2505
- height: "100%",
2506
- width: "100%",
2507
- ...histogramStyle === "centered" && {
2508
- justifyContent: "center",
2509
- gap: `${barSpacing}px`
2510
- },
2511
- ...histogramStyle === "full-width" && {
2512
- gap: `${barSpacing}px`,
2513
- justifyContent: "space-between"
2514
- },
2515
- opacity: gradientStyle === "mirrored" && !growUpwards ? 0.25 : 1
2516
- };
2517
- return /* @__PURE__ */ React24.createElement("div", { style: containerStyle2 }, frequencies.map((value, index) => /* @__PURE__ */ React24.createElement(
2518
- "div",
2519
- {
2520
- key: index,
2521
- style: {
2522
- ...histogramStyle === "full-width" ? { width: `${barWidth}px` } : { width: `${barWidth}px` },
2523
- ...styleGradientProp,
2524
- height: `${Math.min(
2525
- height / 2,
2526
- Math.abs(value) * (height / 2) * (amplitude || 1)
2527
- )}px`,
2528
- borderRadius: growUpwards ? `${barBorderRadius}px ${barBorderRadius}px 0 0` : `0 0 ${barBorderRadius}px ${barBorderRadius}px`,
2529
- opacity
2530
- }
2531
- }
2532
- )));
2533
- };
2534
- if (verticalMirror) {
2535
- const topHalfStyle = {
2536
- position: "absolute",
2537
- bottom: `calc(100% - ${height / 2}px)`,
2538
- height: `${height / 2}px`,
2539
- width: "100%",
2540
- left: 0
2541
- };
2542
- const bottomHalfStyle = {
2543
- position: "absolute",
2544
- top: `${height / 2}px`,
2545
- height: `${height / 2}px`,
2546
- width: "100%",
2547
- left: 0
2548
- };
2549
- return /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement("div", { style: topHalfStyle }, /* @__PURE__ */ React24.createElement(Bars, { growUpwards: true })), /* @__PURE__ */ React24.createElement("div", { style: bottomHalfStyle }, /* @__PURE__ */ React24.createElement(Bars, { growUpwards: false })));
2550
- }
2551
- const containerStyle = {
2552
- width: "100%",
2553
- position: "absolute",
2554
- top: `${height / 2 - height / 4}px`,
2555
- height: `${height / 2}px`,
2556
- left: 0
2557
- };
2558
- return /* @__PURE__ */ React24.createElement("div", { style: containerStyle }, /* @__PURE__ */ React24.createElement(Bars, { growUpwards: true }));
2559
- };
2560
-
2561
- // src/templates/waveform/components/WaveformHistogramRanged.tsx
2562
- import React25 from "react";
2563
- var WaveformHistogramRanged = ({ data }) => {
2564
- const {
2565
- config: config12,
2566
- className = "",
2567
- style = {},
2568
- barColor = "#FF6B6B",
2569
- barWidth = 4,
2570
- barSpacing = 2,
2571
- barBorderRadius = 2,
2572
- opacity = 1,
2573
- verticalMirror = false,
2574
- histogramStyle = "centered",
2575
- amplitude = 1,
2576
- showFrequencyRanges = true,
2577
- rangeDividerColor = "#666",
2578
- rangeLabels = false,
2579
- bassBarColor = "#5DADE2",
2580
- midBarColor = "#58D68D",
2581
- trebleBarColor = "#F5B041",
2582
- gradientStartColor,
2583
- gradientEndColor,
2584
- gradientDirection = "vertical",
2585
- gradientStyle = "normal",
2586
- horizontalSymmetry = false,
2587
- waveDirection = "right-to-left"
2588
- } = data;
2589
- return /* @__PURE__ */ React25.createElement(Waveform, { config: config12, className, style }, /* @__PURE__ */ React25.createElement(
2590
- WaveformHistogramRangedContent,
2591
- {
2592
- barColor,
2593
- barWidth,
2594
- barSpacing,
2595
- barBorderRadius,
2596
- opacity,
2597
- verticalMirror,
2598
- histogramStyle,
2599
- amplitude,
2600
- showFrequencyRanges,
2601
- rangeDividerColor,
2602
- rangeLabels,
2603
- bassBarColor,
2604
- midBarColor,
2605
- trebleBarColor,
2606
- gradientStartColor,
2607
- gradientEndColor,
2608
- gradientDirection,
2609
- gradientStyle,
2610
- horizontalSymmetry,
2611
- waveDirection
2612
- }
2613
- ));
2614
- };
2615
- var WaveformHistogramRangedContent = ({
2616
- barColor,
2617
- barWidth,
2618
- barSpacing,
2619
- barBorderRadius,
2620
- opacity,
2621
- verticalMirror,
2622
- histogramStyle,
2623
- amplitude,
2624
- showFrequencyRanges,
2625
- rangeDividerColor,
2626
- rangeLabels,
2627
- bassBarColor,
2628
- midBarColor,
2629
- trebleBarColor,
2630
- gradientStartColor,
2631
- gradientEndColor,
2632
- gradientDirection,
2633
- gradientStyle,
2634
- horizontalSymmetry,
2635
- waveDirection
2636
- }) => {
2637
- const { amplitudes, bassValues, midValues, trebleValues, height } = useWaveformContext();
2638
- if (!amplitudes || !bassValues || !midValues || !trebleValues) {
2639
- return /* @__PURE__ */ React25.createElement("div", { className: "flex items-center justify-center w-full h-full text-gray-500" }, "Loading frequency data...");
2640
- }
2641
- const bassFrequencies = bassValues;
2642
- const midFrequencies = midValues;
2643
- const trebleFrequencies = trebleValues;
2644
- const allFrequencies = waveDirection === "right-to-left" ? [bassFrequencies, midFrequencies, trebleFrequencies].flat() : [trebleFrequencies, midFrequencies, bassFrequencies].flat();
2645
- const unifiedWaveform = horizontalSymmetry ? [...allFrequencies.slice(1).reverse(), ...allFrequencies] : allFrequencies;
2646
- const Bars = ({ growUpwards }) => {
2647
- const containerStyle2 = {
2648
- display: "flex",
2649
- flexDirection: "row",
2650
- alignItems: growUpwards ? "flex-end" : "flex-start",
2651
- height: "100%",
2652
- width: "100%",
2653
- ...histogramStyle === "centered" && {
2654
- justifyContent: "center",
2655
- gap: `${barSpacing}px`
2656
- },
2657
- ...histogramStyle === "full-width" && {
2658
- gap: `${barSpacing}px`,
2659
- justifyContent: "space-between"
2660
- },
2661
- opacity: gradientStyle === "mirrored" && !growUpwards ? 0.25 : 1
2662
- };
2663
- return /* @__PURE__ */ React25.createElement("div", { style: containerStyle2 }, unifiedWaveform.map((value, index) => {
2664
- const rangeName = index === 0 ? "Bass" : index === 1 ? "Mid" : "Treble";
2665
- const styleGradientProp = gradientStartColor && gradientEndColor ? {
2666
- 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})`
2667
- } : { backgroundColor: barColor };
2668
- return /* @__PURE__ */ React25.createElement(
2669
- "div",
2670
- {
2671
- key: index,
2672
- style: {
2673
- width: `${barWidth || 4}px`,
2674
- // Wider bars for the three ranges
2675
- ...styleGradientProp,
2676
- height: `${Math.min(
2677
- height / 2,
2678
- Math.abs(value) * (height / 2) * (amplitude || 1)
2679
- )}px`,
2680
- borderRadius: growUpwards ? `${barBorderRadius}px ${barBorderRadius}px 0 0` : `0 0 ${barBorderRadius}px ${barBorderRadius}px`,
2681
- opacity,
2682
- position: "relative"
2683
- },
2684
- title: `${rangeName}: ${(value * 100).toFixed(1)}%`
2685
- },
2686
- rangeLabels && /* @__PURE__ */ React25.createElement("div", { style: {
2687
- position: "absolute",
2688
- bottom: growUpwards ? "-20px" : "auto",
2689
- top: growUpwards ? "auto" : "-20px",
2690
- left: "50%",
2691
- transform: "translateX(-50%)",
2692
- fontSize: "10px",
2693
- color: rangeDividerColor,
2694
- whiteSpace: "nowrap"
2695
- } }, rangeName)
2696
- );
2697
- }));
2698
- };
2699
- if (verticalMirror) {
2700
- const topHalfStyle = {
2701
- position: "absolute",
2702
- bottom: `calc(100% - ${height / 2}px)`,
2703
- height: `${height / 2}px`,
2704
- width: "100%",
2705
- left: 0
2706
- };
2707
- const bottomHalfStyle = {
2708
- position: "absolute",
2709
- top: `${height / 2}px`,
2710
- height: `${height / 2}px`,
2711
- width: "100%",
2712
- left: 0
2713
- };
2714
- return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement("div", { style: topHalfStyle }, /* @__PURE__ */ React25.createElement(Bars, { growUpwards: true })), /* @__PURE__ */ React25.createElement("div", { style: bottomHalfStyle }, /* @__PURE__ */ React25.createElement(Bars, { growUpwards: false })));
2715
- }
2716
- const containerStyle = {
2717
- width: "100%",
2718
- position: "absolute",
2719
- top: `${height / 2 - height / 4}px`,
2720
- height: `${height / 2}px`,
2721
- left: 0
2722
- };
2723
- return /* @__PURE__ */ React25.createElement("div", { style: containerStyle }, /* @__PURE__ */ React25.createElement(Bars, { growUpwards: true }));
2724
- };
2725
-
2726
- // src/templates/waveform/components/WaveformLine.tsx
2727
- import React26, { useMemo as useMemo12 } from "react";
2728
- import { createSmoothSvgPath } from "@remotion/media-utils";
2729
- import { useCurrentFrame as useCurrentFrame10, useVideoConfig as useVideoConfig11 } from "remotion";
2730
- var detectBeat = (frequencyData, amplitudes, threshold = 0.7, bpm, frame = 0, fps = 30) => {
2731
- if (!frequencyData || !amplitudes || frequencyData.length === 0) return false;
2732
- if (bpm) {
2733
- const beatInterval = 60 / bpm * fps;
2734
- const beatFrame = Math.round(frame / beatInterval) * beatInterval;
2735
- return Math.abs(frame - beatFrame) < 2;
2736
- }
2737
- const bassFrequencies = amplitudes.slice(0, Math.floor(amplitudes.length * 0.15));
2738
- const midFrequencies = amplitudes.slice(Math.floor(amplitudes.length * 0.15), Math.floor(amplitudes.length * 0.4));
2739
- const bassEnergy = Math.sqrt(bassFrequencies.reduce((sum, val) => sum + val * val, 0) / bassFrequencies.length);
2740
- const midEnergy = Math.sqrt(midFrequencies.reduce((sum, val) => sum + val * val, 0) / midFrequencies.length);
2741
- const bassPeak = Math.max(...bassFrequencies);
2742
- const midPeak = Math.max(...midFrequencies);
2743
- const totalEnergy = bassEnergy * 0.6 + midEnergy * 0.2 + bassPeak * 0.15 + midPeak * 0.05;
2744
- const normalizedEnergy = Math.min(totalEnergy, 1);
2745
- return normalizedEnergy > threshold;
2746
- };
2747
- var easingFunctions = {
2748
- linear: (t) => t,
2749
- "ease-in": (t) => t * t,
2750
- "ease-out": (t) => 1 - (1 - t) * (1 - t),
2751
- "ease-in-out": (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2,
2752
- bounce: (t) => {
2753
- if (t < 1 / 2.75) return 7.5625 * t * t;
2754
- if (t < 2 / 2.75) return 7.5625 * (t -= 1.5 / 2.75) * t + 0.75;
2755
- if (t < 2.5 / 2.75) return 7.5625 * (t -= 2.25 / 2.75) * t + 0.9375;
2756
- return 7.5625 * (t -= 2.625 / 2.75) * t + 0.984375;
2757
- }
2758
- };
2759
- var WaveformLine = ({ data }) => {
2760
- const {
2761
- config: config12,
2762
- className = "",
2763
- style = {},
2764
- strokeColor = "#FF6B6B",
2765
- strokeWidth = 3,
2766
- strokeLinecap = "round",
2767
- strokeLinejoin = "round",
2768
- fill = "none",
2769
- opacity = 1,
2770
- centerLine = false,
2771
- centerLineColor = "#666",
2772
- centerLineWidth = 1,
2773
- beatSync = false,
2774
- bpm,
2775
- beatThreshold = 0.7,
2776
- beatAmplitudeMultiplier = 1.2,
2777
- beatAnimationDuration = 30,
2778
- smoothAnimation = true,
2779
- waveSpacing = 0.1,
2780
- waveSegments = 1,
2781
- waveOffset = 0,
2782
- waveDirection = "horizontal",
2783
- amplitudeCurve = "ease-out",
2784
- animationSpeed = 0.5,
2785
- pulseOnBeat = false,
2786
- pulseColor = "#FFD700",
2787
- pulseScale = 1.2
2788
- } = data;
2789
- return /* @__PURE__ */ React26.createElement(Waveform, { config: config12, className, style }, /* @__PURE__ */ React26.createElement(
2790
- WaveformLineContent,
2791
- {
2792
- strokeColor,
2793
- strokeWidth,
2794
- strokeLinecap,
2795
- strokeLinejoin,
2796
- fill,
2797
- opacity,
2798
- centerLine,
2799
- centerLineColor,
2800
- centerLineWidth,
2801
- beatSync,
2802
- bpm,
2803
- beatThreshold,
2804
- beatAmplitudeMultiplier,
2805
- beatAnimationDuration,
2806
- smoothAnimation,
2807
- waveSpacing,
2808
- waveSegments,
2809
- waveOffset,
2810
- waveDirection,
2811
- amplitudeCurve,
2812
- animationSpeed,
2813
- pulseOnBeat,
2814
- pulseColor,
2815
- pulseScale
2816
- }
2817
- ));
2818
- };
2819
- var WaveformLineContent = ({
2820
- strokeColor,
2821
- strokeWidth,
2822
- strokeLinecap,
2823
- strokeLinejoin,
2824
- fill,
2825
- opacity,
2826
- centerLine,
2827
- centerLineColor,
2828
- centerLineWidth,
2829
- beatSync,
2830
- bpm,
2831
- beatThreshold,
2832
- beatAmplitudeMultiplier,
2833
- beatAnimationDuration,
2834
- smoothAnimation,
2835
- waveSpacing,
2836
- waveSegments,
2837
- waveOffset,
2838
- waveDirection,
2839
- amplitudeCurve,
2840
- animationSpeed,
2841
- pulseOnBeat,
2842
- pulseColor,
2843
- pulseScale
2844
- }) => {
2845
- const { waveformData, frequencyData, amplitudes, width, height, config: config12, frame, fps } = useWaveformContext();
2846
- const currentFrame = useCurrentFrame10();
2847
- const videoConfig = useVideoConfig11();
2848
- const isBeat = useMemo12(() => {
2849
- if (!beatSync || !frequencyData || !amplitudes) return false;
2850
- return detectBeat(frequencyData, amplitudes, beatThreshold, bpm, currentFrame, fps);
2851
- }, [beatSync, frequencyData, amplitudes, beatThreshold, bpm, currentFrame, fps]);
2852
- const beatProgress = useMemo12(() => {
2853
- if (!isBeat || !beatAnimationDuration) return 0;
2854
- const beatStartFrame = Math.floor(currentFrame / beatAnimationDuration) * beatAnimationDuration;
2855
- const progress = (currentFrame - beatStartFrame) / beatAnimationDuration;
2856
- const clampedProgress = Math.max(0, Math.min(1, progress));
2857
- if (smoothAnimation) {
2858
- return 1 - Math.pow(1 - clampedProgress, 3);
2859
- }
2860
- return clampedProgress;
2861
- }, [isBeat, currentFrame, beatAnimationDuration, smoothAnimation]);
2862
- const currentBeatMultiplier = useMemo12(() => {
2863
- if (!beatSync || !isBeat || !beatAmplitudeMultiplier || !amplitudeCurve) return 1;
2864
- const easing = easingFunctions[amplitudeCurve];
2865
- const easedProgress = easing(beatProgress);
2866
- return 1 + (beatAmplitudeMultiplier - 1) * (1 - easedProgress);
2867
- }, [beatSync, isBeat, beatProgress, beatAmplitudeMultiplier, amplitudeCurve]);
2868
- const smoothFactor = useMemo12(() => {
2869
- if (!beatSync) {
2870
- return 0.3;
2871
- }
2872
- return smoothAnimation ? 0.7 : 1;
2873
- }, [beatSync, smoothAnimation]);
2874
- const waveformPaths = useMemo12(() => {
2875
- if (!waveformData) return [];
2876
- const paths = [];
2877
- const segments = waveSegments || 1;
2878
- const spacing = waveSpacing || 0.1;
2879
- const offset = waveOffset || 0;
2880
- const speed = animationSpeed || 1;
2881
- const segmentWidth = width / segments;
2882
- const segmentSpacing = segmentWidth * spacing;
2883
- for (let i = 0; i < segments; i++) {
2884
- const segmentStart = i * segmentWidth;
2885
- const segmentEnd = (i + 1) * segmentWidth;
2886
- const segmentDataWidth = segmentEnd - segmentStart;
2887
- const points = waveformData.map((y, index) => {
2888
- const progress = index / (waveformData.length - 1);
2889
- const x = segmentStart + progress * segmentDataWidth + offset;
2890
- let animatedAmplitude = y * (config12.amplitude || 1) * currentBeatMultiplier * speed;
2891
- const baseAmplitude = y * (config12.amplitude || 1) * speed;
2892
- const beatAmplitude = animatedAmplitude - baseAmplitude;
2893
- animatedAmplitude = baseAmplitude + beatAmplitude * smoothFactor;
2894
- const yPos = waveDirection === "horizontal" ? animatedAmplitude * height / 2 + height / 2 : animatedAmplitude * width / 2 + width / 2;
2895
- return waveDirection === "horizontal" ? { x, y: yPos } : { x: yPos, y: x };
2896
- });
2897
- const path = createSmoothSvgPath({ points });
2898
- paths.push({ path, segmentIndex: i });
2899
- }
2900
- return paths;
2901
- }, [waveformData, width, height, config12.amplitude, currentBeatMultiplier, animationSpeed, waveSegments, waveSpacing, waveOffset, waveDirection, smoothFactor]);
2902
- if (!waveformData) {
2903
- return /* @__PURE__ */ React26.createElement("div", { className: "flex items-center justify-center w-full h-full text-gray-500" }, "Loading waveform...");
2904
- }
2905
- return /* @__PURE__ */ React26.createElement(
2906
- "svg",
2907
- {
2908
- width,
2909
- height,
2910
- className: "absolute inset-0",
2911
- style: { pointerEvents: "none" }
2912
- },
2913
- centerLine && /* @__PURE__ */ React26.createElement(
2914
- "line",
2915
- {
2916
- x1: waveDirection === "horizontal" ? 0 : width / 2,
2917
- y1: waveDirection === "horizontal" ? height / 2 : 0,
2918
- x2: waveDirection === "horizontal" ? width : width / 2,
2919
- y2: waveDirection === "horizontal" ? height / 2 : height,
2920
- stroke: centerLineColor,
2921
- strokeWidth: centerLineWidth,
2922
- opacity: 0.3
2923
- }
2924
- ),
2925
- waveformPaths.map(({ path, segmentIndex }) => /* @__PURE__ */ React26.createElement("g", { key: segmentIndex }, pulseOnBeat && isBeat && /* @__PURE__ */ React26.createElement(
2926
- "path",
2927
- {
2928
- d: path,
2929
- stroke: pulseColor,
2930
- strokeWidth: (strokeWidth || 3) * (pulseScale || 1.2),
2931
- strokeLinecap,
2932
- strokeLinejoin,
2933
- fill: "none",
2934
- opacity: (opacity || 1) * (1 - beatProgress)
2935
- }
2936
- ), /* @__PURE__ */ React26.createElement(
2937
- "path",
2938
- {
2939
- d: path,
2940
- stroke: strokeColor,
2941
- strokeWidth,
2942
- strokeLinecap,
2943
- strokeLinejoin,
2944
- fill,
2945
- opacity
2946
- }
2947
- )))
2948
- );
2949
- };
2950
-
2951
- // src/templates/waveform/utils.ts
2952
- var WaveformPresets = {
2953
- stopgapLine: (props) => {
2954
- return {
2955
- componentId: "WaveformLine",
2956
- type: "atom",
2957
- data: {
2958
- strokeColor: "#58C4DC",
2959
- strokeWidth: 8,
2960
- strokeLinecap: "round",
2961
- opacity: 1,
2962
- amplitudeCurve: "ease-in-out",
2963
- animationSpeed: 0.15,
2964
- smoothAnimation: true,
2965
- ...props,
2966
- config: {
2967
- numberOfSamples: 64,
2968
- // Increased for better frequency resolution
2969
- windowInSeconds: 1 / 30,
2970
- amplitude: 4,
2971
- height: 300,
2972
- width: 1920 * 3,
2973
- posterize: 4,
2974
- ...props.config
2975
- }
2976
- }
2977
- };
2978
- }
2979
- };
2980
-
2981
- // src/templates/waveform/index.ts
2982
- registerComponent("WaveformLine", WaveformLine, "atom", {
2983
- displayName: "WaveformLine"
2984
- });
2985
- registerComponent("WaveformHistogram", WaveformHistogram, "atom", {
2986
- displayName: "WaveformHistogram"
2987
- });
2988
- registerComponent("WaveformHistogramRanged", WaveformHistogramRanged, "atom", {
2989
- displayName: "WaveformHistogramRanged"
2990
- });
2991
- registerComponent("WaveformCircle", WaveformCircle, "atom", {
2992
- displayName: "WaveformCircle"
2993
- });
2994
-
2995
- // src/components/Composition.tsx
2996
- import React27 from "react";
2997
- import { AbsoluteFill as AbsoluteFill7, Composition as RemotionComposition } from "remotion";
2998
-
2999
- // src/core/context/timing.ts
3000
- import { ALL_FORMATS, Input, UrlSource } from "mediabunny";
3001
- var findMatchingComponents = (childrenData, targetIds) => {
3002
- const matches = [];
3003
- const searchRecursively = (components) => {
3004
- for (const component of components) {
3005
- if (targetIds.includes(component.id)) {
3006
- matches.push(component);
3007
- }
3008
- if (component.childrenData && component.childrenData.length > 0) {
3009
- searchRecursively(component.childrenData);
3010
- }
3011
- }
3012
- };
3013
- searchRecursively(childrenData);
3014
- return matches;
3015
- };
3016
- var calculateDuration = async (childrenData, config12) => {
3017
- let calculatedDuration = void 0;
3018
- const targetIds = Array.isArray(config12.fitDurationTo) ? config12.fitDurationTo : [config12.fitDurationTo];
3019
- const matchingComponents = findMatchingComponents(
3020
- childrenData || [],
3021
- targetIds
3022
- );
3023
- if (matchingComponents.length === 1) {
3024
- if (matchingComponents[0].type === "atom" && (matchingComponents[0].componentId === "AudioAtom" || matchingComponents[0].componentId === "VideoAtom")) {
3025
- const src = matchingComponents[0].data.src;
3026
- if (src.startsWith("http")) {
3027
- const audioInput = new Input({
3028
- formats: ALL_FORMATS,
3029
- source: new UrlSource(src)
3030
- });
3031
- calculatedDuration = await audioInput.computeDuration();
3032
- } else {
3033
- }
3034
- }
3035
- }
3036
- return calculatedDuration;
3037
- };
3038
- var setDurationsInContext = async (root) => {
3039
- const iterateRecursively = async (components) => {
3040
- const updatedComponents = [];
3041
- for (const component of components) {
3042
- let updatedComponent = { ...component };
3043
- if (component.context?.timing?.fitDurationTo?.length > 0) {
3044
- const duration = await calculateDuration(component.childrenData, {
3045
- fitDurationTo: component.context?.timing?.fitDurationTo
3046
- });
3047
- updatedComponent = {
3048
- ...component,
3049
- context: {
3050
- ...component.context,
3051
- timing: {
3052
- ...component.context.timing,
3053
- duration
3054
- }
3055
- }
3056
- };
3057
- }
3058
- if (component.childrenData && component.childrenData.length > 0) {
3059
- updatedComponent.childrenData = await iterateRecursively(
3060
- component.childrenData
3061
- );
3062
- }
3063
- updatedComponents.push(updatedComponent);
3064
- }
3065
- return updatedComponents;
3066
- };
3067
- const updatedChildrenData = await iterateRecursively(root.childrenData);
3068
- return {
3069
- ...root,
3070
- childrenData: updatedChildrenData
3071
- };
3072
- };
3073
-
3074
- // src/components/Composition.tsx
3075
- var CompositionLayout = ({ childrenData, style, config: config12 }) => {
3076
- return /* @__PURE__ */ React27.createElement(
3077
- CompositionProvider,
3078
- {
3079
- value: {
3080
- root: childrenData,
3081
- duration: config12.duration
3082
- }
3083
- },
3084
- /* @__PURE__ */ React27.createElement(AbsoluteFill7, { style }, childrenData?.map((component) => /* @__PURE__ */ React27.createElement(
3085
- ComponentRenderer,
3086
- {
3087
- key: component.id,
3088
- ...component
3089
- }
3090
- )))
3091
- );
3092
- };
3093
- var calculateCompositionLayoutMetadata = async ({ props, defaultProps, abortSignal, isRendering }) => {
3094
- let calculatedDuration = void 0;
3095
- if (props.config?.fitDurationTo?.length > 0) {
3096
- calculatedDuration = await calculateDuration(props.childrenData, {
3097
- fitDurationTo: props.config.fitDurationTo
3098
- });
3099
- }
3100
- const duration = calculatedDuration ?? props.config.duration ?? defaultProps.config.duration;
3101
- const fps = props.config.fps ?? defaultProps.config.fps;
3102
- const durationInFrames = Math.round(duration * fps);
3103
- const updatedProps = await setDurationsInContext(props);
3104
- return {
3105
- // Change the metadata
3106
- durationInFrames,
3107
- // or transform some props
3108
- props: updatedProps,
3109
- // // or add per-composition default codec
3110
- // defaultCodec: 'h264',
3111
- // // or add per-composition default video image format
3112
- // defaultVideoImageFormat: 'png',
3113
- // // or add per-composition default pixel format
3114
- // defaultPixelFormat: 'yuv420p',
3115
- width: props.config?.width || defaultProps.config.width,
3116
- height: props.config?.height || defaultProps.config.height,
3117
- fps,
3118
- duration
3119
- };
3120
- };
3121
- var Composition = ({
3122
- id,
3123
- childrenData,
3124
- config: config12,
3125
- style
3126
- }) => {
3127
- return /* @__PURE__ */ React27.createElement(
3128
- RemotionComposition,
3129
- {
3130
- id,
3131
- component: CompositionLayout,
3132
- durationInFrames: Math.round(config12.duration * config12.fps),
3133
- fps: config12.fps,
3134
- defaultProps: { childrenData, style, config: config12 },
3135
- calculateMetadata: calculateCompositionLayoutMetadata
3136
- }
3137
- );
3138
- };
3139
- export {
3140
- Atom5 as AudioAtom,
3141
- config6 as AudioAtomConfig,
3142
- Layout as BaseLayout,
3143
- config as BaseLayoutConfig,
3144
- BlurEffect,
3145
- config8 as BlurEffectConfig,
3146
- ComponentRenderer,
3147
- Composition,
3148
- CompositionLayout,
3149
- CompositionProvider,
3150
- Frame,
3151
- Atom2 as ImageAtom,
3152
- config3 as ImageAtomConfig,
3153
- LoopEffect,
3154
- config9 as LoopEffectConfig,
3155
- NextjsLogo,
3156
- PanEffect,
3157
- config10 as PanEffectConfig,
3158
- Rings,
3159
- RippleOutLayout,
3160
- SceneFrame,
3161
- Atom as ShapeAtom,
3162
- config2 as ShapeAtomConfig,
3163
- Atom3 as TextAtom,
3164
- config4 as TextAtomConfig,
3165
- Atom6 as TextAtomWithFonts,
3166
- config7 as TextAtomWithFontsConfig,
3167
- TextFade,
3168
- Atom4 as VideoAtom,
3169
- config5 as VideoAtomConfig,
3170
- Waveform,
3171
- WaveformCircle,
3172
- WaveformHistogram,
3173
- WaveformHistogramRanged,
3174
- WaveformLine,
3175
- WaveformPresets,
3176
- ZoomEffect,
3177
- config11 as ZoomEffectConfig,
3178
- buildLayoutHook,
3179
- calculateCircularPosition,
3180
- calculateCompositionLayoutMetadata,
3181
- calculateGridPosition,
3182
- calculateHierarchy,
3183
- calculateTimingWithInheritance,
3184
- clearFontCache,
3185
- componentRegistry,
3186
- createRootContext,
3187
- findComponentById,
3188
- findParentComponent,
3189
- getComponent,
3190
- getComponentConfig,
3191
- getComponentWithConfig,
3192
- getLoadedFontFamily,
3193
- getLoadedFonts,
3194
- getNormalizedFontName,
3195
- isFontAvailable,
3196
- isFontLoaded,
3197
- loadGoogleFont,
3198
- loadMultipleFonts,
3199
- mergeContexts,
3200
- nextjsLogoConfig,
3201
- preloadCommonFonts,
3202
- registerComponent,
3203
- registerEffect,
3204
- registerPackage,
3205
- ringsConfig,
3206
- rippleOutLayoutConfig,
3207
- textFadeConfig,
3208
- useBoundaryCalculation,
3209
- useComponentRegistry,
3210
- useComposition,
3211
- useFont,
3212
- useFontLoader,
3213
- useRenderContext,
3214
- useRippleOutLayout,
3215
- useWaveformContext,
3216
- useWaveformData
3217
- };
3218
- //# sourceMappingURL=index.mjs.map