import type { ReactNode } from "react"; import { NLELayout } from "./nle/NLELayout"; import { CaptionOverlay } from "../captions/components/CaptionOverlay"; import { CaptionTimeline } from "../captions/components/CaptionTimeline"; import { DomEditOverlay } from "./editor/DomEditOverlay"; import type { TimelineElement } from "../player"; import type { BlockedTimelineEditIntent } from "../player/components/timelineEditing"; import { STUDIO_INSPECTOR_PANELS_ENABLED, STUDIO_PREVIEW_MANUAL_EDITING_ENABLED, STUDIO_PREVIEW_SELECTION_ENABLED, } from "./editor/manualEditingAvailability"; import { useStudioContext } from "../contexts/StudioContext"; import { useDomEditContext } from "../contexts/DomEditContext"; export interface StudioPreviewAreaProps { timelineToolbar: ReactNode; renderClipContent: ( element: TimelineElement, style: { clip: string; label: string }, ) => ReactNode; // Timeline editing handleTimelineElementDelete: (element: TimelineElement) => Promise | void; handleTimelineAssetDrop: ( assetPath: string, placement: Pick, ) => Promise | void; handleTimelineFileDrop: ( files: File[], placement?: Pick, ) => Promise | void; handleTimelineElementMove: ( element: TimelineElement, updates: Pick, ) => Promise | void; handleTimelineElementResize: ( element: TimelineElement, updates: Pick, ) => Promise | void; handleBlockedTimelineEdit: (element: TimelineElement, intent: BlockedTimelineEditIntent) => void; setCompIdToSrc: (map: Map) => void; setCompositionLoading: (loading: boolean) => void; shouldShowSelectedDomBounds: boolean; } export function StudioPreviewArea({ timelineToolbar, renderClipContent, handleTimelineElementDelete, handleTimelineAssetDrop, handleTimelineFileDrop, handleTimelineElementMove, handleTimelineElementResize, handleBlockedTimelineEdit, setCompIdToSrc, setCompositionLoading, shouldShowSelectedDomBounds, }: StudioPreviewAreaProps) { const { projectId, refreshKey, activeCompPath, setActiveCompPath, captionEditMode, compositionLoading, isPlaying, previewIframeRef, refreshPreviewDocumentVersion, handlePreviewIframeRef, timelineVisible, toggleTimelineVisibility, } = useStudioContext(); const { domEditHoverSelection, domEditSelection, domEditGroupSelections, handleTimelineElementSelect, handlePreviewCanvasMouseDown, handlePreviewCanvasPointerMove, handlePreviewCanvasPointerLeave, applyDomSelection, handleBlockedDomMove, handleDomManualDragStart, handleDomPathOffsetCommit, handleDomGroupPathOffsetCommit, handleDomBoxSizeCommit, handleDomRotationCommit, } = useDomEditContext(); return (
{ // Sync activeCompPath when user drills down via timeline double-click // or navigates back via breadcrumb — keeps sidebar + thumbnails in sync. // Guard against no-op updates to prevent circular refresh cascades // between activeCompPath → compositionStack → onCompositionChange. if (compPath !== activeCompPath) { setActiveCompPath(compPath); refreshPreviewDocumentVersion(); } }} onIframeRef={handlePreviewIframeRef} previewOverlay={ captionEditMode ? ( ) : STUDIO_INSPECTOR_PANELS_ENABLED ? ( ) : null } timelineFooter={ captionEditMode ? (
Captions
) : undefined } timelineVisible={timelineVisible} onToggleTimeline={toggleTimelineVisibility} />
); }