initial code (#2)

* 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>
This commit is contained in:
Vance Ingalls
2026-03-21 22:43:56 -07:00
committed by GitHub
co-authored by Claude Opus 4.6
parent 10621e7903
commit 9f8e5ba5a1
401 changed files with 54545 additions and 2 deletions
@@ -0,0 +1,70 @@
import { memo } from "react";
import { FileCode, Image, Film, Music, File } from "../../icons/SystemIcons";
interface FileTreeProps {
files: string[];
activeFile: string | null;
onSelectFile: (path: string) => void;
}
const FILE_ICONS: Record<string, { icon: typeof File; color: string }> = {
html: { icon: FileCode, color: "#3B82F6" },
css: { icon: FileCode, color: "#A855F7" },
js: { icon: FileCode, color: "#F59E0B" },
ts: { icon: FileCode, color: "#3B82F6" },
json: { icon: File, color: "#22C55E" },
png: { icon: Image, color: "#22C55E" },
jpg: { icon: Image, color: "#22C55E" },
svg: { icon: Image, color: "#F97316" },
mp4: { icon: Film, color: "#A855F7" },
mp3: { icon: Music, color: "#F59E0B" },
wav: { icon: Music, color: "#F59E0B" },
};
function getFileIcon(path: string) {
const ext = path.split(".").pop()?.toLowerCase() ?? "";
return FILE_ICONS[ext] ?? { icon: File, color: "#737373" };
}
export const FileTree = memo(function FileTree({ files, activeFile, onSelectFile }: FileTreeProps) {
const sorted = [...files].sort((a, b) => {
// index.html first, then alphabetical
if (a === "index.html") return -1;
if (b === "index.html") return 1;
return a.localeCompare(b);
});
return (
<div className="flex flex-col h-full min-h-0">
<div className="px-2.5 py-1.5 border-b border-neutral-800 flex-shrink-0">
<span className="text-2xs font-medium text-neutral-500 uppercase tracking-caps">Files</span>
</div>
<div className="flex-1 overflow-y-auto py-1">
{sorted.map((path) => {
const { icon: Icon, color } = getFileIcon(path);
const isActive = path === activeFile;
const name = path.split("/").pop() ?? path;
const dir = path.includes("/") ? path.split("/").slice(0, -1).join("/") + "/" : "";
return (
<button
key={path}
onClick={() => onSelectFile(path)}
className={`w-full flex items-center gap-2 px-2.5 py-1 min-h-7 text-left transition-all duration-press text-xs ${
isActive
? "bg-neutral-800/60 text-neutral-200"
: "text-neutral-500 hover:bg-neutral-800/30 hover:text-neutral-300 active:scale-[0.98]"
}`}
>
<Icon size={12} style={{ color }} className="flex-shrink-0" />
<span className="truncate">
{dir && <span className="text-neutral-600">{dir}</span>}
{name}
</span>
</button>
);
})}
</div>
</div>
);
});