hyperframes 0.1.14 → 0.1.15
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/dist/cli.js +1 -1
- package/dist/skills/hyperframes-captions/SKILL.md +1 -1
- package/dist/templates/decision-tree/compositions/decision_tree.html +420 -0
- package/dist/templates/decision-tree/index.html +56 -0
- package/dist/templates/generators.ts +32 -0
- package/dist/templates/kinetic-type/compositions/main-graphics.html +588 -0
- package/dist/templates/kinetic-type/index.html +61 -0
- package/dist/templates/nyt-graph/compositions/nyt-chart.html +450 -0
- package/dist/templates/nyt-graph/index.html +51 -0
- package/dist/templates/product-promo/assets/figma-cursors.svg +30 -0
- package/dist/templates/product-promo/assets/figma-logo-pieces.svg +15 -0
- package/dist/templates/product-promo/assets/figma-logo-pills.svg +6 -0
- package/dist/templates/product-promo/compositions/scene1-logo-intro.html +189 -0
- package/dist/templates/product-promo/compositions/scene2-4-canvas.html +570 -0
- package/dist/templates/product-promo/compositions/scene5-logo-outro.html +226 -0
- package/dist/templates/product-promo/index.html +158 -0
- package/package.json +2 -2
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
<template id="scene5-logo-outro-template">
|
|
2
|
+
<div
|
|
3
|
+
data-composition-id="scene5-logo-outro"
|
|
4
|
+
data-width="1920"
|
|
5
|
+
data-height="1080"
|
|
6
|
+
data-duration="6"
|
|
7
|
+
>
|
|
8
|
+
<div class="canvas">
|
|
9
|
+
<!-- Glow effect behind the logo -->
|
|
10
|
+
<div class="logo-glow"></div>
|
|
11
|
+
|
|
12
|
+
<!-- Logo Container -->
|
|
13
|
+
<div class="logo-container">
|
|
14
|
+
<svg viewBox="0 0 160 240" width="160" height="240" class="logo-svg">
|
|
15
|
+
<!-- Figma Logo Pieces -->
|
|
16
|
+
<!-- Top-left: Red (#F24E1E) -->
|
|
17
|
+
<path
|
|
18
|
+
class="logo-piece logo-tl"
|
|
19
|
+
d="M 0 40 C 0 17.9 17.9 0 40 0 L 80 0 L 80 80 L 40 80 C 17.9 80 0 62.1 0 40 Z"
|
|
20
|
+
fill="#F24E1E"
|
|
21
|
+
/>
|
|
22
|
+
<!-- Top-right: Purple (#A259FF) -->
|
|
23
|
+
<path
|
|
24
|
+
class="logo-piece logo-tr"
|
|
25
|
+
d="M 80 0 L 120 0 C 142.1 0 160 17.9 160 40 C 160 62.1 142.1 80 120 80 L 80 80 L 80 0 Z"
|
|
26
|
+
fill="#A259FF"
|
|
27
|
+
/>
|
|
28
|
+
<!-- Middle-left: Pink (#FF7262) -->
|
|
29
|
+
<path
|
|
30
|
+
class="logo-piece logo-ml"
|
|
31
|
+
d="M 0 120 C 0 97.9 17.9 80 40 80 L 80 80 L 80 160 L 40 160 C 17.9 160 0 142.1 0 120 Z"
|
|
32
|
+
fill="#FF7262"
|
|
33
|
+
/>
|
|
34
|
+
<!-- Middle-right: Blue (#1ABCFE) -->
|
|
35
|
+
<circle class="logo-piece logo-mr" cx="120" cy="120" r="40" fill="#1ABCFE" />
|
|
36
|
+
<!-- Bottom-left: Green (#0ACF83) -->
|
|
37
|
+
<path
|
|
38
|
+
class="logo-piece logo-bl"
|
|
39
|
+
d="M 0 200 C 0 177.9 17.9 160 40 160 L 80 160 L 80 200 C 80 222.1 62.1 240 40 240 C 17.9 240 0 222.1 0 200 Z"
|
|
40
|
+
fill="#0ACF83"
|
|
41
|
+
/>
|
|
42
|
+
</svg>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div class="text-container">
|
|
46
|
+
<div class="tagline">Nothing great is made alone.</div>
|
|
47
|
+
<div class="url-pill">
|
|
48
|
+
<span class="url-text">figma.com</span>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<style>
|
|
54
|
+
[data-composition-id="scene5-logo-outro"] .canvas {
|
|
55
|
+
width: 1920px;
|
|
56
|
+
height: 1080px;
|
|
57
|
+
background: #0a0a0f;
|
|
58
|
+
position: relative;
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
font-family: "Inter", sans-serif;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
[data-composition-id="scene5-logo-outro"] .logo-container {
|
|
64
|
+
position: absolute;
|
|
65
|
+
left: 880px; /* Center X: 960 - 80 */
|
|
66
|
+
top: 380px; /* Adjusted for tagline space: 540 - 120 - 40 */
|
|
67
|
+
width: 160px;
|
|
68
|
+
height: 240px;
|
|
69
|
+
z-index: 2;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
[data-composition-id="scene5-logo-outro"] .logo-piece {
|
|
73
|
+
transform-origin: center center;
|
|
74
|
+
opacity: 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
[data-composition-id="scene5-logo-outro"] .logo-glow {
|
|
78
|
+
position: absolute;
|
|
79
|
+
left: 760px; /* 960 - 200 */
|
|
80
|
+
top: 300px; /* 500 - 200 */
|
|
81
|
+
width: 400px;
|
|
82
|
+
height: 400px;
|
|
83
|
+
background: radial-gradient(circle, rgba(162, 89, 255, 0.25) 0%, rgba(10, 10, 15, 0) 70%);
|
|
84
|
+
border-radius: 50%;
|
|
85
|
+
opacity: 0;
|
|
86
|
+
pointer-events: none;
|
|
87
|
+
z-index: 1;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
[data-composition-id="scene5-logo-outro"] .text-container {
|
|
91
|
+
position: absolute;
|
|
92
|
+
top: 720px;
|
|
93
|
+
width: 100%;
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
align-items: center;
|
|
97
|
+
z-index: 3;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
[data-composition-id="scene5-logo-outro"] .tagline {
|
|
101
|
+
font-size: 44px;
|
|
102
|
+
font-weight: 500;
|
|
103
|
+
color: white;
|
|
104
|
+
opacity: 0;
|
|
105
|
+
margin-bottom: 32px;
|
|
106
|
+
text-align: center;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
[data-composition-id="scene5-logo-outro"] .url-pill {
|
|
110
|
+
background: #1a1a1f;
|
|
111
|
+
border: 1px solid #2c2c2c;
|
|
112
|
+
border-radius: 100px;
|
|
113
|
+
padding: 8px 24px;
|
|
114
|
+
opacity: 0;
|
|
115
|
+
display: flex;
|
|
116
|
+
align-items: center;
|
|
117
|
+
justify-content: center;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
[data-composition-id="scene5-logo-outro"] .url-text {
|
|
121
|
+
font-size: 18px;
|
|
122
|
+
color: #666;
|
|
123
|
+
letter-spacing: 0.5px;
|
|
124
|
+
}
|
|
125
|
+
</style>
|
|
126
|
+
|
|
127
|
+
<script>
|
|
128
|
+
(function () {
|
|
129
|
+
const tl = gsap.timeline({ paused: true });
|
|
130
|
+
|
|
131
|
+
const pieces = {
|
|
132
|
+
tl: '[data-composition-id="scene5-logo-outro"] .logo-tl',
|
|
133
|
+
tr: '[data-composition-id="scene5-logo-outro"] .logo-tr',
|
|
134
|
+
ml: '[data-composition-id="scene5-logo-outro"] .logo-ml',
|
|
135
|
+
mr: '[data-composition-id="scene5-logo-outro"] .logo-mr',
|
|
136
|
+
bl: '[data-composition-id="scene5-logo-outro"] .logo-bl',
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const pieceArray = [pieces.tl, pieces.tr, pieces.ml, pieces.mr, pieces.bl];
|
|
140
|
+
const logoGlow = '[data-composition-id="scene5-logo-outro"] .logo-glow';
|
|
141
|
+
const tagline = '[data-composition-id="scene5-logo-outro"] .tagline';
|
|
142
|
+
const urlPill = '[data-composition-id="scene5-logo-outro"] .url-pill';
|
|
143
|
+
|
|
144
|
+
// 1. Pieces slide in from the RIGHT (x: 1920 -> 0) with a ripple stagger (0.08s). Duration: 1.2s.
|
|
145
|
+
pieceArray.forEach((piece, i) => {
|
|
146
|
+
tl.fromTo(
|
|
147
|
+
piece,
|
|
148
|
+
{ x: 1920, opacity: 0 },
|
|
149
|
+
{ x: 0, opacity: 1, duration: 1.2, ease: "power4.out" },
|
|
150
|
+
i * 0.08,
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// 2. Once at the center (960, 540), the pieces should simply EXPAND (scale 1 -> 1.15)
|
|
155
|
+
// and then CLOSE back to their done state (scale 1.15 -> 1).
|
|
156
|
+
// NO positional 'explode' or pushing to corners.
|
|
157
|
+
const expandTime = 1.2; // Start right after the first piece arrives, or after all?
|
|
158
|
+
// Let's start it after the last piece has arrived or is near arrival for a fluid motion.
|
|
159
|
+
// The last piece starts at 0.32s and takes 1.2s to arrive (1.52s total).
|
|
160
|
+
// Let's trigger the expand at 1.2s so it feels like a continuous flow.
|
|
161
|
+
|
|
162
|
+
tl.to(
|
|
163
|
+
pieceArray,
|
|
164
|
+
{
|
|
165
|
+
scale: 1.15,
|
|
166
|
+
duration: 0.5,
|
|
167
|
+
ease: "back.out(1.7)",
|
|
168
|
+
stagger: 0.02,
|
|
169
|
+
},
|
|
170
|
+
expandTime,
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
tl.to(
|
|
174
|
+
pieceArray,
|
|
175
|
+
{
|
|
176
|
+
scale: 1,
|
|
177
|
+
duration: 0.4,
|
|
178
|
+
ease: "power2.inOut",
|
|
179
|
+
},
|
|
180
|
+
expandTime + 0.3,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
// 3. Subtle glow bloom effect (optional but adds polish, keeping it from original as it fits the 'expand')
|
|
184
|
+
tl.fromTo(
|
|
185
|
+
logoGlow,
|
|
186
|
+
{ opacity: 0, scale: 0.5 },
|
|
187
|
+
{ opacity: 1, scale: 1.2, duration: 0.4, ease: "power2.out" },
|
|
188
|
+
expandTime,
|
|
189
|
+
);
|
|
190
|
+
tl.to(
|
|
191
|
+
logoGlow,
|
|
192
|
+
{
|
|
193
|
+
opacity: 0,
|
|
194
|
+
scale: 1.8,
|
|
195
|
+
duration: 1.2,
|
|
196
|
+
ease: "power2.out",
|
|
197
|
+
},
|
|
198
|
+
expandTime + 0.4,
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// 4. Tagline and URL pill fade in as before.
|
|
202
|
+
const textStartTime = expandTime + 0.8;
|
|
203
|
+
tl.fromTo(
|
|
204
|
+
tagline,
|
|
205
|
+
{ opacity: 0, y: 20 },
|
|
206
|
+
{ opacity: 1, y: 0, duration: 1, ease: "power3.out" },
|
|
207
|
+
textStartTime,
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
tl.fromTo(
|
|
211
|
+
urlPill,
|
|
212
|
+
{ opacity: 0, y: 15 },
|
|
213
|
+
{ opacity: 1, y: 0, duration: 0.8, ease: "power3.out" },
|
|
214
|
+
textStartTime + 0.4,
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
// 5. Remove the final pulse animation. (Omitted)
|
|
218
|
+
// 6. After they return to the done state, there should be NO MORE movement for the logo. (Ensured)
|
|
219
|
+
|
|
220
|
+
// Register timeline
|
|
221
|
+
window.__timelines = window.__timelines || {};
|
|
222
|
+
window.__timelines["scene5-logo-outro"] = tl;
|
|
223
|
+
})();
|
|
224
|
+
</script>
|
|
225
|
+
</div>
|
|
226
|
+
</template>
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=1920, height=1080" />
|
|
6
|
+
<title>Product Promo</title>
|
|
7
|
+
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
|
8
|
+
<link
|
|
9
|
+
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;800&display=block"
|
|
10
|
+
rel="stylesheet"
|
|
11
|
+
/>
|
|
12
|
+
<style>
|
|
13
|
+
* {
|
|
14
|
+
margin: 0;
|
|
15
|
+
padding: 0;
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
}
|
|
18
|
+
html,
|
|
19
|
+
body {
|
|
20
|
+
margin: 0;
|
|
21
|
+
width: 1920px;
|
|
22
|
+
height: 1080px;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
background: #0a0a0f;
|
|
25
|
+
font-family: "Inter", sans-serif;
|
|
26
|
+
}
|
|
27
|
+
.scene {
|
|
28
|
+
position: absolute;
|
|
29
|
+
top: 0;
|
|
30
|
+
left: 0;
|
|
31
|
+
width: 100%;
|
|
32
|
+
height: 100%;
|
|
33
|
+
}
|
|
34
|
+
.caption-text-wrapper {
|
|
35
|
+
position: absolute;
|
|
36
|
+
bottom: 150px;
|
|
37
|
+
left: 0;
|
|
38
|
+
right: 0;
|
|
39
|
+
display: flex;
|
|
40
|
+
justify-content: center;
|
|
41
|
+
pointer-events: none;
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
padding: 10px 0;
|
|
44
|
+
}
|
|
45
|
+
.caption-line {
|
|
46
|
+
color: white;
|
|
47
|
+
font-size: 48px;
|
|
48
|
+
font-weight: 600;
|
|
49
|
+
letter-spacing: -0.02em;
|
|
50
|
+
text-align: center;
|
|
51
|
+
text-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
|
|
52
|
+
transform: translateY(100%);
|
|
53
|
+
opacity: 0;
|
|
54
|
+
}
|
|
55
|
+
</style>
|
|
56
|
+
</head>
|
|
57
|
+
<body>
|
|
58
|
+
<div
|
|
59
|
+
id="root"
|
|
60
|
+
data-composition-id="main"
|
|
61
|
+
data-start="0"
|
|
62
|
+
data-duration="20"
|
|
63
|
+
data-width="1920"
|
|
64
|
+
data-height="1080"
|
|
65
|
+
>
|
|
66
|
+
<!-- Scene 1: Logo Intro -->
|
|
67
|
+
<div
|
|
68
|
+
id="scene-1"
|
|
69
|
+
class="scene"
|
|
70
|
+
data-composition-id="scene1-logo-intro"
|
|
71
|
+
data-composition-src="compositions/scene1-logo-intro.html"
|
|
72
|
+
data-start="0"
|
|
73
|
+
data-duration="1.5"
|
|
74
|
+
data-track-index="1"
|
|
75
|
+
data-width="1920"
|
|
76
|
+
data-height="1080"
|
|
77
|
+
></div>
|
|
78
|
+
|
|
79
|
+
<!-- Scene 2-4: Continuous Canvas -->
|
|
80
|
+
<div
|
|
81
|
+
id="scene-2-4"
|
|
82
|
+
class="scene"
|
|
83
|
+
data-composition-id="scene2-4-canvas"
|
|
84
|
+
data-composition-src="compositions/scene2-4-canvas.html"
|
|
85
|
+
data-start="1.5"
|
|
86
|
+
data-duration="12.5"
|
|
87
|
+
data-track-index="1"
|
|
88
|
+
data-width="1920"
|
|
89
|
+
data-height="1080"
|
|
90
|
+
></div>
|
|
91
|
+
|
|
92
|
+
<!-- Scene 5: Logo Outro -->
|
|
93
|
+
<div
|
|
94
|
+
id="scene-5"
|
|
95
|
+
class="scene"
|
|
96
|
+
data-composition-id="scene5-logo-outro"
|
|
97
|
+
data-composition-src="compositions/scene5-logo-outro.html"
|
|
98
|
+
data-start="14"
|
|
99
|
+
data-duration="6"
|
|
100
|
+
data-track-index="1"
|
|
101
|
+
data-width="1920"
|
|
102
|
+
data-height="1080"
|
|
103
|
+
></div>
|
|
104
|
+
|
|
105
|
+
<!-- Captions -->
|
|
106
|
+
<div
|
|
107
|
+
id="captions-comp"
|
|
108
|
+
data-composition-id="captions"
|
|
109
|
+
data-start="1.5"
|
|
110
|
+
data-duration="12.5"
|
|
111
|
+
data-track-index="2"
|
|
112
|
+
data-width="1920"
|
|
113
|
+
data-height="1080"
|
|
114
|
+
>
|
|
115
|
+
<div class="caption-text-wrapper">
|
|
116
|
+
<div id="caption-text" class="caption-line">Starting with a blank canvas.</div>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<script>
|
|
120
|
+
(function () {
|
|
121
|
+
const tl = gsap.timeline({ paused: true });
|
|
122
|
+
const text = document.querySelector("#caption-text");
|
|
123
|
+
|
|
124
|
+
tl.to(text, { opacity: 1, y: 0, duration: 0.8, ease: "power3.out" }, 0);
|
|
125
|
+
tl.to(text, { opacity: 0, y: -20, duration: 0.3, ease: "power3.in" }, 3.2);
|
|
126
|
+
tl.set(text, { innerText: "Three cursors. One file. Zero meetings.", y: 40 }, 3.5);
|
|
127
|
+
tl.to(text, { opacity: 1, y: 0, duration: 0.6, ease: "power3.out" }, 3.5);
|
|
128
|
+
tl.to(text, { opacity: 0, y: -20, duration: 0.3, ease: "power3.in" }, 7.7);
|
|
129
|
+
tl.set(
|
|
130
|
+
text,
|
|
131
|
+
{ innerText: "Components in. Feedback resolved. No one waited.", y: 40 },
|
|
132
|
+
8.0,
|
|
133
|
+
);
|
|
134
|
+
tl.to(text, { opacity: 1, y: 0, duration: 0.6, ease: "power3.out" }, 8.0);
|
|
135
|
+
tl.to(text, { opacity: 0, y: -20, duration: 0.4, ease: "power3.in" }, 12.1);
|
|
136
|
+
|
|
137
|
+
window.__timelines = window.__timelines || {};
|
|
138
|
+
window.__timelines["captions"] = tl;
|
|
139
|
+
})();
|
|
140
|
+
</script>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<script>
|
|
145
|
+
window.__timelines = window.__timelines || {};
|
|
146
|
+
const mainTl = gsap.timeline({ paused: true });
|
|
147
|
+
|
|
148
|
+
mainTl.set("#scene-2-4", { scale: 1, filter: "blur(0px)" }, 1.5);
|
|
149
|
+
mainTl.to(
|
|
150
|
+
"#scene-2-4",
|
|
151
|
+
{ duration: 0.25, scale: 0.94, filter: "blur(6px)", opacity: 0, ease: "power2.in" },
|
|
152
|
+
13.75,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
window.__timelines["main"] = mainTl;
|
|
156
|
+
</script>
|
|
157
|
+
</body>
|
|
158
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hyperframes",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "HyperFrames CLI — create, preview, and render HTML video compositions",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"build:fonts": "cd ../producer && tsx scripts/generate-font-data.ts",
|
|
22
22
|
"build:studio": "cd ../studio && bun run build",
|
|
23
23
|
"build:runtime": "tsx scripts/build-runtime.ts",
|
|
24
|
-
"build:copy": "mkdir -p dist/studio dist/docs dist/templates dist/skills && cp -r ../studio/dist/* dist/studio/ && cp -r src/templates
|
|
24
|
+
"build:copy": "mkdir -p dist/studio dist/docs dist/templates dist/skills && cp -r ../studio/dist/* dist/studio/ && cp -r src/templates/* dist/templates/ && cp -r ../../skills/hyperframes-compose ../../skills/hyperframes-captions dist/skills/ && (cp src/docs/*.md dist/docs/ 2>/dev/null || true)",
|
|
25
25
|
"typecheck": "tsc --noEmit"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|