hyperframes 0.2.5 → 0.3.1

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 (32) hide show
  1. package/dist/cli.js +7152 -6407
  2. package/dist/docs/{templates.md → examples.md} +2 -2
  3. package/dist/skills/gsap/SKILL.md +5 -16
  4. package/dist/skills/gsap/references/effects.md +7 -14
  5. package/dist/skills/hyperframes/SKILL.md +124 -43
  6. package/dist/skills/hyperframes/house-style.md +34 -93
  7. package/dist/skills/hyperframes/references/captions.md +2 -2
  8. package/dist/skills/hyperframes/references/css-patterns.md +36 -34
  9. package/dist/skills/hyperframes/references/transitions/catalog.md +4 -19
  10. package/dist/skills/hyperframes/references/transitions/css-other.md +0 -11
  11. package/dist/skills/hyperframes/references/transitions.md +53 -37
  12. package/dist/skills/hyperframes/references/{fonts.md → typography.md} +73 -32
  13. package/dist/skills/hyperframes/scripts/animation-map.mjs +596 -0
  14. package/dist/skills/hyperframes/scripts/contrast-report.mjs +335 -0
  15. package/dist/skills/hyperframes-cli/SKILL.md +1 -1
  16. package/dist/studio/assets/hyperframes-player-eEkqo7g7.js +198 -0
  17. package/dist/studio/assets/index-DZEa45DQ.css +1 -0
  18. package/dist/studio/assets/{index-BkSXiHxK.js → index-Pn53dCTs.js} +27 -224
  19. package/dist/studio/index.html +2 -2
  20. package/dist/templates/_shared/AGENTS.md +59 -0
  21. package/dist/templates/_shared/CLAUDE.md +7 -7
  22. package/package.json +1 -1
  23. package/dist/skills/gsap/references/frameworks.md +0 -56
  24. package/dist/skills/gsap/references/plugins.md +0 -194
  25. package/dist/skills/gsap/references/react.md +0 -80
  26. package/dist/skills/gsap/references/scrolltrigger.md +0 -147
  27. package/dist/skills/gsap/references/utils.md +0 -91
  28. package/dist/skills/hyperframes/references/examples.md +0 -146
  29. package/dist/skills/hyperframes/references/marker-highlight.md +0 -158
  30. package/dist/skills/hyperframes/references/transitions/shader-setup.md +0 -463
  31. package/dist/skills/hyperframes/references/transitions/shader-transitions.md +0 -329
  32. package/dist/studio/assets/index-DHr9yo58.css +0 -1
@@ -1,463 +0,0 @@
1
- # Shader Transition Setup
2
-
3
- Complete boilerplate for WebGL shader transitions in HyperFrames. Read this when implementing a shader transition — copy the setup code, then plug in the fragment shader from the catalog.
4
-
5
- ## HTML
6
-
7
- ```html
8
- <canvas
9
- id="gl-canvas"
10
- width="1920"
11
- height="1080"
12
- style="position:absolute;top:0;left:0;width:1920px;height:1080px;z-index:100;pointer-events:none;display:none;"
13
- >
14
- </canvas>
15
- ```
16
-
17
- ## WebGL Init + Scene Capture
18
-
19
- Handles images, video, shapes, and text. Supports `object-fit: cover` on images and live video re-upload during transitions.
20
-
21
- ```js
22
- var sceneTextures = {};
23
- var sceneHasVideo = {}; // tracks which scenes have live video
24
- var glCanvas = document.getElementById("gl-canvas");
25
- var gl = glCanvas.getContext("webgl", { preserveDrawingBuffer: true });
26
- gl.viewport(0, 0, 1920, 1080);
27
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
28
-
29
- // Wait for all media to load before capturing
30
- function waitForMedia() {
31
- return new Promise(function (resolve) {
32
- var promises = [];
33
- document.querySelectorAll("img").forEach(function (img) {
34
- if (!img.complete)
35
- promises.push(
36
- new Promise(function (r) {
37
- img.onload = r;
38
- img.onerror = r;
39
- }),
40
- );
41
- });
42
- document.querySelectorAll("video").forEach(function (vid) {
43
- if (vid.readyState < 2)
44
- promises.push(
45
- new Promise(function (r) {
46
- vid.addEventListener("loadeddata", r, { once: true });
47
- }),
48
- );
49
- });
50
- Promise.all(promises).then(resolve);
51
- });
52
- }
53
-
54
- function captureScene(sceneId) {
55
- return new Promise(function (resolve) {
56
- var scene = document.getElementById(sceneId);
57
- var origOpacity = scene.style.opacity;
58
- var origZ = scene.style.zIndex;
59
- scene.style.opacity = "1";
60
- scene.style.zIndex = "999";
61
-
62
- if (scene.querySelector("video")) sceneHasVideo[sceneId] = scene.querySelector("video");
63
-
64
- requestAnimationFrame(function () {
65
- requestAnimationFrame(function () {
66
- var c = document.createElement("canvas");
67
- c.width = 1920;
68
- c.height = 1080;
69
- var ctx = c.getContext("2d");
70
-
71
- ctx.fillStyle = window.getComputedStyle(scene).backgroundColor;
72
- ctx.fillRect(0, 0, 1920, 1080);
73
-
74
- var sr = scene.getBoundingClientRect();
75
- var els = scene.querySelectorAll("*");
76
- for (var i = 0; i < els.length; i++) {
77
- var el = els[i];
78
- var cs = window.getComputedStyle(el);
79
- if (cs.display === "none" || cs.visibility === "hidden") continue;
80
- var r = el.getBoundingClientRect();
81
- if (r.width < 1 || r.height < 1) continue;
82
- var x = r.left - sr.left,
83
- y = r.top - sr.top,
84
- w = r.width,
85
- h = r.height;
86
-
87
- ctx.save();
88
- ctx.globalAlpha = parseFloat(cs.opacity) || 1;
89
-
90
- // <img> elements (with object-fit: cover support)
91
- if (el.tagName === "IMG" && el.complete && el.naturalWidth > 0) {
92
- try {
93
- if (cs.objectFit === "cover") {
94
- var iR = el.naturalWidth / el.naturalHeight,
95
- bR = w / h;
96
- var sx = 0,
97
- sy = 0,
98
- sw = el.naturalWidth,
99
- sh = el.naturalHeight;
100
- if (iR > bR) {
101
- sw = sh * bR;
102
- sx = (el.naturalWidth - sw) / 2;
103
- } else {
104
- sh = sw / bR;
105
- sy = (el.naturalHeight - sh) / 2;
106
- }
107
- ctx.drawImage(el, sx, sy, sw, sh, x, y, w, h);
108
- } else {
109
- ctx.drawImage(el, x, y, w, h);
110
- }
111
- } catch (e) {}
112
- ctx.restore();
113
- continue;
114
- }
115
-
116
- // <video> elements (grabs current frame)
117
- if (el.tagName === "VIDEO" && el.readyState >= 2) {
118
- try {
119
- var vR = el.videoWidth / el.videoHeight,
120
- bR2 = w / h;
121
- var vx = 0,
122
- vy = 0,
123
- vw = el.videoWidth,
124
- vh = el.videoHeight;
125
- if (vR > bR2) {
126
- vw = vh * bR2;
127
- vx = (el.videoWidth - vw) / 2;
128
- } else {
129
- vh = vw / bR2;
130
- vy = (el.videoHeight - vh) / 2;
131
- }
132
- ctx.drawImage(el, vx, vy, vw, vh, x, y, w, h);
133
- } catch (e) {}
134
- ctx.restore();
135
- continue;
136
- }
137
-
138
- // Background color
139
- var bg = cs.backgroundColor;
140
- if (bg && bg !== "rgba(0, 0, 0, 0)" && bg !== "transparent") {
141
- ctx.fillStyle = bg;
142
- var br = parseInt(cs.borderRadius) || 0;
143
- if (br >= Math.min(w, h) / 2 - 1 && Math.abs(w - h) < 4) {
144
- ctx.beginPath();
145
- ctx.arc(x + w / 2, y + h / 2, Math.min(w, h) / 2, 0, Math.PI * 2);
146
- ctx.fill();
147
- } else if (br > 0) {
148
- ctx.beginPath();
149
- ctx.moveTo(x + br, y);
150
- ctx.arcTo(x + w, y, x + w, y + h, br);
151
- ctx.arcTo(x + w, y + h, x, y + h, br);
152
- ctx.arcTo(x, y + h, x, y, br);
153
- ctx.arcTo(x, y, x + w, y, br);
154
- ctx.closePath();
155
- ctx.fill();
156
- } else {
157
- ctx.fillRect(x, y, w, h);
158
- }
159
- }
160
-
161
- // Text (leaf nodes only, with text-shadow)
162
- var hasChildEls = el.querySelector("div, span, img, video");
163
- var text = "";
164
- for (var j = 0; j < el.childNodes.length; j++)
165
- if (el.childNodes[j].nodeType === 3) text += el.childNodes[j].textContent;
166
- text = text.trim();
167
- if (text && !hasChildEls) {
168
- ctx.font = cs.fontWeight + " " + cs.fontSize + " " + cs.fontFamily;
169
- ctx.fillStyle = cs.color;
170
- if (cs.letterSpacing && cs.letterSpacing !== "normal")
171
- ctx.letterSpacing = cs.letterSpacing;
172
- var shadow = cs.textShadow;
173
- if (shadow && shadow !== "none") {
174
- var sp = shadow.match(/rgba?\([^)]+\)\s+(-?\d+)px\s+(-?\d+)px\s+(-?\d+)px/);
175
- if (sp) {
176
- ctx.shadowColor = shadow.match(/rgba?\([^)]+\)/)[0];
177
- ctx.shadowOffsetX = parseFloat(sp[1]);
178
- ctx.shadowOffsetY = parseFloat(sp[2]);
179
- ctx.shadowBlur = parseFloat(sp[3]);
180
- }
181
- }
182
- if (cs.textAlign === "center" || w > 1800) {
183
- ctx.textAlign = "center";
184
- ctx.textBaseline = "middle";
185
- ctx.fillText(text, x + w / 2, y + h / 2);
186
- } else {
187
- ctx.textAlign = "left";
188
- ctx.textBaseline = "middle";
189
- ctx.fillText(text, x, y + h / 2);
190
- }
191
- }
192
- ctx.restore();
193
- }
194
-
195
- scene.style.opacity = origOpacity;
196
- scene.style.zIndex = origZ;
197
-
198
- var tex = gl.createTexture();
199
- gl.bindTexture(gl.TEXTURE_2D, tex);
200
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
201
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
202
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
203
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
204
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
205
- sceneTextures[sceneId] = tex;
206
- resolve();
207
- });
208
- });
209
- });
210
- }
211
-
212
- // Re-capture video scenes every frame (call in updateTrans and during holds)
213
- function recaptureVideoScene(sceneId) {
214
- var video = sceneHasVideo[sceneId];
215
- if (!video || video.readyState < 2) return;
216
- var scene = document.getElementById(sceneId);
217
- var c = document.createElement("canvas");
218
- c.width = 1920;
219
- c.height = 1080;
220
- var ctx = c.getContext("2d");
221
- ctx.fillStyle = window.getComputedStyle(scene).backgroundColor;
222
- ctx.fillRect(0, 0, 1920, 1080);
223
- var sr = scene.getBoundingClientRect();
224
- var els = scene.querySelectorAll("*");
225
- for (var i = 0; i < els.length; i++) {
226
- var el = els[i],
227
- cs = window.getComputedStyle(el);
228
- if (cs.display === "none") continue;
229
- var r = el.getBoundingClientRect();
230
- if (r.width < 1) continue;
231
- var x = r.left - sr.left,
232
- y = r.top - sr.top,
233
- w = r.width,
234
- h = r.height;
235
- ctx.save();
236
- ctx.globalAlpha = parseFloat(cs.opacity) || 1;
237
- if (el.tagName === "VIDEO" && el.readyState >= 2) {
238
- try {
239
- var vR = el.videoWidth / el.videoHeight,
240
- bR = w / h;
241
- var sx = 0,
242
- sy = 0,
243
- sw = el.videoWidth,
244
- sh = el.videoHeight;
245
- if (vR > bR) {
246
- sw = sh * bR;
247
- sx = (el.videoWidth - sw) / 2;
248
- } else {
249
- sh = sw / bR;
250
- sy = (el.videoHeight - sh) / 2;
251
- }
252
- ctx.drawImage(el, sx, sy, sw, sh, x, y, w, h);
253
- } catch (e) {}
254
- } else if (el.tagName === "IMG" && el.complete) {
255
- try {
256
- ctx.drawImage(el, x, y, w, h);
257
- } catch (e) {}
258
- } else {
259
- var bg = cs.backgroundColor;
260
- if (bg && bg !== "rgba(0, 0, 0, 0)") {
261
- ctx.fillStyle = bg;
262
- ctx.fillRect(x, y, w, h);
263
- }
264
- var txt = "";
265
- for (var j = 0; j < el.childNodes.length; j++)
266
- if (el.childNodes[j].nodeType === 3) txt += el.childNodes[j].textContent;
267
- txt = txt.trim();
268
- if (txt && !el.querySelector("div,span,img,video")) {
269
- ctx.font = cs.fontWeight + " " + cs.fontSize + " " + cs.fontFamily;
270
- ctx.fillStyle = cs.color;
271
- ctx.textAlign = "left";
272
- ctx.textBaseline = "middle";
273
- ctx.fillText(txt, x, y + h / 2);
274
- }
275
- }
276
- ctx.restore();
277
- }
278
- gl.bindTexture(gl.TEXTURE_2D, sceneTextures[sceneId]);
279
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
280
- }
281
- ```
282
-
283
- ## Shader Compilation + Shared Constants
284
-
285
- ```js
286
- var vertSrc =
287
- "attribute vec2 a_pos; varying vec2 v_uv; void main(){" +
288
- "v_uv=a_pos*0.5+0.5; v_uv.y=1.0-v_uv.y; gl_Position=vec4(a_pos,0,1);}";
289
-
290
- var quadBuf = gl.createBuffer();
291
- gl.bindBuffer(gl.ARRAY_BUFFER, quadBuf);
292
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
293
-
294
- function compileShader(src, type) {
295
- var s = gl.createShader(type);
296
- gl.shaderSource(s, src);
297
- gl.compileShader(s);
298
- if (!gl.getShaderParameter(s, gl.COMPILE_STATUS))
299
- console.error("Shader:", gl.getShaderInfoLog(s));
300
- return s;
301
- }
302
-
303
- function mkProg(fragSrc) {
304
- var p = gl.createProgram();
305
- gl.attachShader(p, compileShader(vertSrc, gl.VERTEX_SHADER));
306
- gl.attachShader(p, compileShader(fragSrc, gl.FRAGMENT_SHADER));
307
- gl.linkProgram(p);
308
- if (!gl.getProgramParameter(p, gl.LINK_STATUS)) console.error("Link:", gl.getProgramInfoLog(p));
309
- return p;
310
- }
311
-
312
- // Shared uniform header — every fragment shader starts with this
313
- var H =
314
- "precision mediump float;" +
315
- "varying vec2 v_uv;" +
316
- "uniform sampler2D u_from, u_to;" +
317
- "uniform float u_progress;" +
318
- "uniform vec2 u_resolution;\n";
319
- ```
320
-
321
- ## Noise Libraries
322
-
323
- Include only what each shader needs. Do NOT include multiple libraries that redefine `hash()` in the same shader.
324
-
325
- ```js
326
- // Quintic C2 noise + inter-octave rotation FBM
327
- var NQ =
328
- "float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}" +
329
- "float vnoise(vec2 p){vec2 i=floor(p),f=fract(p);" +
330
- "f=f*f*f*(f*(f*6.-15.)+10.);" + // quintic interpolation — C2 continuous
331
- "return mix(mix(hash(i),hash(i+vec2(1,0)),f.x)," +
332
- "mix(hash(i+vec2(0,1)),hash(i+vec2(1,1)),f.x),f.y);}" +
333
- "float fbm(vec2 p){float v=0.,a=.5;" +
334
- "mat2 R=mat2(.8,.6,-.6,.8);" + // inter-octave rotation (~37deg)
335
- "for(int i=0;i<5;i++){v+=a*vnoise(p);p=R*p*2.02;a*=.5;}return v;}";
336
-
337
- // Noise with analytical derivatives (quintic) + erosion FBM
338
- // Use for transitions that need gradient-based edge lighting
339
- var ND =
340
- "float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}" +
341
- "vec3 noised(vec2 p){vec2 i=floor(p),f=fract(p);" +
342
- "vec2 u=f*f*f*(f*(f*6.-15.)+10.),du=30.*f*f*(f*(f-2.)+1.);" +
343
- "float a=hash(i),b=hash(i+vec2(1,0)),c=hash(i+vec2(0,1)),d=hash(i+vec2(1,1));" +
344
- "return vec3(a+(b-a)*u.x+(c-a)*u.y+(a-b-c+d)*u.x*u.y," +
345
- "du*vec2(b-a+(a-b-c+d)*u.y,c-a+(a-b-c+d)*u.x));}" +
346
- "float erosionFBM(vec2 p){float v=0.,a=.5;vec2 d=vec2(0);mat2 R=mat2(.8,.6,-.6,.8);" +
347
- "for(int i=0;i<6;i++){vec3 n=noised(p);d+=n.yz;v+=a*n.x/(1.+dot(d,d));p=R*p*2.02;a*=.5;}return v;}";
348
-
349
- // Cosine palette: a + b*cos(2pi(c*t + d))
350
- var CP = "vec3 palette(float t,vec3 a,vec3 b,vec3 c,vec3 d){" + "return a+b*cos(6.2832*(c*t+d));}";
351
- ```
352
-
353
- ## Render + State Machine
354
-
355
- ```js
356
- function renderShader(prog, texFrom, texTo, progress) {
357
- gl.useProgram(prog);
358
- gl.activeTexture(gl.TEXTURE0);
359
- gl.bindTexture(gl.TEXTURE_2D, texFrom);
360
- gl.uniform1i(gl.getUniformLocation(prog, "u_from"), 0);
361
- gl.activeTexture(gl.TEXTURE1);
362
- gl.bindTexture(gl.TEXTURE_2D, texTo);
363
- gl.uniform1i(gl.getUniformLocation(prog, "u_to"), 1);
364
- gl.uniform1f(gl.getUniformLocation(prog, "u_progress"), progress);
365
- gl.uniform2f(gl.getUniformLocation(prog, "u_resolution"), 1920, 1080);
366
- var pos = gl.getAttribLocation(prog, "a_pos");
367
- gl.bindBuffer(gl.ARRAY_BUFFER, quadBuf);
368
- gl.enableVertexAttribArray(pos);
369
- gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);
370
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
371
- }
372
-
373
- var progPass = mkProg(H + "void main(){gl_FragColor=texture2D(u_from,v_uv);}");
374
-
375
- var trans = {
376
- active: false,
377
- prog: null,
378
- fromId: null,
379
- toId: null,
380
- progress: 0,
381
- };
382
-
383
- function beginTrans(prog, fromId, toId) {
384
- trans.prog = prog;
385
- trans.fromId = fromId;
386
- trans.toId = toId;
387
- trans.progress = 0;
388
- trans.active = true;
389
- }
390
-
391
- function updateTrans() {
392
- if (!trans.active) return;
393
- // Re-capture video scenes every frame during transition
394
- if (sceneHasVideo[trans.fromId]) recaptureVideoScene(trans.fromId);
395
- if (sceneHasVideo[trans.toId]) recaptureVideoScene(trans.toId);
396
- renderShader(trans.prog, sceneTextures[trans.fromId], sceneTextures[trans.toId], trans.progress);
397
- }
398
-
399
- function endTrans(showId) {
400
- trans.active = false;
401
- renderShader(progPass, sceneTextures[showId], sceneTextures[showId], 0);
402
- }
403
- ```
404
-
405
- ## GSAP Timeline Integration
406
-
407
- ```js
408
- // Wait for media, start videos, capture all scenes, then build timeline
409
- var sceneIds = ["scene1", "scene2" /* ... */];
410
- waitForMedia()
411
- .then(function () {
412
- // Start any background videos (muted)
413
- document.querySelectorAll("video").forEach(function (v) {
414
- v.play();
415
- });
416
- return Promise.all(sceneIds.map(captureScene));
417
- })
418
- .then(function () {
419
- glCanvas.style.display = "block";
420
- renderShader(progPass, sceneTextures["scene1"], sceneTextures["scene1"], 0);
421
- document.querySelectorAll(".scene").forEach(function (s) {
422
- s.style.opacity = "0";
423
- });
424
-
425
- var tl = gsap.timeline({
426
- paused: true,
427
- onUpdate: function () {
428
- updateTrans();
429
- },
430
- });
431
-
432
- // For each transition:
433
- tl.call(
434
- function () {
435
- beginTrans(myShaderProg, "scene1", "scene2");
436
- },
437
- null,
438
- T,
439
- );
440
- var tw = { p: 0 };
441
- tl.to(
442
- tw,
443
- {
444
- p: 1,
445
- duration: DUR,
446
- ease: "power2.inOut",
447
- onUpdate: function () {
448
- trans.progress = tw.p;
449
- },
450
- },
451
- T,
452
- );
453
- tl.call(
454
- function () {
455
- endTrans("scene2");
456
- },
457
- null,
458
- T + DUR,
459
- );
460
-
461
- window.__timelines["main"] = tl;
462
- });
463
- ```