import type { StoryboardFrameView } from "../../hooks/useStoryboard"; import { FramePoster, posterTime } from "./FramePoster"; import { FRAME_STATUS_META } from "./frameStatus"; export interface StoryboardFrameTileProps { projectId: string; frame: StoryboardFrameView; /** Open this frame in the full-area focus view. */ onOpen: (index: number) => void; } function firstLine(text: string): string { return ( text .split("\n") .find((line) => line.trim().length > 0) ?.trim() ?? "" ); } function placeholderMessage(frame: StoryboardFrameView): string { if (frame.status === "outline") return "Not built yet"; if (frame.src && !frame.srcExists) return "Frame file not found"; return "No preview"; } /** A single contact-sheet tile: poster preview + its metadata. Click to focus. */ // fallow-ignore-next-line complexity export function StoryboardFrameTile({ projectId, frame, onOpen }: StoryboardFrameTileProps) { const meta = FRAME_STATUS_META[frame.status]; const renderable = frame.srcExists && frame.status !== "outline"; const title = frame.title ?? `Frame ${frame.index}`; const sceneLine = frame.scene ?? firstLine(frame.narrative); return (

{title}

{meta.label}
{sceneLine &&

{sceneLine}

} {frame.voiceover && (

“{frame.voiceover}”

)}
{frame.duration && {frame.duration}} {frame.transitionIn && ↘ {frame.transitionIn}}
); } function FrameTilePlaceholder({ frame }: { frame: StoryboardFrameView }) { return (
{frame.title ?? "Outline"} {placeholderMessage(frame)}
); }