hyperframes 0.7.23 → 0.7.25

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.
@@ -359,6 +359,17 @@
359
359
  };
360
360
  }
361
361
 
362
+ // An ancestor (up to and including `stopAt`) that clips its overflow makes any
363
+ // text spilling past it invisible — that clipping IS the layout mechanism
364
+ // (odometer/ticker reels, masked windows), not a defect to report.
365
+ function clippedByAncestor(element, stopAt) {
366
+ for (let current = element; current; current = current.parentElement) {
367
+ if (current !== element && clipsOverflow(getComputedStyle(current))) return true;
368
+ if (current === stopAt) break;
369
+ }
370
+ return false;
371
+ }
372
+
362
373
  function textOverflowIssues(element, root, rootRect, time, tolerance) {
363
374
  const textRect = textRectFor(element);
364
375
  if (!textRect) return [];
@@ -382,7 +393,11 @@
382
393
  ? tolerance
383
394
  : Math.max(tolerance, parsePx(elementStyle.fontSize) * 0.2);
384
395
  const containerOverflow = overflowFor(textRect, containerRect, tolerance, verticalTolerance);
385
- if (containerOverflow && !hasAllowOverflowFlag(element)) {
396
+ if (
397
+ containerOverflow &&
398
+ !hasAllowOverflowFlag(element) &&
399
+ !clippedByAncestor(element, container)
400
+ ) {
386
401
  const style = elementStyle;
387
402
  issues.push({
388
403
  code: "text_box_overflow",
@@ -622,13 +637,31 @@
622
637
  return Math.min(opacityChain(textScene), opacityChain(occluderScene)) < 0.999;
623
638
  }
624
639
 
640
+ // The nearest ancestor establishing a 3D rendering context, or null. Elements
641
+ // sharing one are depth-sorted in 3D, so a "covering" hit is legitimate
642
+ // perspective (e.g. the back face of a preserve-3d cube), not a 2D overlap.
643
+ function preserve3dContext(element) {
644
+ for (let current = element; current; current = current.parentElement) {
645
+ const ts = getComputedStyle(current).transformStyle;
646
+ if (ts === "preserve-3d") return current;
647
+ }
648
+ return null;
649
+ }
650
+
651
+ function sharedPreserve3d(a, b) {
652
+ const ctx = preserve3dContext(a);
653
+ return !!ctx && ctx === preserve3dContext(b);
654
+ }
655
+
625
656
  // The opaque element painted over (x, y), or null when the topmost element
626
- // there is related to the text, non-opaque, or a transient crossfade overlap.
657
+ // there is related to the text, non-opaque, sharing a 3D context with it, or
658
+ // part of a transient crossfade overlap.
627
659
  // fallow-ignore-next-line complexity
628
660
  function occluderAt(element, x, y) {
629
661
  if (typeof document.elementFromPoint !== "function") return null;
630
662
  const hit = document.elementFromPoint(x, y);
631
663
  if (!isForeignElement(element, hit)) return null;
664
+ if (sharedPreserve3d(element, hit)) return null;
632
665
  if (!isOpaqueOccluder(hit)) return null;
633
666
  if (isCrossSceneTransitionOverlap(element, hit)) return null;
634
667
  return hit;
@@ -25,15 +25,16 @@ Below: a **capability map** (the domain skills, loaded on demand) and the **inte
25
25
 
26
26
  Atomic capabilities you load **on demand** — not full video workflows. For "make me a video", use the intent router below.
27
27
 
28
- | You want to… | Skill |
29
- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------ |
30
- | **Author / edit an HTML composition** — the `data-*` contract, clips, tracks, sub-compositions, variables | `/hyperframes-core` |
31
- | **Animate** — atomic motion, scene blueprints, transitions, runtime adapters (GSAP / Lottie / Three.js / Anime.js / CSS / WAAPI / TypeGPU) | `/hyperframes-animation` |
32
- | **Creative direction** — `frame.md` / `design.md`, palettes, typography, narration, beat planning, audio-reactive | `/hyperframes-creative` |
33
- | **Media** — TTS voiceover, background music, transcription, background removal, captions | `/hyperframes-media` |
34
- | **Media resolve** — find + freeze BGM, SFX, images, icons from HeyGen catalog into `.media/` with manifest tracking | `/media-use` |
35
- | **CLI dev loop** — init, lint, validate, inspect, preview, render, publish, doctor | `/hyperframes-cli` |
36
- | **Install registry blocks / components** (`hyperframes add`) | `/hyperframes-registry` |
28
+ | You want to… | Skill |
29
+ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
30
+ | **Author / edit an HTML composition** — the `data-*` contract, clips, tracks, sub-compositions, variables | `/hyperframes-core` |
31
+ | **Animate** — atomic motion, scene blueprints, transitions, runtime adapters (GSAP / Lottie / Three.js / Anime.js / CSS / WAAPI / TypeGPU) | `/hyperframes-animation` |
32
+ | **Author seek-safe keyframes** — GSAP timelines, CSS keyframes, Anime.js, WAAPI, FLIP, paths, masks, SVG morph/draw, 3D depth, plus `hyperframes keyframes` diagnostics | `/hyperframes-keyframes` |
33
+ | **Creative direction** — `frame.md` / `design.md`, palettes, typography, narration, beat planning, audio-reactive | `/hyperframes-creative` |
34
+ | **Media** — TTS voiceover, background music, transcription, background removal, captions | `/hyperframes-media` |
35
+ | **Media resolve** — find + freeze BGM, SFX, images, icons from HeyGen catalog into `.media/` with manifest tracking | `/media-use` |
36
+ | **CLI dev loop** init, lint, validate, inspect, preview, render, publish, doctor | `/hyperframes-cli` |
37
+ | **Install registry blocks / components** (`hyperframes add`) | `/hyperframes-registry` |
37
38
 
38
39
  ---
39
40
 
@@ -1 +1 @@
1
- import{g as P}from"./index-B8XMgbWF.js";function j(c,d){for(var s=0;s<d.length;s++){const a=d[s];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in c)){const l=Object.getOwnPropertyDescriptor(a,i);l&&Object.defineProperty(c,i,l.get?l:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}))}var v={},w;function k(){if(w)return v;w=1,Object.defineProperty(v,"__esModule",{value:!0}),v.default=d;var c=window.OfflineAudioContext||window.webkitOfflineAudioContext;function d(e){var r=a(e);return r.start(0),[i,y,O(e.sampleRate),s].reduce(function(t,o){return o(t)},r.buffer.getChannelData(0))}function s(e){return e.sort(function(r,t){return t.count-r.count}).splice(0,5)[0].tempo}function a(e){var r=e.length,t=e.numberOfChannels,o=e.sampleRate,n=new c(t,r,o),u=n.createBufferSource();u.buffer=e;var f=n.createBiquadFilter();return f.type="lowpass",u.connect(f),f.connect(n.destination),u}function i(e){for(var r=[],t=.9,o=.3,n=15;r.length<n&&t>=o;)r=l(e,t),t-=.05;if(r.length<n)throw new Error("Could not find enough samples for a reliable detection.");return r}function l(e,r){for(var t=[],o=0,n=e.length;o<n;o+=1)e[o]>r&&(t.push(o),o+=1e4);return t}function y(e){var r=[];return e.forEach(function(t,o){for(var n=function(x){var g=e[o+x]-t,_=r.some(function(h){if(h.interval===g)return h.count+=1});_||r.push({interval:g,count:1})},u=0;u<10;u+=1)n(u)}),r}function O(e){return function(r){var t=[];return r.forEach(function(o){if(o.interval!==0){for(var n=60/(o.interval/e);n<90;)n*=2;for(;n>180;)n/=2;n=Math.round(n);var u=t.some(function(f){if(f.tempo===n)return f.count+=o.count});u||t.push({tempo:n,count:o.count})}}),t}}return v}var p,b;function q(){return b||(b=1,p=k().default),p}var m=q();const A=P(m),D=j({__proto__:null,default:A},[m]);export{D as i};
1
+ import{g as P}from"./index-HBY-OdAh.js";function j(c,d){for(var s=0;s<d.length;s++){const a=d[s];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in c)){const l=Object.getOwnPropertyDescriptor(a,i);l&&Object.defineProperty(c,i,l.get?l:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}))}var v={},w;function k(){if(w)return v;w=1,Object.defineProperty(v,"__esModule",{value:!0}),v.default=d;var c=window.OfflineAudioContext||window.webkitOfflineAudioContext;function d(e){var r=a(e);return r.start(0),[i,y,O(e.sampleRate),s].reduce(function(t,o){return o(t)},r.buffer.getChannelData(0))}function s(e){return e.sort(function(r,t){return t.count-r.count}).splice(0,5)[0].tempo}function a(e){var r=e.length,t=e.numberOfChannels,o=e.sampleRate,n=new c(t,r,o),u=n.createBufferSource();u.buffer=e;var f=n.createBiquadFilter();return f.type="lowpass",u.connect(f),f.connect(n.destination),u}function i(e){for(var r=[],t=.9,o=.3,n=15;r.length<n&&t>=o;)r=l(e,t),t-=.05;if(r.length<n)throw new Error("Could not find enough samples for a reliable detection.");return r}function l(e,r){for(var t=[],o=0,n=e.length;o<n;o+=1)e[o]>r&&(t.push(o),o+=1e4);return t}function y(e){var r=[];return e.forEach(function(t,o){for(var n=function(x){var g=e[o+x]-t,_=r.some(function(h){if(h.interval===g)return h.count+=1});_||r.push({interval:g,count:1})},u=0;u<10;u+=1)n(u)}),r}function O(e){return function(r){var t=[];return r.forEach(function(o){if(o.interval!==0){for(var n=60/(o.interval/e);n<90;)n*=2;for(;n>180;)n/=2;n=Math.round(n);var u=t.some(function(f){if(f.tempo===n)return f.count+=o.count});u||t.push({tempo:n,count:o.count})}}),t}}return v}var p,b;function q(){return b||(b=1,p=k().default),p}var m=q();const A=P(m),D=j({__proto__:null,default:A},[m]);export{D as i};
@@ -1,4 +1,4 @@
1
- import{n as Qi}from"./index-B8XMgbWF.js";/*!
1
+ import{n as Qi}from"./index-HBY-OdAh.js";/*!
2
2
  * Copyright (c) 2026-present, Vanilagy and contributors
3
3
  *
4
4
  * This Source Code Form is subject to the terms of the Mozilla Public