@evatril/video-templates 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/package.json +14 -0
  2. package/public/Fonts/DancingScript-VariableFont_wght.ttf +0 -0
  3. package/public/Fonts/GreatVibes-Regular.ttf +0 -0
  4. package/public/Fonts/PlayfairDisplay-Italic-VariableFont_wght.ttf +0 -0
  5. package/public/video-images/20012026-bg.png +0 -0
  6. package/public/video-images/20012026-bride.png +0 -0
  7. package/public/video-images/20012026-butterfly.png +0 -0
  8. package/public/video-images/20012026-couple-walk.png +0 -0
  9. package/public/video-images/20012026-curtain-floral.png +0 -0
  10. package/public/video-images/20012026-floral-left.png +0 -0
  11. package/public/video-images/20012026-floral-right.png +0 -0
  12. package/public/video-images/20012026-groom.png +0 -0
  13. package/public/video-images/20012026-opening-gate.png +0 -0
  14. package/public/video-images/20012026-peacock.png +0 -0
  15. package/public/video-images/20012026-tree-left.png +0 -0
  16. package/public/video-images/20012026-tree-right.png +0 -0
  17. package/public/video-images/20012026-wedding-gate.png +0 -0
  18. package/public/video-images/wedding.mp3 +0 -0
  19. package/src/Invitations/Elements/Butterflies20012026.jsx +70 -0
  20. package/src/Invitations/Elements/CoupleWalk20012026.jsx +74 -0
  21. package/src/Invitations/Elements/FlowersSide20012026.jsx +143 -0
  22. package/src/Invitations/Elements/GroomBrideLoveScene20012026.jsx +163 -0
  23. package/src/Invitations/Elements/InkSmokeTransition20012026.jsx +72 -0
  24. package/src/Invitations/Elements/OpeningGate20012026.jsx +59 -0
  25. package/src/Invitations/Elements/PeacockDance20012026.jsx +68 -0
  26. package/src/Invitations/Elements/SideTrees20012026.jsx +104 -0
  27. package/src/Invitations/Elements/SmoothRevealFromTop.jsx +32 -0
  28. package/src/Invitations/Frames/F20012026_01.jsx +180 -0
  29. package/src/Invitations/Frames/F20012026_02.jsx +311 -0
  30. package/src/Invitations/Frames/F20012026_03.jsx +317 -0
  31. package/src/Invitations/Themes/T20012026_01.jsx +125 -0
  32. package/src/compositions.jsx +19 -0
  33. package/src/fonts/index.js +3 -0
  34. package/src/fonts/registerFonts.js +46 -0
  35. package/src/index.js +2 -0
  36. package/src/remotionRoot.jsx +5 -0
@@ -0,0 +1,317 @@
1
+ import React from "react";
2
+ import {
3
+ AbsoluteFill,
4
+ useCurrentFrame,
5
+ useVideoConfig,
6
+ interpolate,
7
+ Easing,
8
+ Img,
9
+ staticFile,
10
+ } from "remotion";
11
+
12
+ import { GroomBrideLoveScene20012026 } from "../Elements/GroomBrideLoveScene20012026.jsx";
13
+ import{ SmoothRevealFromTop} from "../Elements/SmoothRevealFromTop.jsx"
14
+
15
+ export const F20012026_03 = ({
16
+ eventDateTime,
17
+ venueName,
18
+ venueAddress,
19
+ familyMember,
20
+ fadeInDuration = 30,
21
+ }) => {
22
+ const frame = useCurrentFrame();
23
+ const { fps } = useVideoConfig();
24
+
25
+ /* ================= SCENE REVEAL (SMOKE FOLLOW-UP) ================= */
26
+ const sceneOpacity = interpolate(
27
+ frame,
28
+ [0, fadeInDuration],
29
+ [0, 1],
30
+ {
31
+ extrapolateRight: "clamp",
32
+ easing: Easing.out(Easing.ease),
33
+ }
34
+ );
35
+
36
+ // 🎥 VERY SMOOTH CINEMATIC ZOOM
37
+ const sceneScale = interpolate(
38
+ frame,
39
+ [0, fadeInDuration * 2],
40
+ [1.20, 1],
41
+ {
42
+ extrapolateRight: "clamp",
43
+ easing: Easing.out(Easing.cubic),
44
+ }
45
+ );
46
+
47
+ /* ---------------- DATE UTILS ---------------- */
48
+ const getDateParts = (iso) => {
49
+ if (!iso) return { day: "", month: "", year: "", time: "" };
50
+
51
+ const d = new Date(iso);
52
+ if (isNaN(d.getTime())) {
53
+ return { day: "", month: "", year: "", time: "" };
54
+ }
55
+
56
+ return {
57
+ day: d.getDate(),
58
+ month: d.toLocaleString("en-US", { month: "long" }),
59
+ year: d.getFullYear(),
60
+ time: d.toLocaleTimeString("en-US", {
61
+ hour: "2-digit",
62
+ minute: "2-digit",
63
+ hour12: true,
64
+ }),
65
+ };
66
+ };
67
+
68
+ const { day, month, year, time } = getDateParts(eventDateTime);
69
+
70
+ const DETAILS_START = fps * 4;
71
+
72
+ /* ================= IMAGE ANIMATION ================= */
73
+ const showImageAfter = fadeInDuration * 2;
74
+
75
+ const imageOpacity = interpolate(
76
+ frame,
77
+ [showImageAfter, showImageAfter + fps * 1.2],
78
+ [0, 1],
79
+ {
80
+ extrapolateRight: "clamp",
81
+ easing: Easing.out(Easing.ease),
82
+ }
83
+ );
84
+
85
+ const imageScale = interpolate(
86
+ frame,
87
+ [showImageAfter, showImageAfter + fps * 1.2],
88
+ [0.95, 1],
89
+ {
90
+ extrapolateRight: "clamp",
91
+ easing: Easing.out(Easing.cubic),
92
+ }
93
+ );
94
+ const imageTranslateY = interpolate(
95
+ frame,
96
+ [showImageAfter, showImageAfter + fps * 1.2],
97
+ [-200, 0], // 🔥 starts above and comes down
98
+ {
99
+ extrapolateRight: "clamp",
100
+ easing: Easing.out(Easing.ease),
101
+ }
102
+ );
103
+
104
+ return (
105
+ <AbsoluteFill
106
+ style={{
107
+ opacity: sceneOpacity,
108
+ transform: `scale(${sceneScale})`,
109
+ transformOrigin: "center center",
110
+ overflow: "hidden",
111
+ }}
112
+ >
113
+ {/* ================= BACKGROUND ================= */}
114
+ <Img
115
+ src={staticFile("video-images/20012026-bg.png")}
116
+ style={{
117
+ position: "absolute",
118
+ width: "100%",
119
+ height: "100%",
120
+ objectFit: "cover",
121
+
122
+ }}
123
+ />
124
+ <Img
125
+ src={staticFile("video-images/20012026-wedding-gate.png")}
126
+ style={{
127
+ position: "absolute",
128
+ top: 0,
129
+ left: "50%",
130
+ width: "100%",
131
+ height: "100%",
132
+ opacity: imageOpacity,
133
+ transform: `
134
+ translateX(-50%)
135
+ translateY(${imageTranslateY}px)
136
+ scale(${imageScale})
137
+ `,
138
+ }}
139
+ />
140
+
141
+ <GroomBrideLoveScene20012026 startAfter={3.5} />
142
+
143
+ <div
144
+ style={{
145
+ position: "absolute",
146
+ top: "24%",
147
+ width: "100%",
148
+ display: "flex",
149
+ flexDirection: "column",
150
+ alignItems: "center",
151
+ textAlign: "center",
152
+ zIndex: 5,
153
+ gap: "30px"
154
+ }}
155
+ >
156
+ <div
157
+ style={{
158
+ maxWidth: "50%",
159
+ fontFamily: "Playfair Display",
160
+ fontSize: 55,
161
+ fontWeight: "600",
162
+ color: "#3B2F2F",
163
+ lineHeight: 1.2,
164
+ letterSpacing: "2px",
165
+ whiteSpace: "normal",
166
+ wordBreak: "break-word",
167
+ overflowWrap: "break-word",
168
+ ...SmoothRevealFromTop({
169
+ frame,
170
+ startFrame: DETAILS_START,
171
+ delay: 0,
172
+ })
173
+ }}
174
+ >
175
+ {venueName}
176
+ </div>
177
+
178
+ <div
179
+ style={{
180
+ maxWidth: "80%",
181
+ fontFamily: "Playfair Display",
182
+ fontSize: 50,
183
+ fontWeight: "600",
184
+ color: "#5A4A42",
185
+ lineHeight: 1.2,
186
+ letterSpacing: "2px",
187
+ whiteSpace: "normal",
188
+ wordBreak: "break-word",
189
+ overflowWrap: "break-word",
190
+ ...SmoothRevealFromTop({
191
+ frame,
192
+ startFrame: DETAILS_START,
193
+ delay: 25,
194
+ })
195
+
196
+ }}
197
+ >
198
+ {venueAddress}
199
+ </div>
200
+ <div
201
+ style={{
202
+ fontFamily: "Great Vibes",
203
+ fontSize: 55,
204
+ fontWeight: "600",
205
+ color: "#6B1E2E",
206
+ lineHeight: 1.2,
207
+ letterSpacing: "3px",
208
+ whiteSpace: "normal",
209
+ wordBreak: "break-word",
210
+ overflowWrap: "break-word",
211
+ ...SmoothRevealFromTop({
212
+ frame,
213
+ startFrame: DETAILS_START,
214
+ delay: 50,
215
+ })
216
+
217
+ }}
218
+ >
219
+ On the joyous occasion
220
+ </div>
221
+ <div
222
+ style={{
223
+ maxWidth: "80%",
224
+ display: "flex",
225
+ gap: 18,
226
+ fontFamily: "Playfair Display",
227
+ fontSize: 50,
228
+ fontWeight: "600",
229
+ color: "#6B1E2E",
230
+ lineHeight: 1.2,
231
+ letterSpacing: "2px",
232
+ whiteSpace: "normal",
233
+ wordBreak: "break-word",
234
+ overflowWrap: "break-word",
235
+ ...SmoothRevealFromTop({
236
+ frame,
237
+ startFrame: DETAILS_START,
238
+ delay: 70,
239
+ })
240
+
241
+ }}
242
+ >
243
+ <span>{day}</span>
244
+ <span>{month}</span>
245
+ <span>{year}</span>
246
+ </div>
247
+ <div
248
+ style={{
249
+ fontFamily: "Great Vibes",
250
+ fontSize: 55,
251
+ fontWeight: "600",
252
+ color: "#4B3A28",
253
+ lineHeight: 1.2,
254
+ letterSpacing: "2px",
255
+ whiteSpace: "normal",
256
+ wordBreak: "break-word",
257
+ overflowWrap: "break-word",
258
+ ...SmoothRevealFromTop({
259
+ frame,
260
+ startFrame: DETAILS_START,
261
+ delay: 95,
262
+ })
263
+
264
+ }}
265
+ >
266
+ Wedding Time
267
+ </div>
268
+ <div
269
+ style={{
270
+ fontSize: 50,
271
+ fontWeight: "600",
272
+ color: "#4B3A28",
273
+ fontFamily: "Playfair Display",
274
+ lineHeight: 1.2,
275
+ letterSpacing: "2px",
276
+ whiteSpace: "normal",
277
+ wordBreak: "break-word",
278
+ overflowWrap: "break-word",
279
+ ...SmoothRevealFromTop({
280
+ frame,
281
+ startFrame: DETAILS_START,
282
+ delay: 115,
283
+ })
284
+
285
+ }}
286
+ >
287
+ {time}
288
+ </div>
289
+
290
+ <div
291
+ style={{
292
+ maxWidth: "70%",
293
+ fontFamily: "Playfair Display",
294
+ fontSize: 40,
295
+ fontWeight: "600",
296
+ lineHeight: 1.2,
297
+ color: "#7A5C3E",
298
+ lineHeight: 1.2,
299
+ letterSpacing: "2px",
300
+ whiteSpace: "normal",
301
+ wordBreak: "break-word",
302
+ overflowWrap: "break-word",
303
+ ...SmoothRevealFromTop({
304
+ frame,
305
+ startFrame: DETAILS_START,
306
+ delay: 125,
307
+ })
308
+
309
+ }}
310
+ >
311
+ {familyMember}
312
+ </div>
313
+ </div>
314
+
315
+ </AbsoluteFill>
316
+ );
317
+ };
@@ -0,0 +1,125 @@
1
+ import React from "react";
2
+ import { Sequence, useVideoConfig, Audio, staticFile } from "remotion";
3
+ import { F20012026_01 } from "../Frames/F20012026_01.jsx";
4
+ import { F20012026_02 } from "../Frames/F20012026_02.jsx";
5
+ import { F20012026_03 } from "../Frames/F20012026_03.jsx";
6
+ import { InkSmokeTransition20012026 } from "../Elements/InkSmokeTransition20012026.jsx";
7
+
8
+ export const T20012026_01 = ({
9
+ event,
10
+ formData,
11
+ eventDateTime,
12
+ occasionDate,
13
+ venue,
14
+ welcomeMessage,
15
+ invitationMessage,
16
+ familyMember,
17
+ }) => {
18
+ const { durationInFrames } = useVideoConfig();
19
+
20
+ // Detect creator safely
21
+ const whoIsCreating =
22
+ event?.occasion_data?.who_is_creating ??
23
+ event?.who_is_creating;
24
+
25
+ const isBrideCreating =
26
+ whoIsCreating === "Bride" || !whoIsCreating;
27
+
28
+ // Names
29
+ const brideName =
30
+ event?.occasion_data?.bride_name ??
31
+ event?.bride_name ??
32
+ formData?.bride_name ??
33
+ "";
34
+
35
+ const groomName =
36
+ event?.occasion_data?.groom_name ??
37
+ event?.groom_name ??
38
+ formData?.groom_name ??
39
+ "";
40
+
41
+ const firstName = isBrideCreating ? brideName : groomName;
42
+ const secondName = isBrideCreating ? groomName : brideName;
43
+
44
+ // Side notes (safe)
45
+ const firstSideNote = isBrideCreating
46
+ ? formData?.bride_side_note || ""
47
+ : formData?.groom_side_note || "";
48
+
49
+ const secondSideNote = isBrideCreating
50
+ ? formData?.groom_side_note || ""
51
+ : formData?.bride_side_note || "";
52
+
53
+ // Venue (safe)
54
+ const venueName =
55
+ venue?.name || formData?.venue_name || "";
56
+
57
+ const venueAddress =
58
+ venue?.address || formData?.venue_address || "";
59
+
60
+
61
+ const framesPerPage = Math.floor(durationInFrames / 3);
62
+ const transitionDuration = Math.floor(framesPerPage * 0.25); // ~1 sec
63
+
64
+ return (
65
+ <>
66
+ {/* 🎵 Background Music */}
67
+ <Audio
68
+ src={staticFile("video-images/wedding.mp3")}
69
+ startFrom={30}
70
+ endAt={900}
71
+ volume={0.4}
72
+ />
73
+ <Sequence from={0} durationInFrames={framesPerPage}>
74
+ <F20012026_01
75
+ firstName={firstName}
76
+ secondName={secondName}
77
+ welcomeMessage={welcomeMessage}
78
+ eventDateTime={eventDateTime}
79
+ />
80
+ </Sequence>
81
+
82
+ <Sequence
83
+ from={framesPerPage}
84
+ durationInFrames={framesPerPage}
85
+ >
86
+ <F20012026_02
87
+ firstName={firstName}
88
+ secondName={secondName}
89
+ firstSideNote={firstSideNote}
90
+ secondSideNote={secondSideNote}
91
+ invitationMessage={invitationMessage}
92
+ occasionDate={occasionDate}
93
+ fadeInDuration={transitionDuration}
94
+ />
95
+ </Sequence>
96
+
97
+ {/* 🎨 INK / SMOKE TRANSITION OVERLAY */}
98
+ <Sequence
99
+ from={framesPerPage}
100
+ durationInFrames={transitionDuration}
101
+ >
102
+ <InkSmokeTransition20012026 />
103
+ </Sequence>
104
+
105
+ <Sequence from={framesPerPage * 2} durationInFrames={framesPerPage}>
106
+ <F20012026_03
107
+ eventDateTime={eventDateTime}
108
+ venueName={venueName}
109
+ venueAddress={venueAddress}
110
+ familyMember={familyMember}
111
+ />
112
+ </Sequence>
113
+
114
+ {/* ☁️ SMOKE TRANSITION: SCENE 2 ➜ SCENE 3 */}
115
+ <Sequence
116
+ from={framesPerPage * 2}
117
+ durationInFrames={transitionDuration}
118
+ >
119
+ <InkSmokeTransition20012026 />
120
+ </Sequence>
121
+
122
+
123
+ </>
124
+ );
125
+ };
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+ import { Composition } from "remotion";
3
+ import { T20012026_01 } from "./Invitations/Themes/T20012026_01.jsx";
4
+
5
+ export const VideoCompositions = () => {
6
+ return (
7
+ <>
8
+ <Composition
9
+ id="T20012026_01"
10
+ component={T20012026_01}
11
+ durationInFrames={30 * 30}
12
+ fps={30}
13
+ width={1080}
14
+ height={1920}
15
+ />
16
+ </>
17
+ );
18
+ };
19
+
@@ -0,0 +1,3 @@
1
+ import { registerFonts } from "./registerFonts";
2
+
3
+ registerFonts();
@@ -0,0 +1,46 @@
1
+
2
+ import { staticFile } from "remotion";
3
+
4
+ let registered = false;
5
+
6
+ export const registerFonts = () => {
7
+ if (registered) return;
8
+ registered = true;
9
+
10
+ const fonts = [
11
+ {
12
+ family: "Great Vibes",
13
+ url: staticFile("Fonts/GreatVibes-Regular.ttf"),
14
+ format: "truetype",
15
+ weight: "400",
16
+ },
17
+ {
18
+ family: "Dancing Script",
19
+ url: staticFile("Fonts/DancingScript-VariableFont_wght.ttf"
20
+ ),
21
+ format: "truetype",
22
+ weight: "100 700",
23
+ },
24
+ {
25
+ family: "Playfair Display",
26
+ url: staticFile("Fonts/PlayfairDisplay-Italic-VariableFont_wght.ttf"
27
+ ),
28
+ format: "truetype",
29
+ weight: "100 900",
30
+ },
31
+ ];
32
+
33
+ Promise.allSettled(
34
+ fonts.map(async (font) => {
35
+ const fontFace = new FontFace(
36
+ font.family,
37
+ `url('${font.url}') format('${font.format}')`,
38
+ { weight: font.weight }
39
+ );
40
+ await fontFace.load();
41
+ document.fonts.add(fontFace);
42
+ })
43
+ ).catch(() => {
44
+ // Ignore font loading errors; rendering should continue.
45
+ });
46
+ };
package/src/index.js ADDED
@@ -0,0 +1,2 @@
1
+ // Preview-only exports (PURE components)
2
+ export { T20012026_01 } from "./Invitations/Themes/T20012026_01.jsx";
@@ -0,0 +1,5 @@
1
+ import { registerRoot } from "remotion";
2
+ import { VideoCompositions } from "./compositions.jsx";
3
+ import "./fonts";
4
+
5
+ registerRoot(VideoCompositions);