diff --git a/packages/player/src/hyperframes-player.test.ts b/packages/player/src/hyperframes-player.test.ts index e91df7729..352639ccd 100644 --- a/packages/player/src/hyperframes-player.test.ts +++ b/packages/player/src/hyperframes-player.test.ts @@ -1010,6 +1010,56 @@ describe("HyperframesPlayer loop end-state handling", () => { expect(ended).toHaveBeenCalledTimes(1); expect(player._paused).toBe(true); }); + + it("play() seeks to 0 and replays when called after the video has ended", () => { + const seek = vi.spyOn(player, "seek"); + player.loop = false; + player._duration = 4; + player._paused = false; + + player._onMessage( + new MessageEvent("message", { + source: frameWindow, + data: { + source: "hf-preview", + type: "state", + frame: 120, + isPlaying: false, + }, + }), + ); + + expect(player._paused).toBe(true); + seek.mockClear(); + + player.play(); + + expect(seek).toHaveBeenCalledWith(0); + expect(player._paused).toBe(false); + }); + + it("play() does not seek to 0 when called mid-playback", () => { + const seek = vi.spyOn(player, "seek"); + player._duration = 4; + player._paused = true; + // Simulate mid-video position (frame 60 = 2s into a 4s video) + player._onMessage( + new MessageEvent("message", { + source: frameWindow, + data: { + source: "hf-preview", + type: "state", + frame: 60, + isPlaying: false, + }, + }), + ); + + player.play(); + + expect(seek).not.toHaveBeenCalled(); + expect(player._paused).toBe(false); + }); }); describe("HyperframesPlayer srcdoc attribute", () => { diff --git a/packages/player/src/hyperframes-player.ts b/packages/player/src/hyperframes-player.ts index a9cd174d0..0b43e671a 100644 --- a/packages/player/src/hyperframes-player.ts +++ b/packages/player/src/hyperframes-player.ts @@ -402,6 +402,9 @@ class HyperframesPlayer extends HTMLElement { play() { this._hidePoster(); + if (this._duration > 0 && this._currentTime >= this._duration) { + this.seek(0); + } // Always drive the iframe runtime — it's the single source of timeline // truth regardless of who owns audible output. When we own audio, the // proxies join; when the runtime owns, they stay silent. diff --git a/registry/blocks/vfx-liquid-glass/vfx-liquid-glass.html b/registry/blocks/vfx-liquid-glass/vfx-liquid-glass.html index 657dc7deb..2ac7ac054 100644 --- a/registry/blocks/vfx-liquid-glass/vfx-liquid-glass.html +++ b/registry/blocks/vfx-liquid-glass/vfx-liquid-glass.html @@ -52,20 +52,34 @@ overflow: hidden; } .text-source::before { - content: ''; + content: ""; position: absolute; - width: 700px; height: 700px; border-radius: 50%; - background: radial-gradient(circle, rgba(0,212,255,0.06) 0%, transparent 70%); - top: -150px; right: -100px; pointer-events: none; + width: 700px; + height: 700px; + border-radius: 50%; + background: radial-gradient(circle, rgba(0, 212, 255, 0.06) 0%, transparent 70%); + top: -150px; + right: -100px; + pointer-events: none; } .text-source::after { - content: ''; + content: ""; position: absolute; - width: 500px; height: 500px; border-radius: 50%; - background: radial-gradient(circle, rgba(124,58,237,0.05) 0%, transparent 70%); - bottom: -100px; left: -50px; pointer-events: none; + width: 500px; + height: 500px; + border-radius: 50%; + background: radial-gradient(circle, rgba(124, 58, 237, 0.05) 0%, transparent 70%); + bottom: -100px; + left: -50px; + pointer-events: none; + } + .badge { + font-size: 14px; + font-weight: 600; + letter-spacing: 3px; + text-transform: uppercase; + color: rgba(0, 212, 255, 0.8); } - .badge { font-size: 14px; font-weight: 600; letter-spacing: 3px; text-transform: uppercase; color: rgba(0,212,255,0.8); } .text-source h1 { font-size: 148px; font-weight: 900; @@ -83,7 +97,7 @@ .subtitle { font-size: 28px; font-weight: 400; - color: rgba(255,255,255,0.35); + color: rgba(255, 255, 255, 0.35); max-width: 800px; line-height: 1.5; } @@ -92,9 +106,23 @@ gap: 48px; margin-top: 16px; } - .stat { text-align: center; } - .stat-val { font-size: 42px; font-weight: 800; color: #00d4ff; letter-spacing: -1px; } - .stat-label { font-size: 12px; font-weight: 600; color: rgba(255,255,255,0.3); text-transform: uppercase; letter-spacing: 2px; margin-top: 4px; } + .stat { + text-align: center; + } + .stat-val { + font-size: 42px; + font-weight: 800; + color: #00d4ff; + letter-spacing: -1px; + } + .stat-label { + font-size: 12px; + font-weight: 600; + color: rgba(255, 255, 255, 0.3); + text-transform: uppercase; + letter-spacing: 2px; + margin-top: 4px; + } @@ -125,11 +153,23 @@
Write HTML → Render Video

Ship videos 10x faster

-
HTML is the source of truth for video. No timeline editors, no After Effects — just code.
+
+ HTML is the source of truth for video. No timeline editors, no After Effects — just + code. +
-
47x
Faster than AE
-
12.4K
Creators
-
2.4M
Videos Rendered
+
+
47x
+
Faster than AE
+
+
+
12.4K
+
Creators
+
+
+
2.4M
+
Videos Rendered
+
diff --git a/registry/registry.json b/registry/registry.json index 52660dc00..596c4494b 100644 --- a/registry/registry.json +++ b/registry/registry.json @@ -252,4 +252,4 @@ "type": "hyperframes:block" } ] -} \ No newline at end of file +}