import type { ReactNode, Ref } from "react"; import { Player } from "./Player"; import { PlayerControls } from "./PlayerControls"; import { Timeline } from "./Timeline"; interface RenderStatus { state: "idle" | "rendering" | "complete" | "error"; stage?: string; progress?: number; error?: string; onRender?: () => void; } interface PreviewPanelProps { projectId: string | null; hasProject: boolean; portrait: boolean; iframeRef: Ref; onIframeLoad: () => void; onTogglePlay: () => void; onSeek: (t: number) => void; /** Optional render status — pass to show rendering progress/state */ renderStatus?: RenderStatus; /** Optional slot for custom content below the timeline */ children?: ReactNode; } export function PreviewPanel({ projectId, hasProject, portrait, iframeRef, onIframeLoad, onTogglePlay, onSeek, renderStatus, children, }: PreviewPanelProps) { const renderState = renderStatus?.state ?? "idle"; return (
{hasProject && projectId ? ( <> {/* Player — takes all remaining space, constrained for portrait */}
{/* Controls — fixed height */}
{/* Timeline — capped height, internal scroll */}
{/* Render status — only shown when actively rendering, complete, or error */} {renderStatus && (renderState === "rendering" || renderState === "complete" || renderState === "error") && (
{renderState === "rendering" && (
{renderStatus.stage || "Rendering..."}
)} {renderState === "complete" && (
Complete
)} {renderState === "error" && (
{renderStatus.error} {renderStatus.onRender && ( )}
)}
)} {/* Optional custom slot */} {children} ) : (

Preview will appear here

Send a message to generate a video composition

)}
); }