Commit Graph
90 Commits
Author SHA1 Message Date
Miao Yang 5d1bff51b5 fix: unblock music video ci checks 2026-06-23 22:32:51 +08:00
WaterrrForeverandClaude Opus 4.8 4db708eb4a fix(core): register sub-composition timelines after async build + lint rule (#1638)
* fix(core): register sub-composition timelines after async build + lint rule

When a composition builds its GSAP timeline inside document.fonts.ready (or any
async callback), registering window.__timelines[id] BEFORE the build leaves an
EMPTY timeline registered. The runtime's sub-composition readiness gate treats
"key present" as "ready" and nests the child once — an empty timeline gets
nested empty and is never re-nested, so the frame renders blank when used as a
sub-composition.

- registry/blocks/code-{diff,highlight,morph,scroll,typing}: register the
  timeline AFTER the fonts.ready build completes, then call
  window.__hfForceTimelineRebind() to re-nest now that it is populated.
- core lint: add rule gsap_timeline_registered_before_async_build to flag the
  early-registration anti-pattern, with tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(studio): import commitGsapPositionFromDrag from its actual module

The function was split out into gsapDragPositionCommit.ts in #1605, but the
test kept importing it from ./gsapDragCommit, which no longer exports it —
yielding 'is not a function' at runtime. Import from the correct module.

Inherited main breakage (same fix as #1631/#1635); fixes the Test CI check on
this branch independently of merge order.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 22:50:04 +08:00
Vance IngallsandClaude Opus 4.8 cc2220e59e fix(slideshow): address code-review findings #1580-1584 (#1585)
* fix(slideshow): address code-review findings #1580-1584

- player: bundle @hyperframes/core into the IIFE/global build (noExternal)
- player: resolve audience mode from ?mode=audience URL query, not just attr
- player: event-driven waitForScenes + loud failure when no slides resolve
- player: scope window keydown so Space/Backspace don't hijack the host page
- player: audience mirrors full position (branch + fragment) via syncTo
- player: next() reveals remaining fragments even at slide end; enterBranch ignores empty sequences
- core: harden extractScenes against null/non-object scene entries
- core: strict manifest validation; error on inverted ranges & empty hotspot targets; dedup fragments
- core/lint: accept data-end/timeline-derived scene durations (match runtime)
- core+studio: share ISLAND_TYPE + island regex from @hyperframes/core/slideshow
- studio: SlideList reflects manifest slide order; branch-slide authoring (notes/fragments/hotspots)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(player): slideshow fullscreen + presenter-view rework

- fullscreen toggle in the nav chrome (button + 'F' key); standard Fullscreen
  API on the <hyperframes-slideshow> element, icon reflects state
- presenter console: live slide on top, speaker-notes panel below, with the nav
  controls shown in-view; Present button hides once presenting (harness)
- audience (viewer) window: chrome reduced to a fullscreen-only control, no nav
- fix: audience / back() / backToMain() mirror stayed frozen on the first frame —
  a bare paused seek does not repaint some compositions. resumeSlide now plays a
  brief render-nudge (RENDER_NUDGE) past the target so the composition paints,
  then onTime pauses at the hold
- refactor: extract reusable buildNavCluster() + wireChromeButtons(); rework
  buildPresenterLayout into the bottom notes panel
- example: airbnb-deck presenter-test.html harness (Present button + 'F')

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(player): slideshow no auto-progress + presenter slide fits/pins

- navigation jumps to a static frame instead of auto-playing the timeline:
  playTo() seeks to the hold (+ a brief RENDER_NUDGE to repaint) rather than
  sustaining playback, so slides hold until the user advances
- presenter view: pin the live slide to the top and confine the player to the
  region above the notes panel, so the player CONTAINS the composition — the
  full slide stays visible (letterboxed) at any width and re-fits on resize;
  its bottom is no longer cut off by the notes panel
- tests: seek targets updated for the render-nudge offset

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(slideshow): presenter nav flash, slide-1 boundary, branch buttons

Three presenter-mode fixes from testing the airbnb deck: (1) navigation flash — seek to the exact target then play forward to repaint, instead of seeking backward (t-0.2) which painted the previous scene at boundaries; split hold into holdTarget (logical) and holdAt (target+nudge, clamped to slide.end). (2) slide-1 boundary — no-fragment slides rest at the slide midpoint, not slide.end. (3) presenter branch buttons — surface hotspots as buttons in the presenter console (the on-slide pill is lost in the letterboxed view). Also extract paintChrome() to dedupe the three chrome-render sites.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(slideshow): stop presenter nav buttons flickering / dropping clicks

The presenter elapsed clock called render() every second, which rebuilt the
entire chrome (innerHTML) including the nav buttons — they flickered and any
click landing mid-rebuild was lost. The 1s tick now updates only the elapsed
text node; the nav buttons are rebuilt only on actual navigation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(slideshow): CSP-safe nav hover, UUID editor ids, manifest version

Addresses review feedback on the split stack:

- CSP: replace the 8 inline onmouseover/onmouseout handlers on the nav
  buttons with a [data-hf-nav-cluster] button:hover CSS rule (injected once
  per document). No inline event handlers → works under strict CSP.
- IDs: studio sequence/hotspot id generation used Date.now() (sub-ms
  collision on rapid clicks) — now crypto.randomUUID().
- Versioning: stamp version on the persisted manifest island (preserving an
  existing one); add the optional version field + SLIDESHOW_MANIFEST_VERSION
  to the core schema so future schema changes can migrate older islands.

These live on the review-fixes tip (consistent with the stack's fixup-on-tip
model); the touched code belongs to ss-player-b (#1590), ss-studio-a/b
(#1591/#1592), and ss-core (#1580).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(ci): fix format + fallow gates for slideshow stack

- .prettierignore: exclude generated demo compositions (registry/examples/**/*.html)
  from oxfmt — large video-pipeline output (GSAP/Three/WebGL), not hand-authored
  source. Was failing 'Format' repo-wide (pre-existing on main via #1584).
- .fallowrc: exempt SlideshowPanel.tsx (health/complexity — section fan-out) and
  the slideshowPanelHelpers.ts / SlideshowPanel.test.ts parallel-structure clones
  (duplicates.ignore). File-level config, not inline comments — inline shifts line
  numbers and breaks fallow's inherited-finding fingerprint (per existing rc note).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(slideshow): address PR review + CodeQL findings

- CodeQL #638 (parseSlideshow): complete the regex metachar escape in
  slideshowIslandRegex (was missing backslash); add JSDoc on the factory +
  lastIndex caveat (reviewer 5a/16).
- CodeQL #639/#640 + review items 13/17: remove registry/examples/airbnb-deck/
  presenter-test.html — a generated test harness (postMessage w/o origin check,
  proto-pollution) that was scope-creep into a fix PR and a 3rd duplicate island.
  Regenerate locally via the scratchpad script when testing.
- Review item 15 (docs drift in skills/slideshow/SKILL.md): lint resolves scenes
  by data-composition-id only (not .clip[id]); fragments are valid INCLUSIVE of
  [start,end], not 'strictly inside'.

IIFE bundles core confirmed (0 external @hyperframes/core refs in the slideshow
global build). format/lint/fallow green.

* feat(cli): add 'present' command — serve a deck in presenter mode

hyperframes present [dir] starts a lightweight HTTP server, wraps the
composition in <hyperframes-slideshow> with its island inlined, and opens
the browser. A real HTTP origin is required for presenter mode: present()
opens the audience window via window.open(?mode=audience) and the two sync
over BroadcastChannel — neither works from file://.

- New utils/compositionServer.ts factors the server scaffolding shared with
  'play' (resolve runtime/player/slideshow bundles, inject runtime, asset
  content-types, bind to a free port); play.ts now uses it too.
- Errors clearly if the deck has no slideshow island.
- .fallowrc: exempt the play/present command entrypoints (validation + server
  wiring) and the per-command startup/logging block from the complexity /
  duplication gates.

Verified end-to-end against registry/examples/airbnb-deck: server serves the
wrapper + assets, the component binds and renders (counter 1 / 11).

* fix(cli): present renders the deck (player sizing + self-driving serve)

Two bugs caused a black slide area:
- The <hyperframes-player> had no positioning, so its iframe collapsed to
  zero size — the (absolutely-positioned) chrome showed but the composition
  didn't. Add position:absolute; inset:0 (matches demo.html).
- The composition was served with the engine runtime injected, which leaves
  its timelines engine-paused (blank). Slideshow decks self-drive their own
  timelines (like demo.html / the standalone harness), so serve them raw.

Verified end-to-end on registry/examples/airbnb-deck: cover renders, Next
advances 1/11 -> 2/11 and slide 2 paints.

* fix(cli): present plays slideshow sound effects

The composition (in the player's sandboxed iframe) posts
{ type: 'hf-sfx', name } to the parent on nav, but the iframe is
autoplay-blocked — audio must play in the parent that owns the user gesture.
Add the parent-side hf-sfx handler (the 4 standard clips advance/fragment/
branch-enter/back, served from the deck's sfx/ under /composition/sfx/),
gesture-unlocked and mute-aware, in both presenter and audience windows.

Verified: sfx serve 200 (audio/mpeg) and Next delivers [advance, fragment]
to the parent handler.

* feat(examples): softer mellow slideshow sfx for airbnb-deck

Replace the aggressive percussive pops with gentle sine-tone cues (warm
pitches C5/G4/E5/F4, 12ms attack + exponential decay, lowpassed) — advance/
fragment/branch-enter/back. Much lighter; fragment is the most subtle.

* feat(examples): whoosh + sparkle slideshow sfx for airbnb-deck

Replace the sine-tone cues with airy, designed sounds:
- advance: a soft whoosh (band-limited pink noise, bell-shaped swell)
- back: that whoosh reversed and darkened
- fragment: a light sparkle (staggered high chime blips)
- branch-enter: whoosh + a trailing sparkle (magical entry)

* feat(examples): directional whoosh + richer branch-enter cue (airbnb-deck)

- Going backward a slide now plays the reverse whoosh (back), not advance —
  the sfx logic detects nav direction by scene order instead of firing advance
  for every scene change.
- branch-enter is now a more interesting magical cue: a faint whoosh + an
  ascending C5-E5-G5-C6 chime arpeggio + a trailing sparkle.

Verified: next then prev fires [advance, fragment, back]; no page errors.

* fix(cli): harden present sfx handler + mute-hover affordance (R2 review)

Addresses Rames R2 items 19-21:
- 20: the present audio handler reintroduced the CodeQL classes removed with
  presenter-test.html — add an origin check (same-origin composition iframe)
  and an own-property guard so a 'name' like __proto__ can't resolve to and
  mutate Object.prototype.
- 21: assetContentType used a bare index lookup (ext='__proto__' -> prototype);
  guard with Object.hasOwn.
- 19: the CSP hover rule erased the speaker button's muted color; add a
  higher-specificity [data-hf-muted] [data-hf-mute]:hover override.

Verified: hf-sfx origin matches location.origin (guard passes), advance/fragment
still fire, deck renders + advances. Items 14/18/22 deferred (minor, pre-existing).

* fix(slideshow): address remaining R2 items (14/18/22) + re-remove harness

- 14: resumeSlide now mirrors enterSlide — a no-fragment slide resumes at its
  midpoint (visible-at-rest), not frame-0; fragmented slides still resume to the
  saved fragment or slide.start. Added a dedicated test naming the heuristic.
- 18: fullscreenchange swaps only the fullscreen glyph + aria (hoisted SVGs to
  module consts) instead of re-rendering the whole chrome.
- 22: .prettierignore lists the specific generated demo compositions instead of
  blanket registry/examples/**/*.html, so hand-authored example HTML still formats.
- presenter-test.html: a stray 54a4460 git add -A had re-added the deleted
  harness (reviving CodeQL #639/#640); remove it again.

106 slideshow tests pass; tsc/lint/fallow/format clean; deck still renders.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 03:26:49 -07:00
Vance IngallsandClaude Opus 4.8 ae40498433 test(examples): slideshow demos — airbnb deck, startup pitch, fixture (#1584)
* feat(player): slideshow controller state machine

Stack-split from the original ss-player PR (#1581): the SlideshowController
state machine (stack-based slide/fragment/branch navigation) and its tests.
The <hyperframes-slideshow> web component follows in the next PR.

* feat(player): <hyperframes-slideshow> web component + presenter

Stack-split from the original ss-player PR (#1581): the <hyperframes-slideshow>
custom element (wraps <hyperframes-player>, drives the controller),
presenter/audience BroadcastChannel sync, nav chrome, and the player scenes hook.

* feat(studio): slideshow manifest persistence + panel helpers

Stack-split from the original ss-studio PR (#1582): the data layer —
setSlideshowManifest, the useSlideshowPersist hook, and panel helpers.
The editor panel UI follows in the next PR.

* feat(studio): slideshow branching editor panel UI

Stack-split from the original ss-studio PR (#1582): the SlideshowPanel /
SlideshowSubPanels editor UI, right-panel wiring, and app integration.

* docs(skill): slideshow authoring guidance + standalone harness reference

New /slideshow skill (island schema, slide rules, fragments, branching,
validation) + a standalone-harness reference doc, and a router entry in
the /hyperframes skill.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(examples): slideshow demos — airbnb deck, startup pitch, fixture

Three runnable slideshow compositions: a current-Airbnb-branded remake of
the 2009 seed deck (Three.js backgrounds, GSAP entrances, hotspot branch,
HeyGen SFX), an animated startup pitch, and a minimal fixture.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 01:35:23 -07:00
Vance IngallsandClaude Sonnet 4.6 386df23a74 fix(lint): promote rules to errors with registry exemptions and false-positive fixes (#1495)
* fix(lint): promote rules to errors with registry exemptions and false-positive fixes

- Export isRegistrySourceFile/isRegistryInstalledFile from composition.ts
- Add registry exemptions to google_fonts_import and font_family_without_font_face
- Add registry exemption to requestanimationframe_in_composition
- Fix timed_element_missing_clip_class: data-track-index alone no longer triggers
- Fix caption_transcript_parse_error: balanced-bracket scanner replaces non-greedy regex
- Fix missing_timeline_registry: skips sub-compositions and template-wrapped files
- Fix scene_layer_missing_visibility_kill: strip JS comments before pattern matching
- Fix gsap_css_transform_conflict: exempt from() alongside fromTo()
- Fix gsap_from_opacity_noop: only fires when opacity value is actually 0
- Add regression test for data-track-index-only elements

* test(lint): add regression tests for false-positive fixes

Covers the 7 missing negative-case assertions flagged in PR review:
- registry marker suppresses google_fonts_import + font_family_without_font_face
- registry marker suppresses requestanimationframe_in_composition
- isSubComposition suppresses missing_timeline_registry
- scene_layer_missing_visibility_kill: fires, commented-kill fires, real kill suppresses
- gsap_css_transform_conflict: from() exempt alongside fromTo()
- gsap_from_opacity_noop: non-zero opacity (e.g. 0.5) is a valid reveal, not a noop

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(examples): fix warm-grain template to pass promoted lint rules

- index.html: remove undeclared "Lexend" from font-family stack
- intro.html: replace Google Fonts @import with bundled Inter font
- captions.html: quote TRANSCRIPT keys for valid JSON + use Inter font

Fixes CLI smoke CI failure after google_fonts_import, font_family_without_font_face,
and caption_transcript_parse_error were promoted from warning to error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(cli): resolve warm-grain from repo registry in dev mode + bundle at build

getStaticTemplateDir now falls back to registry/examples/<id> in dev mode
so CI smoke tests use the PR-branch copy instead of fetching from main.
build-copy.mjs copies warm-grain to dist/templates/warm-grain at build time
so packed CLIs can scaffold it offline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(examples): remove trailing comma from warm-grain TRANSCRIPT array

JSON.parse rejects trailing commas (valid JS, invalid JSON).
caption_transcript_parse_error was still firing because of the comma
on the last entry after quoting all keys.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 21:13:00 -07:00
Miguel Ángel 07030294e0 feat(registry): add Code Animations catalog section (9 blocks, incl. GPU)
Adds a Code Animations catalog section — 9 self-contained, installable blocks:
morph, snippet-flight, typing, diff, highlight, scroll (DOM/GSAP) and 3d-extrude,
shader-dissolve, particle-assemble (WebGL). Each block ships only its own effect and
renders deterministically (paused GSAP timeline seeked per frame, seeded RNG, no
render-time data fetch). Wires the catalog nav, registry.json, a new code-animation
Studio category, and preview assets.
2026-06-15 21:32:45 -04:00
James RussoandClaude Opus 4.8 e845793ce1 chore: shrink repo — untrack failure frames, recompress backgrounds, harden LFS (#1326)
No-coordination repo-size cleanup (no history rewrite — SHAs unchanged):

- Untrack 158 producer regression-test failure artifacts (~27 MB); already
  gitignored, on-disk copies kept.
- Recompress 13 byte-identical code-snippet block backgrounds (5120x2880/3.3MB
  -> 2560x1440 q78/~428KB): 42 MB -> 5.4 MB. Per-block files kept for portability.
- Recursive LFS patterns (packages/producer/tests/**/*.{mp4,mov,webm,png}) +
  globalized *.onnx — closes the nested-path leak.
- Recursive .gitignore for tests/**/failures/ at any depth.
- scripts/check-large-files.sh + lefthook `largefiles` gate (>500KB non-LFS
  fails commit; excludes registry/). Review fixes: ceiling division, skip
  symlinks, space-safe staged-file read.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 16:05:45 -07:00
Vance IngallsandClaude Sonnet 4.6 1fd1b3164a feat(catalog): add motion-blur component (#1274)
* feat(catalog): add motion-blur component

Velocity-driven directional motion blur using SVG filter ghost copies.
Ghost-copy approach gives one-sided trail; feGaussianBlur top layer keeps
element blurry during movement. Uses tween onUpdate pattern (not
tl.eventCallback) so it works in the HyperFrames headless renderer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: remove accidentally committed .thumbnails cache

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(catalog): address motion-blur review feedback

- registry-item.json: fix description — SVG feGaussianBlur ghost trail,
  not CSS blur/horizontal stretch
- motion-blur.html/demo.html/index.html: fix _hfMbUid counter — use
  window._hfMbUid++ directly so re-evaluation doesn't reset and produce
  duplicate filter IDs
- demo.html/index.html: fix stretchMax default (0.5 → 0) and add
  missing stretchMax > 0 apply/cleanup blocks to match canonical snippet

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 00:50:09 -07:00
48fcf4ada5 feat(registry): add morph-text component and text-effects catalog section (#1247)
* feat(gsap): add innerText support to GSAP inspector for counter animations (#1244)

Adds 'innerText' as a supported GSAP property so number roll-up animations
(count-up from 0 to some value) are visible and editable in the GSAP inspector
panel.

- Add 'innerText' to SUPPORTED_PROPS in gsapConstants.ts
- Add label 'Counter Value', tooltip, and step constraint (1) in
  gsapAnimationConstants.ts

The snap modifier that controls integer rounding is already preserved
verbatim via the EXTRAS_KEYS round-trip, so rounding behavior survives
edits without any additional UI changes.

Closes #1179

* feat(registry): add text-effects catalog section and morph-text component

Introduces a new "Text Effects" catalog section (below Effects) for text-focused visual components.

- Add `text-effects` BlockCategory to core registry types with violet color
- Add `text-effect` tag resolver in resolveBlockCategory (checked before generic `effect` tag)
- Tag caption-blend-difference, texture-mask-text, and morph-text with `text-effect`
- Update studio catalog order and color map to include text-effects
- Add morph-text component: gooey SVG threshold morph cycling through editable statements
  using GSAP seekable proxy pattern for deterministic/seekable rendering

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore(registry): add morph-text preview video

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore(registry): fix morph-text.html formatting

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(catalog): add Text Effects section and morph-text page

Moves caption-blend-difference and texture-mask-text out of Effects into a new
"Text Effects" section below it. Adds morph-text component page with install
instructions and preview video.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore(registry): add demo.html for morph-text catalog preview rendering

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(registry): address PR review feedback on morph-text and text-effects

- Restore `effect` tag on caption-blend-difference and texture-mask-text
  alongside `text-effect` so existing tag-equality searches/analytics still match
- Fix morphPause script fallback from "0.25" to "1.5" to match data attribute default
- Add Math.max(0, ...) guard to blur values (intent clarity)
- Add prefers-reduced-motion: skip morph and show first word statically
- Remove CATEGORY_ORDER record from useBlockCatalog; derive order from
  BLOCK_CATEGORIES array (single source of truth, no drift)
- Add comment to demo.html documenting its purpose (catalog preview script only)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Miguel Ángel <miguel.sierra@heygen.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 10:55:13 -07:00
Miguel Ángel d8ed343d71 fix(registry): add 14 missing blocks to registry manifest (#1163)
Adds entries for all blocks in registry/blocks/ that were missing
from registry/registry.json:

- 12 VS Code code-snippet-* blocks (from #1113, same missed step)
- flowchart-vertical
- vfx-liquid-glass

Without these entries the CLI returns 'Item not found in registry'
even though the block files exist.
2026-06-02 12:19:19 -04:00
Miguel Ángel e9949d76ec fix(registry): add Apple Terminal blocks to registry manifest (#1162)
The 12 code-snippet-apple-terminal-* blocks were missing from
registry/registry.json so the CLI couldn't resolve them. Adds all
12 entries so npx hyperframes add code-snippet-apple-terminal-<theme>
and npx hyperframes add apple-terminal work correctly.
2026-06-02 12:17:44 -04:00
Miguel ÁngelandClaude Sonnet 4.6 689deaf4b8 feat(registry): add Apple Terminal theme code snippet blocks (#1161)
* feat(registry): add Apple Terminal theme code snippet blocks

Adds 12 Apple Terminal built-in profile visualizer blocks to the
Code Snippets catalog section, following the same pattern as the
VS Code theme blocks (commit 5245e190).

Themes: Basic, Clear Dark, Clear Light, Grass, Homebrew, Man Page,
Novel, Ocean, Pro, Red Sands, Silver Aerogel, Solid Colors.

Each block is a self-contained 1920×1080 composition showing a
macOS Terminal.app window in the matching profile colors, with
per-character GSAP typing animation and window.__timelines contract.

Install individually:
  npx hyperframes add code-snippet-apple-terminal-basic

Install all Apple Terminal themes:
  npx hyperframes add apple-terminal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(registry): remove placeholder preview URLs for unrendered Apple Terminal themes

The 8 themes without rendered videos (clear-dark, homebrew, novel,
ocean, pro, red-sands, silver-aerogel, solid-colors) had preview.video
URLs pointing to non-existent S3 objects, returning 403. Removed the
preview field from their registry-item.json and the video embed from
their MDX pages until renders are available.

The 4 themes with uploaded videos (basic, clear-light, grass, man-page)
retain their preview URLs and are live on CDN.

* fix(registry): add apple-terminal tag so npx hyperframes add apple-terminal works

* feat(registry): render + upload all 12 Apple Terminal preview videos to CDN

Rendered the 8 missing themes (clear-dark, homebrew, novel, ocean, pro,
red-sands, silver-aerogel, solid-colors) using npx hyperframes@latest
render and uploaded to the hyperframes CDN. All 12 themes now have
live preview.video URLs and video embeds in their MDX pages.

All 12 CDN URLs return 200.

* style: format Apple Terminal HTML and JSON files with oxfmt

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 12:12:46 -04:00
Miguel Ángel 5245e19062 feat(registry): add code snippet blocks with VS Code workbench (#1113)
* feat(registry): add VS Code theme visualizer example

Full VS Code workbench recreation with per-character typing animation
across 12 built-in themes. Includes activity bar, sidebar, tabs,
editor with line-by-line cursor tracking, terminal panel, and status
bar — all driven by official VS Code theme JSON files.

Themes: Dark Modern, Dark 2026, Dark+, Light Modern, Light 2026,
Light+, Visual Studio Dark, Visual Studio Light, High Contrast,
High Contrast Light, Solarized Light, Monokai.

Includes build scripts to regenerate compositions from theme JSON.

* feat(registry): add 12 code snippet blocks for hyperframes add code

Individual blocks for each VS Code built-in theme, all tagged "code"
so `npx hyperframes add code` installs the full set.

Each block is a self-contained VS Code workbench with per-character
typing animation, activity bar, sidebar, tabs, terminal, and status
bar driven by official theme JSON data.

* docs: add mdx pages for code snippet blocks and example

- 12 block doc pages under catalog/blocks/code-snippet-*
- "Code Snippets" nav group in docs.json
- vscode-theme-visualizer entry in examples.mdx

* docs: revert examples.mdx — code snippets belong in catalog only

* docs: drop redundant 'Code Snippet' prefix from sidebar titles

* docs: add video previews to code snippet catalog pages

* style: format HTML, CSS, and MJS files for CI

* fix: address review feedback — build pipeline, LICENSE, dead code, nav order

1. Build script now regenerates both example compositions AND published
   blocks in registry/blocks/code-snippet-*/, keeping them in sync.
2. Add MIT LICENSE for vendored VS Code theme JSONs (microsoft/vscode).
3. Remove dead `chars` variable from runtime, build script, all blocks,
   and all example compositions.
4. Alphabetize Code Snippets nav group in docs.json to match catalog
   convention.

* style: format all build-generated files (render-entries, CSS, index)
2026-05-28 16:02:44 -04:00
Miguel Ángel b37236ed97 fix(registry): match Tahoe notification motion 2026-05-24 01:19:24 -04:00
Miguel Ángel 4819d84786 feat(registry): polish macOS Tahoe liquid glass 2026-05-24 00:44:21 -04:00
Miguel Ángel 83dc57ad77 feat(registry): frost liquid glass widgets 2026-05-23 23:25:44 -04:00
Miguel Ángel f9fcf33c08 feat(registry): polish liquid glass previews 2026-05-23 22:37:37 -04:00
Miguel Ángel 4913bf3782 feat(registry): refine iOS Liquid Glass home screen 2026-05-23 20:52:30 -04:00
Miguel Ángel f63c2d40fb docs: remove stale liquid glass catalog entry 2026-05-23 19:49:56 -04:00
Miguel Ángel 3224a5d581 feat(registry): polish Liquid Glass catalog blocks 2026-05-23 19:34:00 -04:00
Miguel Ángel eb7ca3c1c0 fix: fully remove glass lens, zoom camera closer to iPhone screen 2026-05-23 16:51:50 -04:00
Miguel Ángel ccf0812c95 fix: remove glass lens from iOS 26, improve background, fix macOS Tahoe layout 2026-05-23 16:49:22 -04:00
Miguel Ángel 92bec1b395 fix: macOS Tahoe camera focuses on MacBook, zoom-out animation 2026-05-23 16:42:49 -04:00
Miguel Ángel 5f02161ec1 fix: iOS 26 zoom-out camera, notification glass paint cycle, engine WebGPU flag 2026-05-23 16:35:50 -04:00
Miguel Ángel 1891578dd6 feat(engine): add --enable-unsafe-webgpu flag for WebGPU glass rendering
Adds WebGPU support to the Chrome launch args alongside the existing
CanvasDrawElement flag. Use PRODUCER_HEADLESS_SHELL_PATH to point to
Brave for full WebGPU + drawElementImage support.

Also fixes flicker in liquid glass blocks by removing onpaint/requestPaint
callbacks that conflicted with GSAP's deterministic onUpdate rendering.

Adds macos-tahoe-liquid-glass block (WIP).
2026-05-23 16:23:32 -04:00
Miguel Ángel d88df39613 feat(registry): iOS 26 liquid glass home screen on 3D GLTF iPhone
Replaces the phone screen content in vfx-iphone-device with an iOS 26
home screen: glass app icons (Weather, Stocks, ChatGPT, Slack, X, etc.),
status bar with battery/signal, search pill, dock with badges. All on a
real GLTF iPhone model with camera choreography.
2026-05-23 16:13:10 -04:00
Miguel Ángel 5b8fc0107c feat(registry): iOS 26 liquid glass home screen block (WIP — 3D rendering) 2026-05-23 15:57:14 -04:00
Miguel Ángel 23037e7f0d feat(registry): liquid glass blocks + iOS 26 home screen (WIP)
- 4 liquid glass component blocks with WebGPU glass via
  liquid-glass-html-in-canvas (25KB): notification, context menu,
  media controls, widgets
- iOS 26 liquid glass home screen block (WIP): 3D iPhone with
  layoutsubtree canvas showing app grid with glass icons
- All blocks use 3-layer architecture: Three.js shader (z:0),
  glass panels in layoutsubtree canvas (z:1), CSS text overlay (z:2)
- Renders via Brave with WebGPU + drawElementImage flags
2026-05-23 15:38:57 -04:00
Miguel Ángel 9b9e49c5f8 fix(registry): notification block — top-right positioning, working glass panels 2026-05-23 15:18:10 -04:00
Miguel Ángel 77588b0759 feat(registry): rewrite liquid glass blocks with liquid-glass-html-in-canvas
Complete rewrite of all 4 liquid glass registry blocks using
jeantimex/liquid-glass-html-in-canvas for real WebGPU glass rendering.

Architecture: Three.js aurora shader (z:0) + empty glass panels in
layoutsubtree canvas (z:1) + CSS text overlay (z:2). Text is crisp
and never passes through the glass shader.

- Renders via Brave with WebGPU + drawElementImage flags
- Continuous motion throughout — panels sweep across the screen
- liquid-glass.iife.js bundle (25KB) replaces liquid-dom (88KB)
2026-05-23 15:10:10 -04:00
Miguel ÁngelandKanyini 618ac7f5b3 fix(registry): dark body background eliminates visible grid gaps
The #f6f6f4 off-white background was showing through the 30px grid
gaps and behind translated cards during the zoom/unzoom transitions,
creating visible white strips in the rendered video. Changed to
#1a1a20 (near-black) so gaps read as intentional dark separators.

Also added a .zoom-backdrop div behind the grid in the zoom demo that
fades to the focus card's gold gradient during the transition, covering
any gaps left by sibling cards translating off-screen.

Co-authored-by: Kanyini <onebenson@gmail.com>
2026-05-22 19:42:53 -04:00
Miguel ÁngelandKanyini fa58903eb4 fix(registry): work around CDP subpixel capture artifact
The renderer's Page.captureScreenshot can introduce a 1-2px offset
at viewport boundaries due to compositor subpixel rounding. Grid rows
are now 341px (3×341 + 2×30 = 1083), overflowing the 1080 viewport
by 3px. The overflow is clipped by overflow: hidden, but ensures any
capture offset still sees grid content rather than the body background.

Also removed flex centering from .demo-canvas — unnecessary now that
the grid fills the viewport, and it was a source of non-deterministic
positioning under multi-worker rendering.

Co-authored-by: Kanyini <onebenson@gmail.com>
2026-05-22 19:28:52 -04:00
Miguel ÁngelandKanyini f0b0b977e0 fix(registry): edge-to-edge grid eliminates background bleed
Cards 360×340 with 30px gap = exactly 1920×1080. No body background
visible at any frame. Focus scale drops from 9 to 6 (360×6 = 2160,
still overshoots viewport by 240px).

Co-authored-by: Kanyini <onebenson@gmail.com>
2026-05-22 19:19:29 -04:00
Miguel ÁngelandKanyini 15e92e2299 fix(registry): fix rendering artifacts in parallax-zoom/unzoom demos
- Increase --focus-scale from 8 to 9 — at scale 8 the card matched
  the viewport width exactly (240×8=1920), leaving zero tolerance for
  subpixel rounding. Scale 9 overshoots by 240px on each axis.

- Reduce grid gap from 40px to 24px — the 1040px grid in a 1080px
  viewport left only 20px of padding, causing bottom-row cards and
  their box-shadows to clip at the frame edge.

- Remove transform-style: preserve-3d from both snippets — no 3D
  transforms are used, and preserve-3d can cause compositing artifacts
  with overflow: hidden ancestors.

- Unzoom: set --pu-sibling-fade to 0 and drive sibling opacity via
  GSAP (starting at t=2.0s). Previously, CSS-driven opacity made cards
  70% visible when they first peeked into the viewport, creating
  colored strips at the frame edge during the reveal.

Co-authored-by: Kanyini <onebenson@gmail.com>
2026-05-22 19:09:30 -04:00
Miguel ÁngelandKanyini babf9dc15a feat(registry): add parallax-zoom and parallax-unzoom components
Two companion components inspired by the eBay Playbook hero transition:

- parallax-zoom: center card scales up to fill the frame while siblings
  parallax outward. Single CSS variable (--pz-progress 0→1), fully
  seekable and deterministic.

- parallax-unzoom: the reverse — focus card starts at full-frame scale
  and shrinks back into its grid position while siblings parallax inward.
  Uses --pu-progress with the pu prefix to avoid variable collisions when
  both components live in the same composition.

Designed to chain: zoom INTO a card in scene 1, unzoom OUT of it in
scene 2 to reveal a fresh grid underneath.

Includes demo compositions, registry manifests, and catalog pages.
Preview assets rendered and uploaded to CDN.

Co-authored-by: Kanyini <onebenson@gmail.com>
2026-05-22 18:42:50 -04:00
Miguel Ángel b58a81160e Merge pull request #933 from heygen-com/05-18-feat_registry_add_blend-difference_text_effect_component
feat(registry): add blend-difference text effect component
2026-05-21 21:28:56 +02:00
Miguel Ángel ec66d59caa fix(registry): add pointer-events: none to caption component roots
Caption components are overlays — their root element should not
intercept pointer events, allowing clicks to pass through to the
underlying composition content in Studio.
2026-05-20 02:20:16 -04:00
Miguel Ángel 335ec45bc2 style(registry): format caption component HTML files 2026-05-20 02:08:57 -04:00
Miguel Ángel 0187a82a6f fix(registry): transparent backgrounds on all caption components
Replace opaque backgrounds (#0a0a0a, #000, #000000) with transparent
on both html/body and the composition root div for all 15 caption
components. Captions are overlays — opaque backgrounds cover the
underlying video when loaded as sub-compositions.
2026-05-20 02:02:12 -04:00
Miguel Ángel 471b4efb4b feat: data-timeline-locked + fix font loss in sub-compositions
Timeline locking:
- Add data-timeline-locked attribute support — fully disables move,
  trim-start, and trim-end in Studio for clips that carry this attr
- Runtime propagates the attribute from inner composition root to host
  element so component authors control it from their HTML
- All 15 caption components in the registry now carry the attribute

Font fix:
- Extract <link rel="stylesheet"> and <link rel="preconnect"> from
  sub-composition <head> alongside existing <style>/<script> extraction
- Fixes caption components (and any sub-comp using Google Fonts via
  <link> tags) losing their font-family when loaded as sub-compositions
- Applied in both runtime (compositionLoader) and compiler
  (inlineSubCompositions) paths
2026-05-20 01:55:17 -04:00
Vance Ingalls 75a34d34e3 fix(registry): add demo.html for caption-blend-difference
Catalog preview script (scripts/generate-catalog-previews.ts) uses demo.html
as the component entry point. Missing file caused the Render catalog previews
job to fail with "Item not found".
2026-05-19 17:07:30 -07:00
Miguel Ángel ffbc18ad31 feat(studio): full Blocks panel — browse, search, add, drag-and-drop registry items
Adds a Blocks tab to the Studio left sidebar with the full 78-item registry
catalog (58 blocks + 20 components). Users can browse by category, search by
title/description, preview CDN-hosted poster thumbnails with video-on-hover,
and install items on-demand with one click or drag-to-timeline.

Core changes:
- BlockCategory type + resolveBlockCategory() for 7 categories (Captions, VFX,
  Transitions, Effects, Social, Data, Scenes)
- Registry API routes: GET /api/registry/blocks (catalog) + POST install
- StudioApiAdapter extended with listRegistryCatalog + installRegistryBlock
- Vite adapter reads from disk; CLI adapter fetches from GitHub (24h cache)
- BlockParam interface + params on 6 blocks for future parameter controls

Studio UI:
- 4th sidebar tab "Blocks" with responsive grid, category pills, search bar
- BlockCard: CDN poster thumbnail, video autoplay on hover, duration + WebGL badges
- On-demand install: blocks append as sub-compositions on timeline; components
  overlay at start=0 spanning full duration with transparent background patching
- TIMELINE_BLOCK_MIME drag-and-drop to timeline
- BlockParamsPanel (Phase 3 scaffold) auto-opens for parameterized blocks

Registry manifests:
- All 58 blocks backfilled with preview: { video, poster } CDN URLs
- All 20 components normalized to object format + poster URLs added
- 6 blocks annotated with params (Liquid Glass/Background, Portal, Chart,
  Logo Outro, Magnetic)
- flowchart-vertical preview generated and uploaded to CDN
2026-05-18 21:15:15 -04:00
Miguel Ángel 09af2f9cc1 feat(registry): rename caption-texture-lava to caption-texture with multi-texture support
Rename component to caption-texture and bundle 6 popular textures
(lava, marble, metal, wood, concrete, rock). The texture is configurable
via the texture composition variable (default: lava).

Usage: hyperframes render --variables '{"texture":"marble-012"}'

Tested: lava, marble-012, metal-046-b all render correctly with
distinct visual patterns.
2026-05-18 12:40:48 -04:00
Vance Ingalls bed1ca653c feat(registry): add blend-difference text effect component 2026-05-18 09:15:45 -07:00
Miguel Ángel 8b4c994611 style: format us-map and world-map after stagger change 2026-05-18 01:24:30 -04:00
Miguel Ángel 4b9abaaf6f fix: deterministic stagger, lint importmap/module, cache-bust previews
- Replace from:"random" with from:"center" stagger in us-map,
  world-map, spain-map — random stagger is non-deterministic across
  parallel render workers, causing visual jumps at chunk boundaries.

- Exempt type="importmap" and type="module" inline scripts from the
  invalid_inline_script_syntax lint rule. The rule used new Function()
  to parse, which rejects import statements and JSON import maps.
  Closes #929.

- Cache-bust all map MDX preview video URLs after re-rendering with
  the deterministic stagger fix.
2026-05-18 01:18:24 -04:00
Miguel Ángel ae1716d4c1 feat(registry): add spain-map block + fix MDX preview paths
New block: spain-map — animated Spain choropleth by autonomous
community using D3 conic conformal projection with GDP per capita
data and red-to-amber color scale.

Also switches all map MDX preview URLs from S3 to local paths
so they render in mintlify dev without needing S3 upload first.
2026-05-17 23:25:47 -04:00
Miguel Ángel dba158dfc1 feat(registry): add maps section with 4 new map blocks + docs
New blocks: world-map (D3 Natural Earth choropleth), us-map-bubble
(proportional city markers), us-map-hex (hexagonal tile grid),
us-map-flow (animated connection arcs between cities).

All blocks share the same dark theme and are composable — layer
bubble or flow on top of the choropleth via track indexes.

Adds "Maps" section to the catalog docs with MDX pages for all 5
map blocks (including the us-map from the previous commit).
2026-05-17 23:16:41 -04:00
Miguel Ángel b443e7e076 feat(registry): add us-map choropleth block
Animated US population density choropleth using D3 geoAlbersUsa
projection with TopoJSON. Includes staggered state reveals, label
fade-ins, gradient legend, and highlight pulses on densest states.
2026-05-17 23:03:35 -04:00
Miguel Ángel 0be66f9446 fix(registry): replace gradient-fill with Siri-style rainbow shimmer 2026-05-17 21:31:52 -04:00