hyperframes 0.1.1 → 0.1.4

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 (31) hide show
  1. package/README.md +121 -0
  2. package/dist/cli.js +2755 -1167
  3. package/dist/docs/compositions.md +8 -1
  4. package/dist/docs/data-attributes.md +4 -0
  5. package/dist/docs/gsap.md +3 -0
  6. package/dist/docs/rendering.md +4 -0
  7. package/dist/docs/templates.md +4 -0
  8. package/dist/docs/troubleshooting.md +7 -0
  9. package/dist/hyperframe-runtime.js +4 -3
  10. package/dist/hyperframe.manifest.json +22 -0
  11. package/dist/hyperframe.runtime.iife.js +13 -0
  12. package/dist/studio/index.html +11 -11
  13. package/dist/templates/blank/compositions/captions.html +92 -0
  14. package/dist/templates/blank/index.html +44 -0
  15. package/dist/templates/play-mode/compositions/captions.html +96 -30
  16. package/dist/templates/play-mode/compositions/intro.html +90 -71
  17. package/dist/templates/play-mode/compositions/stats.html +210 -74
  18. package/dist/templates/play-mode/index.html +214 -148
  19. package/dist/templates/swiss-grid/compositions/captions.html +70 -17
  20. package/dist/templates/swiss-grid/compositions/graphics.html +52 -43
  21. package/dist/templates/swiss-grid/compositions/intro.html +42 -25
  22. package/dist/templates/swiss-grid/index.html +227 -165
  23. package/dist/templates/vignelli/compositions/captions.html +87 -28
  24. package/dist/templates/vignelli/compositions/overlays.html +83 -31
  25. package/dist/templates/vignelli/index.html +183 -164
  26. package/dist/templates/warm-grain/compositions/captions.html +80 -66
  27. package/dist/templates/warm-grain/compositions/graphics.html +29 -22
  28. package/dist/templates/warm-grain/compositions/intro.html +29 -20
  29. package/dist/templates/warm-grain/index.html +278 -179
  30. package/package.json +16 -15
  31. package/LICENSE +0 -21
@@ -1,172 +1,234 @@
1
- <!DOCTYPE html>
1
+ <!doctype html>
2
2
  <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Swiss Grid - Hyperframes</title>
7
7
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
8
8
  <style>
9
- body, html {
10
- margin: 0;
11
- padding: 0;
12
- width: 1920px;
13
- height: 1080px;
14
- background-color: #F2F2F2;
15
- overflow: hidden;
16
- font-family: 'Helvetica', Arial, sans-serif;
17
- }
18
-
19
- #master-root {
20
- width: 1920px;
21
- height: 1080px;
22
- position: relative;
23
- }
24
-
25
- .background-grid {
26
- position: absolute;
27
- top: 0;
28
- left: 0;
29
- width: 100%;
30
- height: 100%;
31
- z-index: 0;
32
- }
33
-
34
- /* A-roll styling */
35
- #short_mag_cut_frame {
36
- position: absolute;
37
- border-radius: 8px; /* Required */
38
- z-index: 1;
39
- box-shadow: 0 20px 40px rgba(0,0,0,0.3);
40
- overflow: hidden;
41
- background: #000;
42
- }
43
-
44
- #short_mag_cut,
45
- #short_mag_cut_frame > img.__render_frame__,
46
- #short_mag_cut_frame > img.__preview_render_frame__ {
47
- position: absolute;
48
- inset: 0;
49
- width: 100%;
50
- height: 100%;
51
- object-fit: cover;
52
- object-position: center;
53
- display: block;
54
- }
55
-
56
- /* Overlay layers */
57
- .overlay-layer {
58
- position: absolute;
59
- top: 0;
60
- left: 0;
61
- width: 100%;
62
- height: 100%;
63
- pointer-events: none;
64
- }
65
-
66
- #intro-comp { z-index: 2; }
67
- #graphics-comp { z-index: 3; }
68
- #captions-comp { z-index: 4; }
9
+ body,
10
+ html {
11
+ margin: 0;
12
+ padding: 0;
13
+ width: 1920px;
14
+ height: 1080px;
15
+ background-color: #f2f2f2;
16
+ overflow: hidden;
17
+ font-family: "Helvetica", Arial, sans-serif;
18
+ }
19
+
20
+ #master-root {
21
+ width: 1920px;
22
+ height: 1080px;
23
+ position: relative;
24
+ }
25
+
26
+ .background-grid {
27
+ position: absolute;
28
+ top: 0;
29
+ left: 0;
30
+ width: 100%;
31
+ height: 100%;
32
+ z-index: 0;
33
+ }
34
+
35
+ /* A-roll styling */
36
+ #short_mag_cut_frame {
37
+ position: absolute;
38
+ border-radius: 8px; /* Required */
39
+ z-index: 1;
40
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
41
+ overflow: hidden;
42
+ background: #000;
43
+ }
44
+
45
+ #short_mag_cut,
46
+ #short_mag_cut_frame > img.__render_frame__,
47
+ #short_mag_cut_frame > img.__preview_render_frame__ {
48
+ position: absolute;
49
+ inset: 0;
50
+ width: 100%;
51
+ height: 100%;
52
+ object-fit: cover;
53
+ object-position: center;
54
+ display: block;
55
+ }
56
+
57
+ /* Overlay layers */
58
+ .overlay-layer {
59
+ position: absolute;
60
+ top: 0;
61
+ left: 0;
62
+ width: 100%;
63
+ height: 100%;
64
+ pointer-events: none;
65
+ }
66
+
67
+ #intro-comp {
68
+ z-index: 2;
69
+ }
70
+ #graphics-comp {
71
+ z-index: 3;
72
+ }
73
+ #captions-comp {
74
+ z-index: 4;
75
+ }
69
76
  </style>
70
- </head>
71
- <body>
72
- <div id="master-root" data-composition-id="master" data-width="1920" data-height="1080" data-duration="16.04">
73
-
74
- <!-- Background Grid -->
75
- <img id="bg-grid"
76
- class="background-grid"
77
- src="assets/swiss-grid.svg"
78
- alt="Grid"
79
- data-start="0"
80
- data-duration="16.04"
81
- data-track-index="0">
82
-
83
- <!-- A-roll Video -->
84
- <div id="short_mag_cut_frame">
85
- <video id="short_mag_cut"
86
- src="__VIDEO_SRC__"
87
- data-start="0"
88
- data-duration="16.04"
89
- data-track-index="1">
90
- </video>
91
- </div>
92
-
93
- <!-- Intro Sub-composition -->
94
- <div id="intro-comp"
95
- class="overlay-layer"
96
- data-composition-id="intro"
97
- data-composition-src="compositions/intro.html"
98
- data-start="0"
99
- data-duration="1.86"
100
- data-track-index="2">
101
- </div>
102
-
103
- <!-- Graphics Sub-composition -->
104
- <div id="graphics-comp"
105
- class="overlay-layer"
106
- data-composition-id="graphics"
107
- data-composition-src="compositions/graphics.html"
108
- data-start="0"
109
- data-duration="16.04"
110
- data-track-index="3">
111
- </div>
112
-
113
- <!-- Captions Sub-composition -->
114
- <div id="captions-comp"
115
- class="overlay-layer"
116
- data-composition-id="captions"
117
- data-composition-src="compositions/captions.html"
118
- data-start="0"
119
- data-duration="16.04"
120
- data-track-index="4">
121
- </div>
122
-
123
- <!-- Sound Effects -->
124
- <audio id="sfx-intro" data-start="0" data-track-index="5" data-duration="1" src=""></audio>
125
- <audio id="sfx-stat1" data-start="1.86" data-track-index="5" data-duration="1" src=""></audio>
126
- <audio id="sfx-stat2" data-start="4.68" data-track-index="5" data-duration="1" src=""></audio>
127
- <audio id="sfx-stat3" data-start="8.88" data-track-index="5" data-duration="1" src=""></audio>
128
-
129
- <script>
130
- window.__timelines = window.__timelines || {};
131
-
132
- const masterTL = gsap.timeline({ paused: true });
133
- const v = document.getElementById('short_mag_cut_frame');
134
-
135
- // --- A-ROLL MOVEMENT (Structured Swiss Layout) ---
136
-
137
- // 1. Entrance (0-1.86s): Slide in from left, settle centered for Intro
138
- masterTL.fromTo(v,
139
- { x: -1000, y: 120, width: 960, height: 840 },
140
- { x: 480, y: 120, width: 960, height: 840, duration: 0.8, ease: "power2.out" },
141
- 0
142
- );
143
-
144
- // 2. Stat 1 (1.86s - 4.68s): Move to right side (Graphic is on left)
145
- masterTL.to(v, {
146
- x: 1080, y: 120, width: 720, height: 720,
147
- duration: 0.25, ease: "expo.out"
148
- }, 1.86);
149
-
150
- // 3. Stat 2 (4.68s - 8.88s): Stay right, zoom in slightly
151
- masterTL.to(v, {
152
- x: 1080, y: 60, width: 780, height: 780,
153
- duration: 0.25, ease: "expo.out"
154
- }, 4.68);
155
-
156
- // 4. Stat 3 (8.88s - 14.2s): Move to left side (Graphic is on right)
157
- masterTL.to(v, {
158
- x: 120, y: 120, width: 720, height: 720,
159
- duration: 0.25, ease: "expo.out"
160
- }, 8.88);
161
-
162
- // 5. Conclusion (14.2s - 16.04s): Center large
163
- masterTL.to(v, {
164
- x: 240, y: 60, width: 1440, height: 810,
165
- duration: 0.5, ease: "expo.out"
166
- }, 14.2);
167
-
168
- window.__timelines["master"] = masterTL;
169
- </script>
77
+ </head>
78
+ <body>
79
+ <div
80
+ id="master-root"
81
+ data-composition-id="master"
82
+ data-width="1920"
83
+ data-height="1080"
84
+ data-start="0"
85
+ data-duration="__VIDEO_DURATION__"
86
+ >
87
+ <!-- Background Grid -->
88
+ <img
89
+ id="bg-grid"
90
+ class="background-grid"
91
+ src="assets/swiss-grid.svg"
92
+ alt="Grid"
93
+ data-start="0"
94
+ data-duration="__VIDEO_DURATION__"
95
+ data-track-index="0"
96
+ />
97
+
98
+ <!-- A-roll Video -->
99
+ <div id="short_mag_cut_frame">
100
+ <video
101
+ id="short_mag_cut"
102
+ src="__VIDEO_SRC__"
103
+ muted
104
+ playsinline
105
+ data-start="0"
106
+ data-duration="__VIDEO_DURATION__"
107
+ data-track-index="1"
108
+ ></video>
109
+ </div>
110
+ <audio
111
+ id="a-roll-audio"
112
+ src="__VIDEO_SRC__"
113
+ data-start="0"
114
+ data-duration="__VIDEO_DURATION__"
115
+ data-track-index="5"
116
+ data-volume="1"
117
+ ></audio>
118
+
119
+ <!-- Intro Sub-composition -->
120
+ <div
121
+ id="intro-comp"
122
+ class="overlay-layer"
123
+ data-composition-id="intro"
124
+ data-composition-src="compositions/intro.html"
125
+ data-start="0"
126
+ data-duration="1.86"
127
+ data-track-index="2"
128
+ ></div>
129
+
130
+ <!-- Graphics Sub-composition -->
131
+ <div
132
+ id="graphics-comp"
133
+ class="overlay-layer"
134
+ data-composition-id="graphics"
135
+ data-composition-src="compositions/graphics.html"
136
+ data-start="0"
137
+ data-duration="__VIDEO_DURATION__"
138
+ data-track-index="3"
139
+ ></div>
140
+
141
+ <!-- Captions Sub-composition -->
142
+ <div
143
+ id="captions-comp"
144
+ class="overlay-layer"
145
+ data-composition-id="captions"
146
+ data-composition-src="compositions/captions.html"
147
+ data-start="0"
148
+ data-duration="__VIDEO_DURATION__"
149
+ data-track-index="4"
150
+ ></div>
151
+
152
+ <!-- Sound Effects (src set dynamically; omitted to avoid 404s) -->
153
+ <audio id="sfx-intro" data-start="0" data-track-index="5" data-duration="1"></audio>
154
+ <audio id="sfx-stat1" data-start="1.86" data-track-index="5" data-duration="1"></audio>
155
+ <audio id="sfx-stat2" data-start="4.68" data-track-index="5" data-duration="1"></audio>
156
+ <audio id="sfx-stat3" data-start="8.88" data-track-index="5" data-duration="1"></audio>
157
+
158
+ <script>
159
+ window.__timelines = window.__timelines || {};
160
+
161
+ const masterTL = gsap.timeline({ paused: true });
162
+ const v = document.getElementById("short_mag_cut_frame");
163
+
164
+ // --- A-ROLL MOVEMENT (Structured Swiss Layout) ---
165
+
166
+ // 1. Entrance (0-1.86s): Slide in from left, settle centered for Intro
167
+ masterTL.fromTo(
168
+ v,
169
+ { x: -1000, y: 120, width: 960, height: 840 },
170
+ { x: 480, y: 120, width: 960, height: 840, duration: 0.8, ease: "power2.out" },
171
+ 0,
172
+ );
173
+
174
+ // 2. Stat 1 (1.86s - 4.68s): Move to right side (Graphic is on left)
175
+ masterTL.to(
176
+ v,
177
+ {
178
+ x: 1080,
179
+ y: 120,
180
+ width: 720,
181
+ height: 720,
182
+ duration: 0.25,
183
+ ease: "expo.out",
184
+ },
185
+ 1.86,
186
+ );
187
+
188
+ // 3. Stat 2 (4.68s - 8.88s): Stay right, zoom in slightly
189
+ masterTL.to(
190
+ v,
191
+ {
192
+ x: 1080,
193
+ y: 60,
194
+ width: 780,
195
+ height: 780,
196
+ duration: 0.25,
197
+ ease: "expo.out",
198
+ },
199
+ 4.68,
200
+ );
201
+
202
+ // 4. Stat 3 (8.88s - 14.2s): Move to left side (Graphic is on right)
203
+ masterTL.to(
204
+ v,
205
+ {
206
+ x: 120,
207
+ y: 120,
208
+ width: 720,
209
+ height: 720,
210
+ duration: 0.25,
211
+ ease: "expo.out",
212
+ },
213
+ 8.88,
214
+ );
215
+
216
+ // 5. Conclusion (14.2s - 16.04s): Center large
217
+ masterTL.to(
218
+ v,
219
+ {
220
+ x: 240,
221
+ y: 60,
222
+ width: 1440,
223
+ height: 810,
224
+ duration: 0.5,
225
+ ease: "expo.out",
226
+ },
227
+ 14.2,
228
+ );
229
+
230
+ window.__timelines["master"] = masterTL;
231
+ </script>
170
232
  </div>
171
- </body>
233
+ </body>
172
234
  </html>
@@ -1,5 +1,10 @@
1
1
  <template id="captions-template">
2
- <div data-composition-id="captions" data-width="1080" data-height="1920" data-duration="13.88">
2
+ <div
3
+ data-composition-id="captions"
4
+ data-width="1080"
5
+ data-height="1920"
6
+ data-duration="__VIDEO_DURATION__"
7
+ >
3
8
  <div id="captions-container"></div>
4
9
 
5
10
  <style>
@@ -39,9 +44,9 @@
39
44
  font-size: 64px;
40
45
  line-height: 1.1;
41
46
  color: #000000;
42
- background-color: #FFFFFF;
47
+ background-color: #ffffff;
43
48
  padding: 15px 30px;
44
- border-top: 8px solid #CC0000; /* Vignelli Red top border accent */
49
+ border-top: 8px solid #cc0000; /* Vignelli Red top border accent */
45
50
  display: inline-block;
46
51
  letter-spacing: -0.02em; /* Tight Helvetica spacing */
47
52
  white-space: nowrap; /* Prevent wrapping at the element level */
@@ -49,29 +54,77 @@
49
54
  </style>
50
55
 
51
56
  <script>
52
- (function() {
53
- const TRANSCRIPT = [{'text': 'We', 'start': 0.14, 'end': 0.239}, {'text': 'asked', 'start': 0.28, 'end': 0.459}, {'text': 'what', 'start': 0.5, 'end': 0.619}, {'text': 'you', 'start': 0.659, 'end': 0.779}, {'text': 'needed.', 'start': 0.8, 'end': 1.179}, {'text': 'Forty-seven', 'start': 1.199, 'end': 1.619}, {'text': 'percent', 'start': 1.699, 'end': 1.96}, {'text': 'of', 'start': 1.979, 'end': 2.059}, {'text': 'you', 'start': 2.099, 'end': 2.299}, {'text': 'said', 'start': 2.319, 'end': 2.499}, {'text': 'motion', 'start': 2.559, 'end': 2.839}, {'text': 'graphics,', 'start': 2.899, 'end': 3.759}, {'text': 'sixty-two', 'start': 3.799, 'end': 4.159}, {'text': 'percent', 'start': 4.239, 'end': 4.559}, {'text': 'said', 'start': 4.639, 'end': 4.799}, {'text': 'static', 'start': 4.859, 'end': 5.199}, {'text': 'content', 'start': 5.239, 'end': 5.639}, {'text': 'was', 'start': 5.679, 'end': 5.779}, {'text': 'costing', 'start': 5.859, 'end': 6.219}, {'text': 'you', 'start': 6.259, 'end': 6.339}, {'text': 'attention,', 'start': 6.379, 'end': 7.299}, {'text': 'and', 'start': 7.319, 'end': 7.439}, {'text': 'three', 'start': 7.48, 'end': 7.599}, {'text': 'out', 'start': 7.679, 'end': 7.779}, {'text': 'of', 'start': 7.799, 'end': 7.879}, {'text': 'four', 'start': 7.94, 'end': 8.139}, {'text': 'said', 'start': 8.279, 'end': 8.46}, {'text': 'you', 'start': 8.519, 'end': 8.6}, {'text': 'know', 'start': 8.619, 'end': 8.739}, {'text': 'the', 'start': 8.8, 'end': 8.88}, {'text': 'look', 'start': 8.92, 'end': 9.079}, {'text': 'you', 'start': 9.119, 'end': 9.259}, {'text': 'want', 'start': 9.279, 'end': 9.619}, {'text': 'but', 'start': 9.779, 'end': 9.88}, {'text': "don't", 'start': 9.92, 'end': 10.1}, {'text': 'have', 'start': 10.159, 'end': 10.3}, {'text': 'the', 'start': 10.3, 'end': 10.42}, {'text': 'editing', 'start': 10.5, 'end': 10.779}, {'text': 'skills', 'start': 10.86, 'end': 11.139}, {'text': 'to', 'start': 11.159, 'end': 11.239}, {'text': 'get', 'start': 11.279, 'end': 11.439}, {'text': 'there.', 'start': 11.46, 'end': 12.239}, {'text': 'So', 'start': 12.3, 'end': 12.38}, {'text': 'we', 'start': 12.399, 'end': 12.519}, {'text': 'built', 'start': 12.539, 'end': 12.759}, {'text': 'Hyperframes', 'start': 12.84, 'end': 13.119}];
57
+ (function () {
58
+ const TRANSCRIPT = [
59
+ { text: "We", start: 0.14, end: 0.239 },
60
+ { text: "asked", start: 0.28, end: 0.459 },
61
+ { text: "what", start: 0.5, end: 0.619 },
62
+ { text: "you", start: 0.659, end: 0.779 },
63
+ { text: "needed.", start: 0.8, end: 1.179 },
64
+ { text: "Forty-seven", start: 1.199, end: 1.619 },
65
+ { text: "percent", start: 1.699, end: 1.96 },
66
+ { text: "of", start: 1.979, end: 2.059 },
67
+ { text: "you", start: 2.099, end: 2.299 },
68
+ { text: "said", start: 2.319, end: 2.499 },
69
+ { text: "motion", start: 2.559, end: 2.839 },
70
+ { text: "graphics,", start: 2.899, end: 3.759 },
71
+ { text: "sixty-two", start: 3.799, end: 4.159 },
72
+ { text: "percent", start: 4.239, end: 4.559 },
73
+ { text: "said", start: 4.639, end: 4.799 },
74
+ { text: "static", start: 4.859, end: 5.199 },
75
+ { text: "content", start: 5.239, end: 5.639 },
76
+ { text: "was", start: 5.679, end: 5.779 },
77
+ { text: "costing", start: 5.859, end: 6.219 },
78
+ { text: "you", start: 6.259, end: 6.339 },
79
+ { text: "attention,", start: 6.379, end: 7.299 },
80
+ { text: "and", start: 7.319, end: 7.439 },
81
+ { text: "three", start: 7.48, end: 7.599 },
82
+ { text: "out", start: 7.679, end: 7.779 },
83
+ { text: "of", start: 7.799, end: 7.879 },
84
+ { text: "four", start: 7.94, end: 8.139 },
85
+ { text: "said", start: 8.279, end: 8.46 },
86
+ { text: "you", start: 8.519, end: 8.6 },
87
+ { text: "know", start: 8.619, end: 8.739 },
88
+ { text: "the", start: 8.8, end: 8.88 },
89
+ { text: "look", start: 8.92, end: 9.079 },
90
+ { text: "you", start: 9.119, end: 9.259 },
91
+ { text: "want", start: 9.279, end: 9.619 },
92
+ { text: "but", start: 9.779, end: 9.88 },
93
+ { text: "don't", start: 9.92, end: 10.1 },
94
+ { text: "have", start: 10.159, end: 10.3 },
95
+ { text: "the", start: 10.3, end: 10.42 },
96
+ { text: "editing", start: 10.5, end: 10.779 },
97
+ { text: "skills", start: 10.86, end: 11.139 },
98
+ { text: "to", start: 11.159, end: 11.239 },
99
+ { text: "get", start: 11.279, end: 11.439 },
100
+ { text: "there.", start: 11.46, end: 12.239 },
101
+ { text: "So", start: 12.3, end: 12.38 },
102
+ { text: "we", start: 12.399, end: 12.519 },
103
+ { text: "built", start: 12.539, end: 12.759 },
104
+ { text: "Hyperframes", start: 12.84, end: 13.119 },
105
+ ];
54
106
  const tl = gsap.timeline({ paused: true });
55
- const container = document.getElementById('captions-container');
107
+ const container = document.getElementById("captions-container");
56
108
 
57
109
  // Group words into single lines (max words or based on pauses/sentence ends)
58
110
  function groupTranscript(transcript, maxWords = 3) {
59
111
  const groups = [];
60
112
  let currentGroup = [];
61
-
113
+
62
114
  transcript.forEach((word, index) => {
63
115
  currentGroup.push(word);
64
-
116
+
65
117
  const nextWord = transcript[index + 1];
66
- const isPause = nextWord && (nextWord.start - word.end > 0.15);
67
- const isSentenceEnd = word.text.includes('.') || word.text.includes('?') || word.text.includes('!');
68
-
118
+ const isPause = nextWord && nextWord.start - word.end > 0.15;
119
+ const isSentenceEnd =
120
+ word.text.includes(".") || word.text.includes("?") || word.text.includes("!");
121
+
69
122
  if (currentGroup.length >= maxWords || isPause || isSentenceEnd || !nextWord) {
70
123
  groups.push({
71
124
  words: currentGroup,
72
125
  start: currentGroup[0].start,
73
126
  end: currentGroup[currentGroup.length - 1].end,
74
- text: currentGroup.map(w => w.text).join(' ')
127
+ text: currentGroup.map((w) => w.text).join(" "),
75
128
  });
76
129
  currentGroup = [];
77
130
  }
@@ -82,39 +135,45 @@
82
135
  const captionGroups = groupTranscript(TRANSCRIPT);
83
136
 
84
137
  captionGroups.forEach((group, index) => {
85
- const div = document.createElement('div');
86
- div.className = 'caption-group';
138
+ const div = document.createElement("div");
139
+ div.className = "caption-group";
87
140
  div.id = `group-${index}`;
88
-
89
- const textSpan = document.createElement('span');
90
- textSpan.className = 'caption-text';
141
+
142
+ const textSpan = document.createElement("span");
143
+ textSpan.className = "caption-text";
91
144
  textSpan.innerText = group.text;
92
-
145
+
93
146
  div.appendChild(textSpan);
94
147
  container.appendChild(div);
95
148
 
96
149
  // Animation: Modern "expo.out" transitions
97
150
  // Entrance
98
- tl.fromTo(div,
151
+ tl.fromTo(
152
+ div,
99
153
  { opacity: 0, y: 20 },
100
154
  {
101
155
  opacity: 1,
102
156
  y: 0,
103
157
  duration: 0.4,
104
- ease: "expo.out"
105
- },
106
- group.start
158
+ ease: "expo.out",
159
+ },
160
+ group.start,
107
161
  );
108
162
 
109
163
  // Exit
110
- tl.to(div, {
111
- opacity: 0,
112
- y: -10,
113
- duration: 0.3,
114
- ease: "expo.out"
115
- }, group.end - 0.3);
164
+ tl.to(
165
+ div,
166
+ {
167
+ opacity: 0,
168
+ y: -10,
169
+ duration: 0.3,
170
+ ease: "expo.out",
171
+ },
172
+ group.end - 0.3,
173
+ );
116
174
  });
117
175
 
176
+ window.__timelines = window.__timelines || {};
118
177
  window.__timelines["captions"] = tl;
119
178
  })();
120
179
  </script>