@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,68 @@
1
+ import React from "react";
2
+ import {
3
+ Img,
4
+ staticFile,
5
+ useCurrentFrame,
6
+ useVideoConfig,
7
+ interpolate,
8
+ } from "remotion";
9
+
10
+ export const PeacockDance20012026 = ({
11
+ startAfter = 0,
12
+ durationInSeconds = 12
13
+ }) => {
14
+ const frame = useCurrentFrame();
15
+ const { fps } = useVideoConfig();
16
+
17
+ const delay = fps * startAfter;
18
+
19
+ if (frame < delay) return null;
20
+
21
+ const movementDuration = fps * durationInSeconds;
22
+
23
+ // 1. Horizontal Movement (Right to Left)
24
+ const leftPos = interpolate(
25
+ frame,
26
+ [delay, delay + movementDuration],
27
+ [80, -100],
28
+ {
29
+ extrapolateLeft: "clamp",
30
+ extrapolateRight: "clamp"
31
+ }
32
+ );
33
+
34
+ // 2. WALK CYCLE ANIMATION
35
+ const stepSpeed = 6;
36
+ const walkBounce = Math.abs(Math.sin((frame - delay) / stepSpeed)) * -15;
37
+
38
+ // 3. SQUASH AND STRETCH (Adds weight to the walk)
39
+ const squash = interpolate(
40
+ Math.sin((frame - delay) / stepSpeed),
41
+ [-1, 1],
42
+ [0.95, 1.05]
43
+ );
44
+
45
+ const baseScale = interpolate(
46
+ frame,
47
+ [delay, delay + fps],
48
+ [0.85, 1],
49
+ { extrapolateLeft: "clamp" }
50
+ );
51
+
52
+ return (
53
+ <Img
54
+ src={staticFile("video-images/20012026-peacock.png")}
55
+ style={{
56
+ position: "absolute",
57
+ top: "55%",
58
+ left: `${leftPos}%`,
59
+ transform: `
60
+ translateY(${walkBounce}px)
61
+ scaleX(${baseScale})
62
+ scaleY(${baseScale * squash})
63
+ `,
64
+ width: "60%",
65
+ }}
66
+ />
67
+ );
68
+ };
@@ -0,0 +1,104 @@
1
+ import React from "react";
2
+ import {
3
+ Img,
4
+ staticFile,
5
+ useCurrentFrame,
6
+ useVideoConfig,
7
+ interpolate,
8
+ Easing,
9
+ } from "remotion";
10
+
11
+ export const SideTrees20012026 = ({ startAfter = 1 }) => {
12
+ const frame = useCurrentFrame();
13
+ const { fps } = useVideoConfig();
14
+
15
+ const delay = fps * startAfter;
16
+ const duration = fps * 1.2;
17
+
18
+ /* ---------------- FADE IN ---------------- */
19
+ const opacity = interpolate(
20
+ frame,
21
+ [delay, delay + duration],
22
+ [0, 1],
23
+ {
24
+ extrapolateLeft: "clamp",
25
+ extrapolateRight: "clamp",
26
+ easing: Easing.out(Easing.ease),
27
+ }
28
+ );
29
+
30
+ /* ---------------- SLIDE IN ---------------- */
31
+ const leftTreeX = interpolate(
32
+ frame,
33
+ [delay, delay + duration],
34
+ [-600, -380], // hidden → edge
35
+ {
36
+ extrapolateLeft: "clamp",
37
+ extrapolateRight: "clamp",
38
+ easing: Easing.out(Easing.ease),
39
+ }
40
+ );
41
+
42
+ const rightTreeX = interpolate(
43
+ frame,
44
+ [delay, delay + duration],
45
+ [600, 380], // hidden → edge
46
+ {
47
+ extrapolateLeft: "clamp",
48
+ extrapolateRight: "clamp",
49
+ easing: Easing.out(Easing.ease),
50
+ }
51
+ );
52
+
53
+ /* ---------------- 🌬️ TREE SWING (WIND) ---------------- */
54
+ const swingSpeed = 20; // higher = slower swing
55
+ const swingAngle = 2; // degrees (keep small)
56
+
57
+ const swing =
58
+ frame > delay
59
+ ? Math.sin((frame - delay) / swingSpeed) * swingAngle
60
+ : 0;
61
+
62
+ const swayX =
63
+ frame > delay
64
+ ? Math.sin((frame - delay) / (swingSpeed * 1.3)) * 6
65
+ : 0;
66
+
67
+ return (
68
+ <>
69
+ {/* 🌳 LEFT TREE */}
70
+ <Img
71
+ src={staticFile("video-images/20012026-tree-left.png")}
72
+ style={{
73
+ position: "absolute",
74
+ left: 0,
75
+ bottom: 0,
76
+ height: "100%",
77
+ opacity,
78
+ transform: `
79
+ translateX(${leftTreeX + swayX}px)
80
+ rotate(${swing}deg)
81
+ `,
82
+ transformOrigin: "bottom left", // 🌳 root fixed
83
+ }}
84
+ />
85
+
86
+ {/* 🌳 RIGHT TREE */}
87
+ <Img
88
+ src={staticFile("video-images/20012026-tree-right.png")}
89
+ style={{
90
+ position: "absolute",
91
+ right: 0,
92
+ bottom: 0,
93
+ height: "100%",
94
+ opacity,
95
+ transform: `
96
+ translateX(${rightTreeX - swayX}px)
97
+ rotate(${-swing}deg)
98
+ `,
99
+ transformOrigin: "bottom right", // 🌳 root fixed
100
+ }}
101
+ />
102
+ </>
103
+ );
104
+ };
@@ -0,0 +1,32 @@
1
+ import { interpolate, Easing } from "remotion";
2
+
3
+ export const SmoothRevealFromTop = ({
4
+ frame,
5
+ startFrame,
6
+ delay = 0,
7
+ duration = 20,
8
+ fromY = -30,
9
+ toY = 0,
10
+ }) => {
11
+ const opacity = interpolate(
12
+ frame,
13
+ [startFrame + delay, startFrame + delay + duration],
14
+ [0, 1],
15
+ { extrapolateRight: "clamp" }
16
+ );
17
+
18
+ const translateY = interpolate(
19
+ frame,
20
+ [startFrame + delay, startFrame + delay + duration],
21
+ [fromY, toY],
22
+ {
23
+ extrapolateRight: "clamp",
24
+ easing: Easing.out(Easing.ease),
25
+ }
26
+ );
27
+
28
+ return {
29
+ opacity,
30
+ transform: `translateY(${translateY}px)`,
31
+ };
32
+ };
@@ -0,0 +1,180 @@
1
+ import React from "react";
2
+ import {
3
+ AbsoluteFill,
4
+ Img,
5
+ useCurrentFrame,
6
+ useVideoConfig,
7
+ interpolate,
8
+ Easing,
9
+ staticFile
10
+ } from "remotion";
11
+
12
+ import { Butterflies20012026 } from "../Elements/Butterflies20012026.jsx";
13
+ import { OpeningGate20012026 } from "../Elements/OpeningGate20012026.jsx";
14
+ import { CoupleWalk20012026 } from "../Elements/CoupleWalk20012026.jsx";
15
+ import {FlowersSide20012026} from "../Elements/FlowersSide20012026.jsx";
16
+
17
+ export const F20012026_01 = ({
18
+ firstName, secondName, welcomeMessage,
19
+ }) => {
20
+ /* -------------------- HOOKS (ONLY HERE) -------------------- */
21
+ const frame = useCurrentFrame();
22
+ const { fps, width, height, durationInFrames } = useVideoConfig();
23
+
24
+ /* -------------------- MESSAGE REVEAL -------------------- */
25
+ const messageStart = fps * 4;
26
+ const messageOpacity = interpolate(
27
+ frame,
28
+ [messageStart, messageStart + 15],
29
+ [0, 1],
30
+ { extrapolateRight: "clamp" }
31
+ );
32
+ const messageTranslateY = interpolate(
33
+ frame,
34
+ [messageStart, messageStart + 30],
35
+ [60, 0],
36
+ {
37
+ extrapolateRight: "clamp",
38
+ easing: Easing.out(Easing.cubic),
39
+ }
40
+ );
41
+ /* -------------------- NAME ANIMATIONS -------------------- */
42
+ const brideStart = messageStart + fps * 1;
43
+ const wedsStart = brideStart + fps * 0.6;
44
+ const groomStart = wedsStart + fps * 0.6;
45
+
46
+ const reveal = (start) => ({
47
+ opacity: interpolate(frame, [start, start + 20], [0, 1], {
48
+ extrapolateRight: "clamp",
49
+ }),
50
+ translateY: interpolate(frame, [start, start + 25], [40, 0], {
51
+ extrapolateRight: "clamp",
52
+ easing: Easing.out(Easing.cubic),
53
+ }),
54
+ });
55
+
56
+ const brideAnim = reveal(brideStart);
57
+ const wedsAnim = reveal(wedsStart);
58
+ const groomAnim = reveal(groomStart);
59
+ return (
60
+ <AbsoluteFill style={{ overflow: "hidden" }}>
61
+ {/* ================= BACKGROUND ================= */}
62
+ <Img
63
+ src={staticFile("video-images/20012026-bg.png")}
64
+ style={{
65
+ position: "absolute",
66
+ width: "100%",
67
+ height: "100%",
68
+ objectFit: "cover",
69
+ }}
70
+ />
71
+
72
+ {/* ================= VISUAL LAYERS ================= */}
73
+ <Butterflies20012026 frame={frame} fps={fps} width={width} height={height} />
74
+ <OpeningGate20012026 frame={frame} fps={fps} />
75
+ <CoupleWalk20012026 frame={frame} fps={fps} />
76
+ <FlowersSide20012026 frame={frame} fps={fps} />
77
+
78
+ {/* ================= TEXT LAYER (DIV) ================= */}
79
+ <div
80
+ style={{
81
+ position: "absolute",
82
+ inset: 0,
83
+ display: "flex",
84
+ flexDirection: "column",
85
+ alignItems: "center",
86
+ textAlign: "center",
87
+ pointerEvents: "none",
88
+ zIndex: 10,
89
+ marginTop: "40%",
90
+ gap: "30px"
91
+ }}
92
+ >
93
+ {/* ----------- MESSAGE ----------- */}
94
+ <div
95
+ style={{
96
+ width: "100%",
97
+ maxWidth: "70%",
98
+ fontSize: 60,
99
+ fontFamily: "Dancing Script",
100
+ letterSpacing: "3px",
101
+ color: "#6D4C6A",
102
+ fontWeight: "700",
103
+ lineHeight: 1.2,
104
+ opacity: messageOpacity,
105
+ transform: `translateY(${messageTranslateY}px)`,
106
+ }}
107
+ >
108
+ {welcomeMessage}
109
+ </div>
110
+
111
+ {/* ----------- NAMES ----------- */}
112
+ <div
113
+ style={{
114
+ width: "100%",
115
+ display: "flex",
116
+ flexDirection: "column",
117
+ alignItems: "center",
118
+ }}
119
+ >
120
+ <h1
121
+ style={{
122
+ width: "100%",
123
+ maxWidth: "80%",
124
+ marginTop: "10px",
125
+ fontFamily: "Playfair Display",
126
+ color: "#6B1E2E",
127
+ fontSize: 60,
128
+ fontWeight: "600",
129
+ lineHeight: 1.3,
130
+ letterSpacing: "2px",
131
+ textAlign: "center",
132
+ whiteSpace: "normal",
133
+ wordBreak: "break-word",
134
+ overflowWrap: "break-word",
135
+ opacity: brideAnim.opacity,
136
+ transform: `translateY(${brideAnim.translateY}px)`,
137
+ }}
138
+ >
139
+ {firstName}
140
+ </h1>
141
+
142
+ <h2
143
+ style={{
144
+ fontSize: 70,
145
+ fontFamily: "Great Vibes",
146
+ color: "#D4AF37",
147
+ margin: "10px 0",
148
+ opacity: wedsAnim.opacity,
149
+ transform: `translateY(${wedsAnim.translateY}px)`,
150
+ }}
151
+ >
152
+ weds
153
+ </h2>
154
+
155
+ <h1
156
+ style={{
157
+ width: "100%",
158
+ maxWidth: "80%",
159
+ fontFamily: "Playfair Display",
160
+ color: "#6B1E2E",
161
+ fontSize: 60,
162
+ fontWeight: "600",
163
+ lineHeight: 1.3,
164
+ letterSpacing: "2px",
165
+ textAlign: "center",
166
+ whiteSpace: "normal",
167
+ wordBreak: "break-word",
168
+ overflowWrap: "break-word",
169
+ opacity: groomAnim.opacity,
170
+ transform: `translateY(${groomAnim.translateY}px)`,
171
+
172
+ }}
173
+ >
174
+ {secondName}
175
+ </h1>
176
+ </div>
177
+ </div>
178
+ </AbsoluteFill>
179
+ );
180
+ };
@@ -0,0 +1,311 @@
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 { SideTrees20012026 } from "../Elements/SideTrees20012026.jsx";
13
+ import { PeacockDance20012026 } from "../Elements/PeacockDance20012026.jsx";
14
+ import { SmoothRevealFromTop } from "../Elements/SmoothRevealFromTop.jsx";
15
+
16
+ export const F20012026_02 = ({ firstName, secondName,firstSideNote,secondSideNote, invitationMessage ,occasionDate,fadeInDuration = 30,
17
+ }) => {
18
+ const frame = useCurrentFrame();
19
+ const { fps } = useVideoConfig();
20
+
21
+ /* ================= SCENE FADE + ZOOM ================= */
22
+ const sceneOpacity = interpolate(
23
+ frame,
24
+ [0, fadeInDuration],
25
+ [0, 1],
26
+ {
27
+ extrapolateRight: "clamp",
28
+ easing: Easing.out(Easing.ease),
29
+ }
30
+ );
31
+
32
+ // 🎥 VERY SMOOTH CINEMATIC ZOOM
33
+ const sceneScale = interpolate(
34
+ frame,
35
+ [0, fadeInDuration * 2],
36
+ [1.20, 1],
37
+ {
38
+ extrapolateRight: "clamp",
39
+ easing: Easing.out(Easing.cubic),
40
+ }
41
+ );
42
+
43
+ /* ================= SAFE DATE FORMAT ================= */
44
+ const formatDate = (date) => {
45
+ if (!date) return "";
46
+ const d = new Date(date);
47
+ if (isNaN(d.getTime())) return "";
48
+
49
+ return d.toLocaleDateString("en-IN", {
50
+ day: "numeric",
51
+ month: "long",
52
+ year: "numeric",
53
+ });
54
+ };
55
+
56
+
57
+ const DETAILS_START = fps * 3;
58
+
59
+ /* ================= IMAGE ANIMATION ================= */
60
+ const showImageAfter = fadeInDuration * 1;
61
+
62
+ const imageOpacity = interpolate(
63
+ frame,
64
+ [showImageAfter, showImageAfter + fps],
65
+ [0, 1],
66
+ {
67
+ extrapolateRight: "clamp",
68
+ easing: Easing.out(Easing.ease),
69
+ }
70
+ );
71
+
72
+ const imageScale = interpolate(
73
+ frame,
74
+ [showImageAfter, showImageAfter + fps],
75
+ [0.92, 1],
76
+ {
77
+ extrapolateRight: "clamp",
78
+ easing: Easing.out(Easing.ease),
79
+ }
80
+ );
81
+
82
+ return (
83
+ <AbsoluteFill
84
+ style={{
85
+ opacity: sceneOpacity,
86
+ transform: `scale(${sceneScale})`,
87
+ transformOrigin: "center center",
88
+ overflow: "hidden",
89
+
90
+ }}
91
+ >
92
+ {/* ================= BACKGROUND ================= */}
93
+ <Img
94
+ src={staticFile("video-images/20012026-bg.png")}
95
+ style={{
96
+ position: "absolute",
97
+ width: "100%",
98
+ height: "100%",
99
+ objectFit: "cover",
100
+ }}
101
+ />
102
+
103
+ <Img
104
+ src={staticFile("video-images/20012026-curtain-floral.png")}
105
+ style={{
106
+ position: "absolute",
107
+ left: "50%",
108
+ width: "100%",
109
+ opacity: imageOpacity,
110
+ transform: `translateX(-50%) scale(${imageScale})`,
111
+ }}
112
+ />
113
+
114
+ {/* ================= DECORATIONS ================= */}
115
+ <SideTrees20012026 startAfter={2} />
116
+ <PeacockDance20012026 startAfter={3} />
117
+
118
+ <div
119
+ style={{
120
+ position: "relative",
121
+ top: "26%",
122
+ width: "100%",
123
+ display: "flex",
124
+ flexDirection: "column",
125
+ alignItems: "center",
126
+ textAlign: "center",
127
+ gap: "15px"
128
+ }}
129
+ >
130
+ {/* Invitation Message */}
131
+ <div
132
+ style={{
133
+ maxWidth: "50%",
134
+ fontFamily: "Dancing Script",
135
+ color: "#4A3A2A",
136
+ fontSize: 40,
137
+ fontWeight: "500",
138
+ lineHeight: 1.2,
139
+ letterSpacing: "2px",
140
+ ...SmoothRevealFromTop({
141
+ frame,
142
+ startFrame: DETAILS_START,
143
+ delay: 0,
144
+ })
145
+ }}
146
+ >
147
+ {invitationMessage}
148
+ </div>
149
+
150
+ {/* Bride Name */}
151
+ <h1
152
+ style={{
153
+ maxWidth: "70%",
154
+ fontFamily: "Playfair Display",
155
+ color: "#7A1E2E",
156
+ fontSize: 60,
157
+ fontWeight: "600",
158
+ lineHeight: 1.2,
159
+ letterSpacing: "3px",
160
+ whiteSpace: "normal",
161
+ wordBreak: "break-word",
162
+ overflowWrap: "break-word",
163
+ ...SmoothRevealFromTop({
164
+ frame,
165
+ startFrame: DETAILS_START,
166
+ delay: 25,
167
+ })
168
+ }}
169
+ >
170
+ {firstName}
171
+ </h1>
172
+
173
+ {/* Bride Side Note */}
174
+ <div
175
+ style={{
176
+ maxWidth: "60%",
177
+ fontFamily: "Dancing Script",
178
+ color: "#B87A6A",
179
+ fontSize: 40,
180
+ fontWeight: "600",
181
+ lineHeight: 1.2,
182
+ letterSpacing: "2px",
183
+ whiteSpace: "normal",
184
+ wordBreak: "break-word",
185
+ overflowWrap: "break-word",
186
+ ...SmoothRevealFromTop({
187
+ frame,
188
+ startFrame: DETAILS_START,
189
+ delay: 50,
190
+ })
191
+ }}
192
+ >
193
+ {firstSideNote}
194
+ </div>
195
+
196
+ {/* & Symbol */}
197
+ <div
198
+ style={{
199
+ fontSize: 40,
200
+ color: "#C9A24D",
201
+ letterSpacing: "6px",
202
+ ...SmoothRevealFromTop({
203
+ frame,
204
+ startFrame: DETAILS_START,
205
+ delay: 70,
206
+ })
207
+ }}
208
+ >
209
+ ❁ ❁ ❁
210
+ </div>
211
+
212
+
213
+ {/* Groom Name */}
214
+ <h1
215
+ style={{
216
+ maxWidth: "70%",
217
+ fontFamily: "Playfair Display",
218
+ color: "#7A1E2E",
219
+ fontSize: 60,
220
+ fontWeight: "600",
221
+ lineHeight: 1.2,
222
+ letterSpacing: "3px",
223
+ whiteSpace: "normal",
224
+ wordBreak: "break-word",
225
+ overflowWrap: "break-word",
226
+ ...SmoothRevealFromTop({
227
+ frame,
228
+ startFrame: DETAILS_START,
229
+ delay: 95,
230
+ })
231
+ }}
232
+ >
233
+ {secondName}
234
+ </h1>
235
+
236
+ {/* Groom Side Note */}
237
+ <div
238
+ style={{
239
+ maxWidth: "70%",
240
+ fontFamily: "Dancing Script",
241
+ color: "#B87A6A",
242
+ fontSize: 40,
243
+ fontWeight: "600",
244
+ lineHeight: 1.2,
245
+ letterSpacing: "2px",
246
+ whiteSpace: "normal",
247
+ wordBreak: "break-word",
248
+ overflowWrap: "break-word",
249
+ ...SmoothRevealFromTop({
250
+ frame,
251
+ startFrame: DETAILS_START,
252
+ delay: 120,
253
+ })
254
+ }}
255
+ >
256
+ {secondSideNote}
257
+ </div>
258
+
259
+ {/* Date */}
260
+ <div
261
+ style={{
262
+ maxWidth: "70%",
263
+ marginTop: 20,
264
+ textAlign: "center",
265
+ ...SmoothRevealFromTop({
266
+ frame,
267
+ startFrame: DETAILS_START,
268
+ delay: 145,
269
+ })
270
+ }}
271
+ >
272
+ {/* -------- Message Line -------- */}
273
+ <div
274
+ style={{
275
+ fontSize: 45,
276
+ fontFamily:"Great Vibes",
277
+ fontWeight: "500",
278
+ letterSpacing: "3px",
279
+ color: "#2F6B4F",
280
+ lineHeight: 1.2,
281
+ marginBottom: 8,
282
+ whiteSpace: "nowrap",
283
+
284
+ }}
285
+ >
286
+ – Join us on this auspicious day –
287
+ </div>
288
+
289
+ {/* -------- Date Line -------- */}
290
+ <div
291
+ style={{
292
+ fontSize: 55,
293
+ fontFamily:"Playfair Display",
294
+ fontWeight: "400",
295
+ color: "#5A4632",
296
+ lineHeight: 1.2,
297
+ letterSpacing: "4px",
298
+ whiteSpace: "nowrap", // 🔥 force single line
299
+ }}
300
+ >
301
+ {formatDate(occasionDate)}
302
+ </div>
303
+ </div>
304
+
305
+
306
+ </div>
307
+
308
+
309
+ </AbsoluteFill>
310
+ );
311
+ };