mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-12 23:29:50 +00:00
* feat: initial code port from hyperframes-internal Port all OSS-ready packages from the internal monorepo: - @hyperframes/core — shared types, HTML generation, GSAP utilities, runtime - @hyperframes/cli — CLI for creating, previewing, and rendering compositions - @hyperframes/engine — framework-agnostic rendering engine (BeginFrame + FFmpeg) - @hyperframes/producer — video rendering pipeline (Puppeteer + FFmpeg) - @hyperframes/ui-player — browser-based video player component - @hyperframes/studio — composition editor (React frontend + Hono backend) Includes regression test suite with Docker-based test harness. All HeyGen-internal references, deployment infrastructure, and proprietary assets have been removed. Package names migrated from @app/* to @hyperframes/*. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: scrub internal codenames and stale references from OSS port - Replace static.heygen.ai runtime URLs in test fixtures - Remove internal CDN publish script (publish-hyperframe-runtime.ts) - Replace sandbox-studio, sandbox-interceptor, __magicEditRuntime with neutral names (studio, hyperframe-runtime, __hyperframeRuntime) - Fix stale Vault API / localhost references in docs - Remove broken deprecated_studio link Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove remaining internal codenames and stale references - Delete stale producer README.md and PIPELINE.md (referenced nonexistent files) - Replace "Cerberus" codename with "HyperFrames" in test design reviews - Replace magic-edit postMessage identifiers with hf-preview/hf-parent - Rename debug-magic-edit-timeline.ts to debug-timeline.ts - Replace "Motion Cut" with "HyperFrames" in Timeline comments - Fix studio/CLI references to nonexistent archive package (use local data/projects/ dir, stub render proxy) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
327 lines
10 KiB
HTML
327 lines
10 KiB
HTML
<template id="data-graphics-template">
|
|
<div data-composition-id="data-graphics" data-width="1920" data-height="1080" data-duration="16.04">
|
|
<div class="grid-container">
|
|
<!-- Graphic 1: 47% NEED MOTION GRAPHICS -->
|
|
<div id="graphic-1" class="graphic-box" style="opacity: 0;">
|
|
<div class="label">47% NEED MOTION GRAPHICS</div>
|
|
<div class="progress-bar-container">
|
|
<div class="progress-bar-bg"></div>
|
|
<div id="bar-1" class="progress-bar-fill"></div>
|
|
</div>
|
|
<div id="counter-1" class="counter">00%</div>
|
|
</div>
|
|
|
|
<!-- Graphic 2: 62% LOSE ATTENTION -->
|
|
<div id="graphic-2" class="graphic-box" style="opacity: 0;">
|
|
<div class="label">62% LOSE ATTENTION</div>
|
|
<div class="chart-container">
|
|
<div class="bar-group">
|
|
<div class="bar-label">STATIC</div>
|
|
<div class="bar-wrapper"><div id="bar-2-static" class="bar-fill gray"></div></div>
|
|
</div>
|
|
<div class="bar-group">
|
|
<div class="bar-label">MOTION</div>
|
|
<div id="counter-2" class="counter small">00%</div>
|
|
<div class="bar-wrapper"><div id="bar-2-motion" class="bar-fill green"></div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Graphic 3: 75% LACK SKILLS -->
|
|
<div id="graphic-3" class="graphic-box" style="opacity: 0;">
|
|
<div class="label">75% LACK SKILLS</div>
|
|
<div class="radial-container">
|
|
<div class="radial-svg-wrapper">
|
|
<svg viewBox="0 0 100 100" class="radial-svg">
|
|
<circle cx="50" cy="50" r="45" class="radial-bg" />
|
|
<circle id="radial-fill" cx="50" cy="50" r="45" class="radial-progress" />
|
|
</svg>
|
|
</div>
|
|
<div id="counter-3" class="counter">00%</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
@import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&display=swap');
|
|
|
|
[data-composition-id="data-graphics"] {
|
|
background: transparent;
|
|
font-family: 'Space Mono', monospace;
|
|
text-transform: uppercase;
|
|
color: #8A8A8A;
|
|
overflow: hidden;
|
|
width: 1920px;
|
|
height: 1080px;
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .grid-container {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
display: grid;
|
|
grid-template-columns: repeat(24, 1fr);
|
|
grid-template-rows: repeat(12, 1fr);
|
|
padding: 40px;
|
|
gap: 0; /* Removed gap for precise grid snapping */
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .graphic-box {
|
|
grid-column: 18 / 25; /* Positioned on the right side for A-roll scale down */
|
|
background: rgba(0, 0, 0, 0.6);
|
|
backdrop-filter: blur(10px);
|
|
-webkit-backdrop-filter: blur(10px);
|
|
border: 1px solid rgba(138, 138, 138, 0.4);
|
|
padding: 30px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: flex-start;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] #graphic-1 { grid-row: 2 / 5; margin-bottom: 10px; }
|
|
[data-composition-id="data-graphics"] #graphic-2 { grid-row: 5 / 8; margin-bottom: 10px; }
|
|
[data-composition-id="data-graphics"] #graphic-3 { grid-row: 8 / 11; }
|
|
|
|
[data-composition-id="data-graphics"] .label {
|
|
font-size: 20px;
|
|
font-weight: 700;
|
|
margin-bottom: 20px;
|
|
letter-spacing: 1px;
|
|
color: rgba(255, 255, 255, 0.9);
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .counter {
|
|
font-size: 48px;
|
|
font-weight: 700;
|
|
color: rgba(51, 255, 102, 0.9); /* Softened green with opacity */
|
|
margin-top: 15px;
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .counter.small {
|
|
font-size: 32px;
|
|
margin-top: 0;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
/* Progress Bar Styles */
|
|
[data-composition-id="data-graphics"] .progress-bar-container {
|
|
width: 100%;
|
|
height: 24px;
|
|
position: relative;
|
|
background: rgba(138, 138, 138, 0.1);
|
|
border: 1px solid rgba(138, 138, 138, 0.3);
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .progress-bar-bg {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: repeating-linear-gradient(90deg, rgba(138, 138, 138, 0.2), rgba(138, 138, 138, 0.2) 2px, transparent 2px, transparent 12px);
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .progress-bar-fill {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
height: 100%;
|
|
background: rgba(51, 255, 102, 0.8); /* Softened green */
|
|
width: 0%;
|
|
}
|
|
|
|
/* Bar Chart Styles */
|
|
[data-composition-id="data-graphics"] .chart-container {
|
|
width: 100%;
|
|
display: flex;
|
|
gap: 30px;
|
|
height: 140px;
|
|
align-items: flex-end;
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .bar-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
flex: 1;
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .bar-label {
|
|
font-size: 12px;
|
|
margin-bottom: 10px;
|
|
color: rgba(138, 138, 138, 0.8);
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .bar-wrapper {
|
|
width: 100%;
|
|
height: 100px;
|
|
background: rgba(138, 138, 138, 0.1);
|
|
border: 1px solid rgba(138, 138, 138, 0.3);
|
|
position: relative;
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .bar-fill {
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 0%;
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .bar-fill.green { background: rgba(51, 255, 102, 0.8); }
|
|
[data-composition-id="data-graphics"] .bar-fill.gray { background: rgba(138, 138, 138, 0.5); }
|
|
|
|
/* Radial Styles */
|
|
[data-composition-id="data-graphics"] .radial-container {
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 40px;
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .radial-svg-wrapper {
|
|
width: 110px;
|
|
height: 110px;
|
|
transform: rotate(-90deg);
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .radial-svg {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .radial-bg {
|
|
fill: none;
|
|
stroke: rgba(138, 138, 138, 0.2);
|
|
stroke-width: 10;
|
|
stroke-dasharray: 4 4;
|
|
}
|
|
|
|
[data-composition-id="data-graphics"] .radial-progress {
|
|
fill: none;
|
|
stroke: rgba(51, 255, 102, 0.8);
|
|
stroke-width: 10;
|
|
stroke-dasharray: 282.74; /* 2 * PI * 45 */
|
|
stroke-dashoffset: 282.74;
|
|
stroke-linecap: round;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
(function() {
|
|
const tl = gsap.timeline({ paused: true });
|
|
const REVEAL_DURATION = 0.8;
|
|
const EASE = "power2.out";
|
|
const graphicSelectors = [
|
|
'[data-composition-id="data-graphics"] #graphic-1',
|
|
'[data-composition-id="data-graphics"] #graphic-2',
|
|
'[data-composition-id="data-graphics"] #graphic-3'
|
|
];
|
|
|
|
// Helper for counter animation
|
|
function animateCounter(id, target, duration, startTime) {
|
|
const obj = { val: 0 };
|
|
const el = document.querySelector(`[data-composition-id="data-graphics"] #${id}`);
|
|
if (!el) return;
|
|
|
|
tl.to(obj, {
|
|
val: target,
|
|
duration: duration,
|
|
ease: EASE,
|
|
onUpdate: () => {
|
|
el.innerText = Math.floor(obj.val).toString().padStart(2, '0') + '%';
|
|
}
|
|
}, startTime);
|
|
}
|
|
|
|
gsap.set(graphicSelectors, { x: 24 });
|
|
|
|
// 1. 47% NEED MOTION GRAPHICS at 1.839s
|
|
tl.to('[data-composition-id="data-graphics"] #graphic-1', {
|
|
opacity: 1,
|
|
x: 0,
|
|
duration: 0.5,
|
|
ease: "power2.out"
|
|
}, 1.839);
|
|
|
|
tl.to('[data-composition-id="data-graphics"] #bar-1', {
|
|
width: '47%',
|
|
duration: REVEAL_DURATION,
|
|
ease: EASE
|
|
}, 1.839 + 0.2);
|
|
|
|
animateCounter('counter-1', 47, REVEAL_DURATION, 1.839 + 0.2);
|
|
|
|
// 2. 62% LOSE ATTENTION at 4.659s
|
|
tl.to('[data-composition-id="data-graphics"] #graphic-2', {
|
|
opacity: 1,
|
|
duration: 0.5,
|
|
ease: "power2.out"
|
|
}, 4.659);
|
|
|
|
tl.to('[data-composition-id="data-graphics"] #bar-2-static', {
|
|
height: '30%',
|
|
duration: REVEAL_DURATION,
|
|
ease: EASE
|
|
}, 4.659 + 0.2);
|
|
|
|
tl.to('[data-composition-id="data-graphics"] #bar-2-motion', {
|
|
height: '62%',
|
|
duration: REVEAL_DURATION,
|
|
ease: EASE
|
|
}, 4.659 + 0.4);
|
|
|
|
animateCounter('counter-2', 62, REVEAL_DURATION, 4.659 + 0.4);
|
|
|
|
// 3. 75% LACK SKILLS at 8.88s
|
|
tl.to('[data-composition-id="data-graphics"] #graphic-3', {
|
|
opacity: 1,
|
|
duration: 0.5,
|
|
ease: "power2.out"
|
|
}, 8.88);
|
|
|
|
const circumference = 282.74;
|
|
const offset = circumference - (0.75 * circumference);
|
|
|
|
tl.to('[data-composition-id="data-graphics"] #radial-fill', {
|
|
strokeDashoffset: offset,
|
|
duration: REVEAL_DURATION,
|
|
ease: EASE
|
|
}, 8.88 + 0.2);
|
|
|
|
animateCounter('counter-3', 75, REVEAL_DURATION, 8.88 + 0.2);
|
|
|
|
// A one-way settle keeps the UI alive without repeat/yoyo timeline noise.
|
|
const greenElements = [
|
|
'[data-composition-id="data-graphics"] .progress-bar-fill',
|
|
'[data-composition-id="data-graphics"] .bar-fill.green',
|
|
'[data-composition-id="data-graphics"] .radial-progress',
|
|
'[data-composition-id="data-graphics"] .counter'
|
|
];
|
|
|
|
gsap.set(greenElements, { opacity: 0.85 });
|
|
tl.to(greenElements, {
|
|
opacity: 1,
|
|
duration: 1.2,
|
|
stagger: 0.08,
|
|
ease: "none"
|
|
}, 2);
|
|
|
|
// Outro: Fade all out near the end
|
|
tl.to(['[data-composition-id="data-graphics"] #graphic-1', '[data-composition-id="data-graphics"] #graphic-2', '[data-composition-id="data-graphics"] #graphic-3'], {
|
|
opacity: 0,
|
|
y: 20,
|
|
duration: 0.5,
|
|
ease: "power2.in"
|
|
}, 15.5);
|
|
|
|
window.__timelines["data-graphics"] = tl;
|
|
})();
|
|
</script>
|
|
</div>
|
|
</template>
|