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