hyperframes 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/cli.js +22905 -0
  2. package/dist/docs/compositions.md +26 -0
  3. package/dist/docs/data-attributes.md +22 -0
  4. package/dist/docs/gsap.md +23 -0
  5. package/dist/docs/rendering.md +23 -0
  6. package/dist/docs/templates.md +15 -0
  7. package/dist/docs/troubleshooting.md +22 -0
  8. package/dist/hyperframe-runtime.js +12 -0
  9. package/dist/studio/assets/index-B1830ANq.js +78 -0
  10. package/dist/studio/assets/index-KoBceNoU.css +1 -0
  11. package/dist/studio/icons/timeline/audio.svg +7 -0
  12. package/dist/studio/icons/timeline/captions.svg +5 -0
  13. package/dist/studio/icons/timeline/composition.svg +12 -0
  14. package/dist/studio/icons/timeline/image.svg +18 -0
  15. package/dist/studio/icons/timeline/music.svg +10 -0
  16. package/dist/studio/icons/timeline/text.svg +3 -0
  17. package/dist/studio/index.html +13 -0
  18. package/dist/templates/play-mode/compositions/captions.html +97 -0
  19. package/dist/templates/play-mode/compositions/intro.html +88 -0
  20. package/dist/templates/play-mode/compositions/stats.html +252 -0
  21. package/dist/templates/play-mode/index.html +173 -0
  22. package/dist/templates/swiss-grid/assets/swiss-grid.svg +116 -0
  23. package/dist/templates/swiss-grid/compositions/captions.html +95 -0
  24. package/dist/templates/swiss-grid/compositions/graphics.html +198 -0
  25. package/dist/templates/swiss-grid/compositions/intro.html +114 -0
  26. package/dist/templates/swiss-grid/index.html +172 -0
  27. package/dist/templates/vignelli/compositions/captions.html +122 -0
  28. package/dist/templates/vignelli/compositions/overlays.html +271 -0
  29. package/dist/templates/vignelli/index.html +171 -0
  30. package/dist/templates/warm-grain/compositions/captions.html +133 -0
  31. package/dist/templates/warm-grain/compositions/graphics.html +157 -0
  32. package/dist/templates/warm-grain/compositions/intro.html +77 -0
  33. package/dist/templates/warm-grain/index.html +195 -0
  34. package/package.json +54 -0
@@ -0,0 +1,171 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Massimo Vignelli Video</title>
6
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
7
+ <style>
8
+ body,
9
+ html {
10
+ margin: 0;
11
+ padding: 0;
12
+ background: #FFFFFF;
13
+ overflow: hidden;
14
+ width: 1080px;
15
+ height: 1920px;
16
+ font-family: 'Helvetica', Arial, sans-serif;
17
+ }
18
+
19
+ /* 6-Column Grid System */
20
+ .grid-container {
21
+ position: absolute;
22
+ top: 0;
23
+ left: 0;
24
+ width: 1080px;
25
+ height: 1920px;
26
+ display: grid;
27
+ grid-template-columns: repeat(6, 1fr);
28
+ pointer-events: none;
29
+ z-index: 1000;
30
+ opacity: 0; /* Keep grid invisible but present for layout references */
31
+ }
32
+
33
+ .grid-column {
34
+ border-right: 1px solid rgba(204, 0, 0, 0.2); /* Vignelli Red accent */
35
+ }
36
+
37
+ #main-composition {
38
+ position: relative;
39
+ width: 1080px;
40
+ height: 1920px;
41
+ background: #FFFFFF;
42
+ overflow: hidden;
43
+ }
44
+
45
+ /* Layer Hosts */
46
+ #a-roll-wrapper {
47
+ position: absolute;
48
+ top: 0;
49
+ left: 0;
50
+ width: 100%;
51
+ height: 100%;
52
+ z-index: 10;
53
+ overflow: hidden;
54
+ }
55
+
56
+ #a-roll,
57
+ #a-roll-wrapper img.__render_frame__,
58
+ #a-roll-wrapper img.__preview_render_frame__ {
59
+ position: absolute;
60
+ inset: 0;
61
+ width: 100%;
62
+ height: 100%;
63
+ object-fit: cover;
64
+ }
65
+
66
+ #overlays-comp,
67
+ #captions-comp {
68
+ position: absolute;
69
+ top: 0;
70
+ left: 0;
71
+ width: 1080px;
72
+ height: 1920px;
73
+ pointer-events: none;
74
+ }
75
+
76
+ #overlays-comp {
77
+ z-index: 20;
78
+ }
79
+
80
+ #captions-comp {
81
+ z-index: 30;
82
+ }
83
+
84
+ /* Curtain Transition Layer */
85
+ .curtain {
86
+ position: absolute;
87
+ top: 0;
88
+ left: -100%;
89
+ width: 100%;
90
+ height: 100%;
91
+ background: #1A1A1A;
92
+ z-index: 25;
93
+ pointer-events: none;
94
+ }
95
+
96
+ .curtain.red {
97
+ background: #CC0000;
98
+ z-index: 26;
99
+ }
100
+
101
+ </style>
102
+ </head>
103
+ <body>
104
+ <div id="main-composition" data-composition-id="main-comp" data-width="1080" data-height="1920" data-duration="13.88">
105
+
106
+ <!-- A-Roll -->
107
+ <div id="a-roll-wrapper">
108
+ <video id="a-roll"
109
+ src="__VIDEO_SRC__"
110
+ data-start="0"
111
+ data-duration="13.88"
112
+ data-track-index="0">
113
+ </video>
114
+ </div>
115
+
116
+ <!-- Transitions -->
117
+ <div id="curtain-black" class="curtain"></div>
118
+ <div id="curtain-red" class="curtain red"></div>
119
+
120
+ <!-- Overlays Composition -->
121
+ <div id="overlays-comp"
122
+ data-composition-id="overlays"
123
+ data-composition-src="compositions/overlays.html"
124
+ data-start="0"
125
+ data-duration="13.88"
126
+ data-track-index="2">
127
+ </div>
128
+
129
+ <!-- Captions Composition -->
130
+ <div id="captions-comp"
131
+ data-composition-id="captions"
132
+ data-composition-src="compositions/captions.html"
133
+ data-start="0"
134
+ data-duration="13.88"
135
+ data-track-index="3">
136
+ </div>
137
+
138
+ <!-- Grid Visualization -->
139
+ <div class="grid-container">
140
+ <div class="grid-column"></div>
141
+ <div class="grid-column"></div>
142
+ <div class="grid-column"></div>
143
+ <div class="grid-column"></div>
144
+ <div class="grid-column"></div>
145
+ <div class="grid-column"></div>
146
+ </div>
147
+
148
+ <script>
149
+ const tl = gsap.timeline({ paused: true });
150
+
151
+ // Transition: Curtain Pull logic
152
+ // A-roll leaves the screen at least once.
153
+ // Timing: Let's do a curtain pull at 3.7s (transitioning to the 62% stat)
154
+ // and return at 7.3s (end of attention stat).
155
+
156
+ // Curtain Out (A-roll hidden)
157
+ tl.to("#curtain-black", { left: "0%", duration: 0.2, ease: "power2.inOut" }, 3.5);
158
+ tl.to("#a-roll-wrapper", { opacity: 0, duration: 0 }, 3.7);
159
+ tl.to("#curtain-black", { left: "100%", duration: 0.4, ease: "power2.inOut" }, 3.7);
160
+
161
+ // Curtain In (A-roll return)
162
+ tl.set("#curtain-red", { left: "-100%" }, 7.1);
163
+ tl.to("#curtain-red", { left: "0%", duration: 0.2, ease: "power2.inOut" }, 7.1);
164
+ tl.to("#a-roll-wrapper", { opacity: 1, duration: 0 }, 7.3);
165
+ tl.to("#curtain-red", { left: "100%", duration: 0.4, ease: "power2.inOut" }, 7.3);
166
+
167
+ window.__timelines["main-comp"] = tl;
168
+ </script>
169
+ </div>
170
+ </body>
171
+ </html>
@@ -0,0 +1,133 @@
1
+ <template id="captions-template">
2
+ <div data-composition-id="captions" data-width="1920" data-height="1080" data-duration="18">
3
+ <div class="captions-container">
4
+ <div id="caption-box" class="caption-box">
5
+ <span id="caption-text" class="caption-text"></span>
6
+ </div>
7
+ </div>
8
+
9
+ <style>
10
+ [data-composition-id="captions"] .captions-container {
11
+ width: 100%;
12
+ height: 100%;
13
+ display: flex;
14
+ justify-content: center;
15
+ align-items: flex-end;
16
+ padding-bottom: 230px; /* Position at y: 850 (1080 - 230 = 850) */
17
+ pointer-events: none;
18
+ }
19
+
20
+ [data-composition-id="captions"] .caption-box {
21
+ background-color: #7A6248;
22
+ padding: 12px 32px;
23
+ border-radius: 24px;
24
+ display: flex;
25
+ justify-content: center;
26
+ align-items: center;
27
+ min-width: 100px;
28
+ max-width: 80%;
29
+ opacity: 0;
30
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
31
+ }
32
+
33
+ [data-composition-id="captions"] .caption-text {
34
+ color: #F5F0E0;
35
+ font-family: 'Outfit', sans-serif;
36
+ font-size: 48px;
37
+ font-weight: 700;
38
+ text-align: center;
39
+ line-height: 1.2;
40
+ white-space: nowrap;
41
+ }
42
+ </style>
43
+
44
+ <script>
45
+ (function() {
46
+ const script = [
47
+ {"text": "We", "start": 0.119, "end": 0.259},
48
+ {"text": "asked", "start": 0.319, "end": 0.479},
49
+ {"text": "what", "start": 0.519, "end": 0.659},
50
+ {"text": "you", "start": 0.699, "end": 0.819},
51
+ {"text": "needed.", "start": 0.859, "end": 1.819},
52
+ {"text": "Forty-seven", "start": 1.86, "end": 2.299},
53
+ {"text": "percent", "start": 2.399, "end": 2.679},
54
+ {"text": "of", "start": 2.7, "end": 2.799},
55
+ {"text": "you", "start": 2.839, "end": 2.939},
56
+ {"text": "said", "start": 3.039, "end": 3.179},
57
+ {"text": "motion", "start": 3.24, "end": 3.559},
58
+ {"text": "graphics,", "start": 3.579, "end": 4.599},
59
+ {"text": "sixty-two", "start": 4.679, "end": 5.179},
60
+ {"text": "percent", "start": 5.299, "end": 5.759},
61
+ {"text": "said", "start": 5.859, "end": 5.98},
62
+ {"text": "static", "start": 6.079, "end": 6.399},
63
+ {"text": "content", "start": 6.46, "end": 6.879},
64
+ {"text": "was", "start": 6.92, "end": 7.079},
65
+ {"text": "costing", "start": 7.099, "end": 7.48},
66
+ {"text": "you", "start": 7.5, "end": 7.579},
67
+ {"text": "attention,", "start": 7.679, "end": 8.659},
68
+ {"text": "and", "start": 8.699, "end": 8.86},
69
+ {"text": "three", "start": 8.88, "end": 9.06},
70
+ {"text": "out", "start": 9.079, "end": 9.18},
71
+ {"text": "of", "start": 9.199, "end": 9.34},
72
+ {"text": "four", "start": 9.38, "end": 9.799},
73
+ {"text": "said", "start": 9.84, "end": 10.0},
74
+ {"text": "you", "start": 10.019, "end": 10.159},
75
+ {"text": "know", "start": 10.179, "end": 10.36},
76
+ {"text": "the", "start": 10.38, "end": 10.42},
77
+ {"text": "look", "start": 10.519, "end": 10.699},
78
+ {"text": "you", "start": 10.739, "end": 10.859},
79
+ {"text": "want", "start": 10.98, "end": 11.34},
80
+ {"text": "but", "start": 11.359, "end": 11.52},
81
+ {"text": "don't", "start": 11.56, "end": 11.779},
82
+ {"text": "have", "start": 11.819, "end": 11.94},
83
+ {"text": "the", "start": 11.96, "end": 12.06},
84
+ {"text": "editing", "start": 12.079, "end": 12.4},
85
+ {"text": "skills", "start": 12.52, "end": 12.86},
86
+ {"text": "to", "start": 12.88, "end": 13.0},
87
+ {"text": "get", "start": 13.019, "end": 13.18},
88
+ {"text": "there.", "start": 13.22, "end": 14.22},
89
+ {"text": "So", "start": 14.239, "end": 14.399},
90
+ {"text": "we", "start": 14.42, "end": 14.52},
91
+ {"text": "built", "start": 14.619, "end": 14.88},
92
+ {"text": "Hyperframes.", "start": 15.079, "end": 16.02}
93
+ ];
94
+
95
+ // Group words into lines (max 5 words per line)
96
+ const lines = [];
97
+ for (let i = 0; i < script.length; i += 5) {
98
+ const lineWords = script.slice(i, i + 5);
99
+ lines.push({
100
+ text: lineWords.map(w => w.text).join(' '),
101
+ start: lineWords[0].start,
102
+ end: lineWords[lineWords.length - 1].end
103
+ });
104
+ }
105
+
106
+ const tl = gsap.timeline({ paused: true });
107
+ const box = document.querySelector('[data-composition-id="captions"] #caption-box');
108
+ const textEl = document.querySelector('[data-composition-id="captions"] #caption-text');
109
+
110
+ lines.forEach((line, index) => {
111
+ // Fade in and set text
112
+ tl.to(box, {
113
+ opacity: 1,
114
+ duration: 0.1,
115
+ ease: "power2.out",
116
+ onStart: () => {
117
+ textEl.textContent = line.text;
118
+ }
119
+ }, line.start);
120
+
121
+ // Fade out at the end of the line
122
+ tl.to(box, {
123
+ opacity: 0,
124
+ duration: 0.1,
125
+ ease: "power2.in"
126
+ }, line.end);
127
+ });
128
+
129
+ window.__timelines["captions"] = tl;
130
+ })();
131
+ </script>
132
+ </div>
133
+ </template>
@@ -0,0 +1,157 @@
1
+ <template id="graphics-template">
2
+ <div data-composition-id="graphics" data-width="1920" data-height="1080" data-duration="14">
3
+ <!-- Moment 1: 47% Stat (1.8s - 4.5s) -->
4
+ <div id="moment-1" class="moment circle-stat">
5
+ <div class="stat-content">
6
+ <div class="stat-text">47%</div>
7
+ <div class="stat-desc">Need Motion Graphics</div>
8
+ </div>
9
+ </div>
10
+
11
+ <!-- Moment 2: 62% Stat (4.6s - 8.6s) -->
12
+ <div id="moment-2" class="moment pill-stat">
13
+ <div class="stat-text">62%</div>
14
+ </div>
15
+
16
+ <!-- Moment 3: Editing Skills (8.8s - 14s) -->
17
+ <div id="moment-3" class="moment rect-stat">
18
+ <div class="icon-shape">
19
+ <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
20
+ <path d="M20,20 Q50,0 80,20 Q100,50 80,80 Q50,100 20,80 Q0,50 20,20" fill="currentColor" />
21
+ </svg>
22
+ </div>
23
+ <div class="stat-text">Editing Skills</div>
24
+ </div>
25
+
26
+ <style>
27
+ [data-composition-id="graphics"] {
28
+ position: relative;
29
+ width: 1920px;
30
+ height: 1080px;
31
+ font-family: 'Outfit', sans-serif;
32
+ color: white;
33
+ overflow: hidden;
34
+ }
35
+
36
+ [data-composition-id="graphics"] .moment {
37
+ position: absolute;
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: center;
41
+ opacity: 0;
42
+ /* We'll use GSAP to handle the centering and drift */
43
+ }
44
+
45
+ /* Moment 1: Forest Green Circle */
46
+ [data-composition-id="graphics"] #moment-1 {
47
+ width: 500px;
48
+ height: 500px;
49
+ background-color: #3B5E3A;
50
+ border-radius: 50%;
51
+ left: 1400px;
52
+ top: 540px;
53
+ transform: translate(-50%, -50%);
54
+ }
55
+
56
+ [data-composition-id="graphics"] .stat-content {
57
+ display: flex;
58
+ flex-direction: column;
59
+ align-items: center;
60
+ text-align: center;
61
+ }
62
+
63
+ [data-composition-id="graphics"] .stat-desc {
64
+ font-size: 36px;
65
+ font-weight: 400;
66
+ margin-top: 10px;
67
+ max-width: 300px;
68
+ line-height: 1.2;
69
+ }
70
+
71
+ /* Moment 2: Ochre Pill */
72
+ [data-composition-id="graphics"] #moment-2 {
73
+ width: 500px;
74
+ height: 220px;
75
+ background-color: #CC8832;
76
+ border-radius: 110px;
77
+ left: 960px;
78
+ top: 200px;
79
+ transform: translate(-50%, -50%);
80
+ }
81
+
82
+ /* Moment 3: Terracotta Rounded Rect */
83
+ [data-composition-id="graphics"] #moment-3 {
84
+ width: 550px;
85
+ height: 180px;
86
+ background-color: #C45D3E;
87
+ border-radius: 40px;
88
+ left: 400px;
89
+ top: 540px;
90
+ transform: translate(-50%, -50%);
91
+ padding: 0 40px;
92
+ justify-content: center;
93
+ gap: 30px;
94
+ }
95
+
96
+ [data-composition-id="graphics"] .stat-text {
97
+ font-size: 80px;
98
+ font-weight: 700;
99
+ letter-spacing: -2px;
100
+ }
101
+
102
+ [data-composition-id="graphics"] #moment-3 .stat-text {
103
+ font-size: 54px;
104
+ letter-spacing: -1px;
105
+ }
106
+
107
+ [data-composition-id="graphics"] .icon-shape {
108
+ width: 80px;
109
+ height: 80px;
110
+ color: rgba(255, 255, 255, 0.9);
111
+ }
112
+
113
+ [data-composition-id="graphics"] .icon-shape svg {
114
+ width: 100%;
115
+ height: 100%;
116
+ }
117
+ </style>
118
+
119
+ <script>
120
+ (function() {
121
+ const tl = gsap.timeline({ paused: true });
122
+
123
+ // Moment 1: 1.8s - 4.5s
124
+ // Gentle drift into place and settle
125
+ tl.fromTo('#moment-1',
126
+ { opacity: 0, x: '+=40', y: '+=15', scale: 0.8 },
127
+ { opacity: 1, x: 0, y: 0, scale: 1, duration: 1.2, ease: 'back.out(1.7)' },
128
+ 1.8
129
+ );
130
+ // Hold until 4.5s, then fade out
131
+ tl.to('#moment-1', { opacity: 0, scale: 0.8, duration: 0.3, ease: 'power2.in' }, 4.2);
132
+
133
+ // Moment 2: 4.6s - 8.6s
134
+ // Gentle drift into place and settle
135
+ tl.fromTo('#moment-2',
136
+ { opacity: 0, y: '-=40', x: '+=10', scale: 0.8 },
137
+ { opacity: 1, y: 0, x: 0, scale: 1, duration: 1.2, ease: 'back.out(1.7)' },
138
+ 4.6
139
+ );
140
+ // Hold until 8.6s, then fade out
141
+ tl.to('#moment-2', { opacity: 0, scale: 0.8, duration: 0.3, ease: 'power2.in' }, 8.3);
142
+
143
+ // Moment 3: 8.8s - 14s
144
+ // Gentle drift into place and settle
145
+ tl.fromTo('#moment-3',
146
+ { opacity: 0, x: '-=40', y: '-=10', scale: 0.8 },
147
+ { opacity: 1, x: 0, y: 0, scale: 1, duration: 1.2, ease: 'back.out(1.7)' },
148
+ 8.8
149
+ );
150
+ // Hold until end (14s)
151
+ tl.to('#moment-3', { opacity: 0, duration: 0.5, ease: 'power2.in' }, 13.5);
152
+
153
+ window.__timelines["graphics"] = tl;
154
+ })();
155
+ </script>
156
+ </div>
157
+ </template>
@@ -0,0 +1,77 @@
1
+ <template id="intro-template">
2
+ <div data-composition-id="intro" data-width="1920" data-height="1080" data-duration="3">
3
+ <div class="container">
4
+ <div class="title-card">
5
+ <h1 class="title">Hyperframes</h1>
6
+ <p class="subtitle">Design simplified.</p>
7
+ </div>
8
+ </div>
9
+
10
+ <style>
11
+ /* Import a rounded humanist sans-serif font */
12
+ @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;600&display=swap');
13
+
14
+ [data-composition-id="intro"] .container {
15
+ width: 100%;
16
+ height: 100%;
17
+ display: flex;
18
+ justify-content: flex-start; /* Align to left for speaker card */
19
+ align-items: center;
20
+ padding-left: 5%;
21
+ font-family: 'Outfit', sans-serif;
22
+ background: transparent;
23
+ }
24
+
25
+ [data-composition-id="intro"] .title-card {
26
+ background-color: #3B5E3A; /* Forest Green for contrast */
27
+ padding: 40px 60px;
28
+ border-radius: 30px;
29
+ box-shadow: 0 15px 40px rgba(0,0,0,0.2);
30
+ text-align: left;
31
+ opacity: 0;
32
+ transform: translateX(-100%); /* Start off-screen left */
33
+ }
34
+
35
+ [data-composition-id="intro"] .title {
36
+ font-size: 100px;
37
+ font-weight: 600;
38
+ color: #F5F0E0; /* Cream text on green card */
39
+ margin: 0;
40
+ line-height: 1.1;
41
+ letter-spacing: -2px;
42
+ }
43
+
44
+ [data-composition-id="intro"] .subtitle {
45
+ font-size: 50px;
46
+ font-weight: 400;
47
+ color: #CC8832; /* Ochre accent */
48
+ margin: 10px 0 0 0;
49
+ line-height: 1.2;
50
+ }
51
+ </style>
52
+
53
+ <script>
54
+ (function() {
55
+ const tl = gsap.timeline({ paused: true });
56
+
57
+ // Animation: Speaker card slides in from the left
58
+ tl.to('[data-composition-id="intro"] .title-card', {
59
+ opacity: 1,
60
+ x: 0,
61
+ duration: 0.8,
62
+ ease: 'power2.out'
63
+ }, 0.2);
64
+
65
+ // Exit: Slide off left at 1.8s (synced with 47% graphic)
66
+ tl.to('[data-composition-id="intro"] .title-card', {
67
+ x: '-120%',
68
+ opacity: 0,
69
+ duration: 0.6,
70
+ ease: 'power2.in'
71
+ }, 1.8);
72
+
73
+ window.__timelines["intro"] = tl;
74
+ })();
75
+ </script>
76
+ </div>
77
+ </template>