import { type Readable, type Writable } from "svelte/store"; import type { MediaSource, MediaType } from "../iiif/mediaResolver"; import type { PluginContext } from "../core/types/plugin"; import { type MediaMarksState } from "./mediaMarks"; import type { StageFade } from "./viewer/storyViewerController"; import { type ExportEnvelope, type SaveResult, type SaveState } from "./storySerializer"; import type { AnnotationPlacement, Chapter, ChapterCameraTrack, ChapterAnnotationTool, ChapterAnnotationStrokeWidth, ChapterDrawingAnnotation, ChapterAdvance, NarrationSegment, StoryState } from "../core/types/story"; import type { ViewBox } from "../core/types/viewer"; import type { ViewerConfig } from "../core/types/config"; import type { ChapterTaskId } from "./chapterTasks"; export type StoryBuilderController = { story: Readable; currentManifest: Readable; viewerCanvasIndex: Readable; viewerCanvasCount: Readable; selectedChapterId: Writable; activeChapterTask: Writable; selectedDrawingAnnotationId: Writable; chapterAnnotationTool: Writable; uiMode: Writable; drawerOpen: Readable; viewBox: Readable; modelPoseDebug: Readable; mediaType: Readable; mediaMarks: Readable; transitionDelayDefault: Readable; avMarksValid: Readable; error: Writable; validationErrors: Readable; language: string; languages: string[]; annotationLanguage: Writable; saveState: Readable; saveConfigured: Readable; dirty: Readable; canUndo: Readable; canRedo: Readable; saveModalOpen: Readable; saveModalPayload: Readable; setSaveConfig: (config: ViewerConfig["story"] extends infer S ? S extends { save?: infer T; } ? T : Record : Record) => void; closeSaveModal: () => void; mediaSources: Readable; layerOpacities: Readable>; updateLayerOpacity: (id: string, opacity: number) => void; attach: (ctx: PluginContext) => () => void; loadStory: (storyToLoad: StoryState) => void; setAnnotationLanguage: (lang: string) => void; setChapterAnnotationTool: (tool: ChapterAnnotationTool) => void; deleteChapterDrawingAnnotation: (annotationId: string) => void; deleteChapterTextAnnotation: (lang: string) => void; editChapterDrawingAnnotation: (annotationId: string) => void; finishChapterDrawingAnnotationEdit: () => void; editChapterTextAnnotation: (lang: string) => void; setChapterDrawingAnnotationLabel: (annotationId: string, lang: string, value: string) => void; setChapterDrawingAnnotationStyle: (annotationId: string, style: { color?: string | null; strokeWidth?: ChapterAnnotationStrokeWidth; fillMode?: ChapterDrawingAnnotation["fillMode"]; /** Null clears it, so the export goes back to inferring from shape. */ motivation?: ChapterDrawingAnnotation["motivation"] | null; }) => void; addChapter: () => void; updateChapter: () => void; /** * Sets the chapter frame — the canvas region this chapter opens on — in * canvas pixels. The frame is an object on the stage: this is how a drag of * it, or a typed value, lands on the chapter. It does not move the camera. */ setChapterPosition: (viewBox: ViewBox) => void; deleteChapter: (chapterId: string) => void; duplicateChapter: (chapterId: string) => void; reorderChapter: (chapterId: string, targetChapterId: string, position?: "before" | "after") => void; selectChapter: (chapterId: string | null) => void; openNarration: () => void; backFromNarration: () => void; closeNarration: () => void; openChapter: () => void; closeChapter: () => void; loadManifestAndAddChapter: (manifest: string) => void; markIn: () => void; markOut: () => void; setMediaMarks: (start: number | null, end: number | null) => void; assignMediaSegment: (start: number, end: number) => void; previewMediaSegment: () => void; stopPreviewMediaSegment: () => void; setNarrationTrack: (lang: string, src: string) => void; updateStoryTitle: (lang: string, value: string) => void; updateStoryIdentifiers: (id: string, annotationBase: string) => void; /** * Adds a camera point. For an image chapter it starts as a frame nested * inside the previous point's (or the chapter's) frame, ready to be dragged * into place on the stage; for a 3D chapter it holds the current pose. */ addMotionPoint: () => void; /** Where a camera point's frame was moved or resized to, in canvas pixels. */ setMotionPointViewBox: (keyframeId: string, viewBox: ViewBox) => void; /** Moves a camera point's pin while preserving its framing/zoom. */ setMotionPointFocus: (keyframeId: string, focus: { x: number; y: number; }) => void; /** Selects a point without moving the live camera. */ selectMotionPoint: (keyframeId: string) => void; /** Copies the live zoom to a point while preserving its pin/focus. */ updateMotionPointFromViewport: (keyframeId: string) => void; /** The camera point whose frame carries the handles on the stage. */ selectedMotionPointId: Writable; deleteMotionPoint: (keyframeId: string) => void; updateMotionDuration: (durationMs: number) => void; updateMotionPathType: (pathType: "linear" | "spline") => void; updateMotionInitialDwell: (dwellMs: number) => void; updateMotionEasing: (easing: NonNullable) => void; goToMotionPoint: (keyframeId: string) => void; applyMotionPreset: (preset: NonNullable["preset"]) => void; motionPreviewing: Readable; motionPreviewPinsVisible: Readable; setMotionPreviewPinsVisible: (visible: boolean) => void; previewMotion: () => void; stopMotionPreview: () => void; updateChapterTitle: (lang: string, value: string) => void; updateChapterDescription: (lang: string, value: string) => void; assignNarrationSegment: (lang: string, start: number, end: number) => void; skipNarration: (lang: string) => void; updateAnnotationText: (lang: string, text: string) => void; updateAnnotationPlacement: (lang: string, placement: AnnotationPlacement) => void; updateAdvanceMode: (mode: ChapterAdvance["mode"]) => void; updateDelay: (delayMs?: number) => void; updateManifest: (manifest: string) => void; reloadManifest: (manifest: string, canvasIndex: number) => void; selectCanvas: (canvasIndex: number) => void; loadManifest: (manifest: string) => void; saveChapterSettings: () => void; cancelChapterSettings: () => void; /** * Re-reads the selected chapter from the viewer after the Source section * moved it to another Manifest or Canvas, so the chapter stores the canvas * it is now showing rather than the one it was created on. */ applyChapterSource: () => void; saveExport: () => { ok: boolean; errors: string[]; }; exportStory: () => { ok: boolean; errors: string[]; }; /** A detached snapshot of the builder's editable story state. */ getStory: () => StoryState; /** The current story serialized as a portable IIIF AnnotationPage. */ getExportPayload: () => ExportEnvelope; saveStory: () => Promise; undo: () => void; redo: () => void; isPreviewing: Readable; /** Stage opacity while a chapter change swaps the Manifest or Canvas. */ stageFade: Readable; startPreview: () => void; stopPreview: () => void; previewChapter: (chapterId?: string) => void; positioningLanguage: Readable; startAnnotationPositioning: (lang: string) => void; confirmAnnotationPositioning: () => void; cancelAnnotationPositioning: () => void; }; export type UIMode = "idle" | "chapterEdit" | "narrationPanel" | "annotationPositioning"; export type StoryBuilderOptions = { language?: string; languages?: string[]; annotationPageId?: string; annotationBase?: string; identifiersLocked?: boolean; initialStory?: StoryState; /** Receives the controller used by the first-party builder plugins. */ onControllerReady?: (controller: StoryBuilderController) => void; }; export declare const collectLatestNarrationSegments: (story: StoryState) => Record; export declare const createStoryBuilderController: (options?: StoryBuilderOptions) => StoryBuilderController;