'use client'; import { BookOpen, Globe } from 'lucide-react'; import { cn } from '@/lib/utils'; import { SlideThumbnail } from '@/components/slide-renderer/SlideThumbnail'; import { ThumbnailInteractive } from '@/components/slide-renderer/components/ThumbnailInteractive'; import type { Scene, SlideContent, InteractiveContent } from '@/lib/types/stage'; interface SceneThumbnailContentProps { readonly scene: Scene; /** * Inner thumbnail pixel size (width) for ThumbnailInteractive's iframe * scaling. Optional — when omitted, ThumbnailInteractive falls back to * a fixed default. The slide branch ignores `size` entirely and always * uses auto-measure (ResizeObserver on the parent container), so editor * rail drag never threads a per-frame pixel width through this prop. */ readonly size?: number; readonly viewportSize: number; readonly viewportRatio: number; /** Skip the live live-render path (slide + interactive iframe) when * the tile is far off-screen. */ readonly visible?: boolean; } const INTERACTIVE_FALLBACK_SIZE = 200; /** * Shared per-scene-type thumbnail render — slide gets a live * ThumbnailSlide, quiz/interactive/pbl get the same stylized mockups * that ship in playback SceneSidebar. Extracted so editor ThumbItem * and playback SceneSidebar render identical content (the user * specifically asked for parity instead of the previous icon-only stub * in Pro mode). * * Caller is responsible for the outer aspect-video card + ring; this * component only paints the inner content centered to fill. */ export function SceneThumbnailContent({ scene, size, viewportSize, viewportRatio, visible = true, }: SceneThumbnailContentProps) { if (scene.type === 'slide') { const slideContent = scene.content as SlideContent; return ( ); } if (scene.type === 'quiz') { return (
{[0, 1, 2, 3].map((i) => (
))}
); } if (scene.type === 'interactive') { const interactiveContent = scene.content as InteractiveContent; if (interactiveContent.html && visible) { return ( ); } return (
{[1, 2, 3].map((i) => (
))}
); } if (scene.type === 'pbl') { return (
{[0, 1, 2].map((col) => (
{Array.from({ length: col === 0 ? 3 : col === 1 ? 2 : 1 }).map((_, i) => (
))}
))}
); } // Exhaustive guard — Scene's `type` union is fully handled above. // The fallback only fires for forward-compat scenarios where a new // scene type is loaded by an older client. const unknownType = (scene as { type: string }).type; return (
{unknownType}
); }