@plasius/video 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface VideoPackageInfo {\n name: \"@plasius/video\";\n version: string;\n}\n\nexport const videoPackageInfo: VideoPackageInfo = {\n name: \"@plasius/video\",\n version: \"0.1.1\",\n};\n"],"mappings":";AAKO,IAAM,mBAAqC;AAAA,EAChD,MAAM;AAAA,EACN,SAAS;AACX;","names":[]}
1
+ {"version":3,"sources":["../src/ai-video-generation/tokens.ts","../src/ai-video-generation/stages.ts","../src/ai-video-generation/demo-model.ts","../src/ai-video-generation/screen.tsx","../src/ai-video-generation/demo.tsx","../src/index.ts"],"sourcesContent":["export const aiVideoGenerationTokens = {\n color: {\n background: \"#0F1117\",\n surface: \"#161A23\",\n accentPrimary: \"#6C5CE7\",\n accentSecondary: \"#00D4FF\",\n success: \"#00C896\",\n warning: \"#FFB020\",\n error: \"#FF4D4F\",\n textPrimary: \"#E6EAF2\",\n textSecondary: \"#A0A8B8\",\n borderSubtle: \"rgba(255,255,255,0.05)\",\n placeholderText: \"rgba(255,255,255,0.35)\",\n },\n typography: {\n headingFontFamily: \"Inter, 'SF Pro Display', sans-serif\",\n bodyFontFamily: \"Inter, sans-serif\",\n h1Px: 28,\n h2Px: 20,\n bodyPx: 16,\n smallPx: 13,\n promptPxMin: 16,\n promptPxMax: 18,\n },\n layout: {\n headerHeightPx: 64,\n promptBarMinHeightPx: 140,\n gridGapPx: 16,\n cardAspectRatio: \"16 / 9\",\n },\n radius: {\n promptPx: 12,\n cardPx: 14,\n panelPx: 14,\n },\n spacing: {\n xxsPx: 4,\n xsPx: 8,\n smPx: 12,\n mdPx: 16,\n lgPx: 20,\n xlPx: 24,\n },\n animation: {\n fastMs: 200,\n standardMs: 280,\n slowMs: 300,\n easing: \"cubic-bezier(0.4, 0.0, 0.2, 1)\",\n },\n} as const;\n\nexport type AIVideoGenerationTokens = typeof aiVideoGenerationTokens;\n","import type { AIVideoGenerationStage } from \"./types.js\";\n\nexport interface AIVideoStageSummary {\n stage: AIVideoGenerationStage;\n label: string;\n mainUI: string;\n description: string;\n}\n\nexport const aiVideoStageFlow: readonly AIVideoStageSummary[] = [\n {\n stage: \"idle\",\n label: \"Idle\",\n mainUI: \"Prompt input\",\n description: \"Base prompt entry with optional image upload and advanced settings.\",\n },\n {\n stage: \"generatingImages\",\n label: \"Generating Images\",\n mainUI: \"Skeleton grid\",\n description: \"Asynchronous generation feedback with shimmer placeholders.\",\n },\n {\n stage: \"imageSelection\",\n label: \"Image Selection\",\n mainUI: \"Image grid\",\n description: \"Select, refine, save, and mark an image as the video source.\",\n },\n {\n stage: \"generatingVideo\",\n label: \"Generating Video\",\n mainUI: \"Image + progress\",\n description: \"Motion extraction and generation progress with live feedback.\",\n },\n {\n stage: \"playback\",\n label: \"Playback\",\n mainUI: \"Video player\",\n description: \"Playback controls, download, regenerate, and voiceover entry point.\",\n },\n {\n stage: \"voiceover\",\n label: \"Voiceover\",\n mainUI: \"Bottom voice panel\",\n description: \"Editable script, voice presets, speed/emotion controls, waveform preview.\",\n },\n {\n stage: \"export\",\n label: \"Export\",\n mainUI: \"Export modal\",\n description: \"Final artifact export options with quality and format metadata.\",\n },\n] as const;\n","import type {\n AIVideoGenerationScreenModel,\n AIVideoGenerationStage,\n AIVideoImageVariant,\n} from \"./types.js\";\n\nconst basePrompt = \"Mountain village at sunset\";\nconst refinement = \"Add fog rolling through the valley\";\n\nconst baseVariants: AIVideoImageVariant[] = [\n { id: \"img-1\", label: \"Variant 1\", alt: \"Village view with warm skyline\" },\n { id: \"img-2\", label: \"Variant 2\", alt: \"Village rooftops and distant mountains\" },\n { id: \"img-3\", label: \"Variant 3\", alt: \"Bridge over misted valley\" },\n { id: \"img-4\", label: \"Variant 4\", alt: \"Forest edge overlooking village lights\" },\n { id: \"img-5\", label: \"Variant 5\", alt: \"Cloud bank drifting above the town\" },\n { id: \"img-6\", label: \"Variant 6\", alt: \"Cinematic wide frame across the valley\" },\n];\n\nconst stageStatusText: Record<AIVideoGenerationStage, string> = {\n idle: \"Ready to generate image directions.\",\n generatingImages: \"Generating course-setting image variants...\",\n imageSelection: \"Choose a visual anchor for motion extraction.\",\n generatingVideo: \"Generating video from selected course image...\",\n playback: \"Video ready for review.\",\n voiceover: \"Voiceover tools ready.\",\n export: \"Review export profile and metadata.\",\n};\n\nfunction withSelectedVariant(\n variants: AIVideoImageVariant[],\n selectedId: string,\n): AIVideoImageVariant[] {\n return variants.map((variant) => ({\n ...variant,\n isSelected: variant.id === selectedId,\n }));\n}\n\nexport function createAIVideoGenerationDemoModel(\n stage: AIVideoGenerationStage = \"idle\",\n): AIVideoGenerationScreenModel {\n const selectedId = \"img-3\";\n const selectedVariants = withSelectedVariant(baseVariants, selectedId);\n\n const model: AIVideoGenerationScreenModel = {\n stage,\n projectName: \"Mountain Valley Storyboard\",\n prompt: basePrompt,\n promptPlaceholder:\n \"Describe your scene, camera movement, mood, and intended spoken narration...\",\n canGenerate: stage !== \"generatingImages\" && stage !== \"generatingVideo\",\n statusText: stageStatusText[stage],\n generationProgress: stage === \"generatingVideo\" ? 62 : 100,\n imageVariants:\n stage === \"idle\" ? [] : stage === \"generatingImages\" ? baseVariants.slice(0, 8) : selectedVariants,\n selectedImageId:\n stage === \"imageSelection\" ||\n stage === \"generatingVideo\" ||\n stage === \"playback\" ||\n stage === \"voiceover\" ||\n stage === \"export\"\n ? selectedId\n : undefined,\n promptVersions: [\n {\n id: \"v1\",\n label: \"Version 1\",\n basePrompt,\n },\n {\n id: \"v2\",\n label: \"Version 2\",\n basePrompt,\n refinement,\n },\n {\n id: \"v3\",\n label: \"Version 3\",\n basePrompt,\n refinement: `${refinement}; camera starts low and pans left.`,\n isActive: true,\n },\n ],\n motionDraft: {\n cameraMotion: \"Camera slowly pans left, then settles into a medium-wide frame.\",\n environmentalMotion: \"Fog layers move through the valley while lantern light flickers.\",\n subjectMotion: \"Foreground flags sway and distant birds cross near the skyline.\",\n },\n motionPrompt: \"Camera slowly pans left with drifting fog and gentle ambient motion.\",\n voiceSettings: {\n script: \"Welcome to the ancient valley. Each light tells a story waiting to be explored.\",\n voiceId: \"narrator-documentary\",\n speed: 1,\n emotion: \"Neutral\",\n },\n voicePresets: [\n { id: \"male-warm\", label: \"Male Warm\" },\n { id: \"female-calm\", label: \"Female Calm\" },\n { id: \"narrator-documentary\", label: \"Narrator Documentary\" },\n ],\n videoSource:\n stage === \"playback\" || stage === \"voiceover\" || stage === \"export\"\n ? \"https://example.invalid/plasius/video/demo.mp4\"\n : undefined,\n };\n\n if (stage === \"idle\") {\n model.uploadedImageName = \"uploaded-village-frame.png\";\n model.motionPrompt = \"\";\n model.canGenerate = false;\n model.statusText = \"Upload Image: complete. Add motion instructions (required).\";\n }\n\n return model;\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { aiVideoStageFlow } from \"./stages.js\";\nimport { aiVideoGenerationTokens } from \"./tokens.js\";\nimport type { AIVideoGenerationScreenModel, AIVideoImageVariant, AIVideoGenerationStage } from \"./types.js\";\n\nconst stageLabel: Record<AIVideoGenerationStage, string> = {\n idle: \"Prompt\",\n generatingImages: \"Images\",\n imageSelection: \"Selection\",\n generatingVideo: \"Video\",\n playback: \"Playback\",\n voiceover: \"Voiceover\",\n export: \"Export\",\n};\n\nfunction clampProgress(value: number | undefined): number {\n if (typeof value !== \"number\" || Number.isNaN(value)) {\n return 0;\n }\n\n if (value < 0) {\n return 0;\n }\n\n if (value > 100) {\n return 100;\n }\n\n return Math.round(value);\n}\n\nfunction gradientForCard(index: number): string {\n const gradients = [\n \"linear-gradient(140deg, #20305a 0%, #6c5ce7 45%, #00d4ff 100%)\",\n \"linear-gradient(140deg, #2b1f3f 0%, #6c5ce7 48%, #3dd9f5 100%)\",\n \"linear-gradient(140deg, #283645 0%, #4f89c2 46%, #9be3ff 100%)\",\n \"linear-gradient(140deg, #2f2921 0%, #8a5f3a 48%, #ffd39f 100%)\",\n ];\n\n return gradients[index % gradients.length];\n}\n\nexport interface AIVideoGenerationScreenCallbacks {\n onHistory?: () => void;\n onSettings?: () => void;\n onExport?: () => void;\n onAccount?: () => void;\n onGenerate?: () => void;\n onUploadImage?: () => void;\n onAdvanced?: () => void;\n onSelectImage?: (variant: AIVideoImageVariant) => void;\n onRefineImage?: (variant: AIVideoImageVariant) => void;\n onSaveImage?: (variant: AIVideoImageVariant) => void;\n onUseForVideo?: (variant: AIVideoImageVariant) => void;\n onAddVoiceover?: () => void;\n onRegenerateVideo?: () => void;\n onDownloadVideo?: () => void;\n}\n\nexport interface AIVideoGenerationScreenProps extends AIVideoGenerationScreenCallbacks {\n model: AIVideoGenerationScreenModel;\n className?: string;\n style?: CSSProperties;\n showContextPanel?: boolean;\n reduceMotion?: boolean;\n}\n\nfunction renderImageCard(\n variant: AIVideoImageVariant,\n index: number,\n callbacks: AIVideoGenerationScreenCallbacks,\n): ReactNode {\n const isSelected = Boolean(variant.isSelected);\n\n return (\n <article\n className={`plv-image-card${isSelected ? \" is-selected\" : \"\"}`}\n key={variant.id}\n aria-label={variant.alt ?? variant.label}\n >\n <button\n type=\"button\"\n className=\"plv-image-select-hitbox\"\n aria-pressed={isSelected}\n onClick={() => callbacks.onSelectImage?.(variant)}\n >\n {variant.src ? (\n <img src={variant.src} alt={variant.alt ?? variant.label} className=\"plv-image-media\" />\n ) : (\n <div className=\"plv-image-media\" style={{ background: gradientForCard(index) }} />\n )}\n <div className=\"plv-image-caption\">\n <span>{variant.label}</span>\n {isSelected ? <span className=\"plv-chip\">Selected</span> : null}\n </div>\n </button>\n\n <div className=\"plv-image-overlay-controls\" role=\"group\" aria-label={`${variant.label} controls`}>\n <button type=\"button\" onClick={() => callbacks.onRefineImage?.(variant)}>\n Refine\n </button>\n <button type=\"button\" onClick={() => callbacks.onSaveImage?.(variant)}>\n Save\n </button>\n <button type=\"button\" onClick={() => callbacks.onUseForVideo?.(variant)}>\n Use for Video\n </button>\n </div>\n\n {isSelected ? (\n <span className=\"plv-selected-checkmark\" aria-hidden=\"true\">\n ✓\n </span>\n ) : null}\n </article>\n );\n}\n\nfunction renderSkeletonGrid(count: number): ReactNode {\n const items = Array.from({ length: count }).map((_, index) => (\n <div className=\"plv-skeleton-card\" key={`skeleton-${index}`} />\n ));\n\n return <div className=\"plv-image-grid\">{items}</div>;\n}\n\nfunction renderStageCanvas(\n model: AIVideoGenerationScreenModel,\n callbacks: AIVideoGenerationScreenCallbacks,\n): ReactNode {\n const progress = clampProgress(model.generationProgress);\n\n if (model.stage === \"generatingImages\") {\n return (\n <>\n <h2>Generating Image Variants</h2>\n <p className=\"plv-muted\">{model.statusText}</p>\n {renderSkeletonGrid(model.imageVariants.length > 0 ? model.imageVariants.length : 8)}\n </>\n );\n }\n\n if (model.stage === \"imageSelection\") {\n return (\n <>\n <h2>Course Setting Image Grid</h2>\n <p className=\"plv-muted\">Select a visual anchor before video generation.</p>\n <div className=\"plv-image-grid\">\n {model.imageVariants.map((variant, index) => renderImageCard(variant, index, callbacks))}\n </div>\n </>\n );\n }\n\n if (model.stage === \"generatingVideo\") {\n return (\n <>\n <h2>Video Generation Phase</h2>\n <div className=\"plv-split-panel\">\n <div className=\"plv-preview-box\">\n <div className=\"plv-preview-title\">Image Preview</div>\n <div className=\"plv-preview-media\" />\n </div>\n <div className=\"plv-motion-panel\">\n <div className=\"plv-preview-title\">Motion Summary</div>\n <label>\n Camera motion\n <textarea readOnly value={model.motionDraft.cameraMotion} />\n </label>\n <label>\n Environmental motion\n <textarea readOnly value={model.motionDraft.environmentalMotion} />\n </label>\n <label>\n Subject motion\n <textarea readOnly value={model.motionDraft.subjectMotion} />\n </label>\n </div>\n </div>\n <div className=\"plv-progress-panel\">\n <div className=\"plv-progress-topline\">\n <span>Generating Video...</span>\n <span>{progress}%</span>\n </div>\n <div className=\"plv-progress-track\" role=\"progressbar\" aria-valuemin={0} aria-valuemax={100} aria-valuenow={progress}>\n <div className=\"plv-progress-fill\" style={{ width: `${progress}%` }} />\n </div>\n <div className=\"plv-waveform\" aria-hidden=\"true\" />\n </div>\n </>\n );\n }\n\n if (model.stage === \"playback\" || model.stage === \"voiceover\" || model.stage === \"export\") {\n return (\n <>\n <h2>Video Playback</h2>\n <div className=\"plv-player-shell\">\n <div className=\"plv-player-frame\">\n <div className=\"plv-player-glow\" />\n <div className=\"plv-player-screen\">16:9 Preview Frame</div>\n </div>\n <div className=\"plv-player-controls\">\n <button type=\"button\">Play / Pause</button>\n <button type=\"button\">Timeline</button>\n <button type=\"button\">Volume</button>\n <button type=\"button\" onClick={callbacks.onDownloadVideo}>\n Download\n </button>\n <button type=\"button\" onClick={callbacks.onRegenerateVideo}>\n Regenerate\n </button>\n <button type=\"button\" onClick={callbacks.onAddVoiceover}>\n Add Voiceover\n </button>\n </div>\n </div>\n\n {model.stage === \"voiceover\" ? (\n <section className=\"plv-voiceover-panel\" aria-label=\"Voiceover panel\">\n <div className=\"plv-preview-title\">Extracted Speech</div>\n <textarea readOnly value={model.voiceSettings.script} />\n <div className=\"plv-voice-grid\">\n <div>\n <div className=\"plv-field-label\">Voice</div>\n <div className=\"plv-pill-group\">\n {model.voicePresets.map((voice) => (\n <button\n type=\"button\"\n key={voice.id}\n className={voice.id === model.voiceSettings.voiceId ? \"is-active\" : undefined}\n >\n {voice.label}\n </button>\n ))}\n </div>\n </div>\n <div>\n <div className=\"plv-field-label\">Speed: {model.voiceSettings.speed.toFixed(1)}x</div>\n <div className=\"plv-slider-track\" />\n </div>\n <div>\n <div className=\"plv-field-label\">Emotion: {model.voiceSettings.emotion}</div>\n <div className=\"plv-slider-track\" />\n </div>\n </div>\n <div className=\"plv-waveform is-voiceover\" aria-hidden=\"true\" />\n </section>\n ) : null}\n\n {model.stage === \"export\" ? (\n <div className=\"plv-export-modal\" role=\"dialog\" aria-label=\"Export modal\">\n <h3>Export</h3>\n <p>Finalize codec, quality, and voice mixdown profile.</p>\n <button type=\"button\" onClick={callbacks.onExport}>\n Confirm Export\n </button>\n </div>\n ) : null}\n </>\n );\n }\n\n return (\n <>\n <h2>Prompt Entry</h2>\n <p className=\"plv-muted\">Start with a cinematic prompt, then generate course-setting images.</p>\n <div className=\"plv-idle-canvas\">\n {model.uploadedImageName ? (\n <>\n <div className=\"plv-upload-chip\">Upload Image: {model.uploadedImageName}</div>\n <div className=\"plv-required-chip\">Add Motion Instructions (Required)</div>\n </>\n ) : (\n <div className=\"plv-upload-chip\">Upload an image or write a prompt to begin.</div>\n )}\n </div>\n </>\n );\n}\n\nexport function AIVideoGenerationScreen({\n model,\n className,\n style,\n showContextPanel = true,\n reduceMotion = false,\n ...callbacks\n}: AIVideoGenerationScreenProps) {\n const rootClassName = [\n \"plv-video-screen\",\n reduceMotion ? \"plv-reduce-motion\" : \"\",\n className ?? \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n const requiresMotionPrompt = Boolean(model.uploadedImageName) && !model.motionPrompt?.trim();\n\n return (\n <section className={rootClassName} style={style}>\n <style>{AI_VIDEO_GENERATION_SCREEN_STYLES}</style>\n\n <header className=\"plv-header\">\n <div className=\"plv-logo\">PLASIUS</div>\n <div className=\"plv-project-title\">{model.projectName}</div>\n <div className=\"plv-header-actions\">\n <button type=\"button\" onClick={callbacks.onHistory}>\n History\n </button>\n <button type=\"button\" onClick={callbacks.onSettings}>\n Settings\n </button>\n <button type=\"button\" onClick={callbacks.onExport}>\n Export\n </button>\n <button type=\"button\" onClick={callbacks.onAccount}>\n Account\n </button>\n </div>\n </header>\n\n <main className=\"plv-main-canvas\">{renderStageCanvas(model, callbacks)}</main>\n\n {showContextPanel ? (\n <aside className=\"plv-context-panel\">\n <div className=\"plv-context-title\">Context Panel</div>\n <div className=\"plv-chip-row\" role=\"list\" aria-label=\"Prompt versions\">\n {model.promptVersions.map((version) => (\n <button\n type=\"button\"\n key={version.id}\n role=\"listitem\"\n className={version.isActive ? \"is-active\" : undefined}\n >\n {version.label}\n </button>\n ))}\n </div>\n <div className=\"plv-metadata-grid\">\n <div>\n <span>Stage</span>\n <strong>{stageLabel[model.stage]}</strong>\n </div>\n <div>\n <span>Status</span>\n <strong>{model.statusText}</strong>\n </div>\n <div>\n <span>Prompt</span>\n <strong>{model.prompt}</strong>\n </div>\n </div>\n <div className=\"plv-stage-row\">\n {aiVideoStageFlow.map((stage) => (\n <span key={stage.stage} className={stage.stage === model.stage ? \"is-active\" : undefined}>\n {stage.label}\n </span>\n ))}\n </div>\n </aside>\n ) : null}\n\n <footer className=\"plv-prompt-area\">\n <label className=\"plv-sr-only\" htmlFor=\"plv-prompt-textarea\">\n Prompt input\n </label>\n <textarea\n id=\"plv-prompt-textarea\"\n value={model.prompt}\n readOnly\n placeholder={model.promptPlaceholder}\n aria-label=\"Prompt input\"\n />\n\n <div className=\"plv-prompt-actions\">\n <button type=\"button\" onClick={callbacks.onUploadImage}>\n Upload Image\n </button>\n <button type=\"button\" onClick={callbacks.onAdvanced}>\n Advanced\n </button>\n <button type=\"button\" className=\"is-generate\" disabled={!model.canGenerate} onClick={callbacks.onGenerate}>\n Generate\n </button>\n </div>\n\n {requiresMotionPrompt ? (\n <div className=\"plv-required-chip\">Upload Image complete. Motion prompt is required before generating.</div>\n ) : null}\n </footer>\n </section>\n );\n}\n\nexport const AI_VIDEO_GENERATION_SCREEN_STYLES = `\n.plv-video-screen {\n --plv-background: ${aiVideoGenerationTokens.color.background};\n --plv-surface: ${aiVideoGenerationTokens.color.surface};\n --plv-border: ${aiVideoGenerationTokens.color.borderSubtle};\n --plv-text: ${aiVideoGenerationTokens.color.textPrimary};\n --plv-text-muted: ${aiVideoGenerationTokens.color.textSecondary};\n --plv-accent-primary: ${aiVideoGenerationTokens.color.accentPrimary};\n --plv-accent-secondary: ${aiVideoGenerationTokens.color.accentSecondary};\n --plv-success: ${aiVideoGenerationTokens.color.success};\n --plv-warning: ${aiVideoGenerationTokens.color.warning};\n --plv-error: ${aiVideoGenerationTokens.color.error};\n --plv-prompt-placeholder: ${aiVideoGenerationTokens.color.placeholderText};\n --plv-header-height: ${aiVideoGenerationTokens.layout.headerHeightPx}px;\n --plv-transition: ${aiVideoGenerationTokens.animation.standardMs}ms ${aiVideoGenerationTokens.animation.easing};\n font-family: ${aiVideoGenerationTokens.typography.bodyFontFamily};\n color: var(--plv-text);\n background:\n radial-gradient(1200px 520px at 20% -10%, rgba(108, 92, 231, 0.22), transparent 62%),\n radial-gradient(1000px 540px at 80% -20%, rgba(0, 212, 255, 0.16), transparent 60%),\n var(--plv-background);\n border-radius: ${aiVideoGenerationTokens.radius.panelPx}px;\n border: 1px solid var(--plv-border);\n overflow: hidden;\n display: grid;\n grid-template-rows: var(--plv-header-height) minmax(360px, 1fr) auto auto;\n min-height: 820px;\n}\n\n.plv-header {\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 0 16px;\n border-bottom: 1px solid var(--plv-border);\n background: #0f1117;\n}\n\n.plv-logo {\n font-weight: 800;\n letter-spacing: 0.08em;\n}\n\n.plv-project-title {\n font-size: 15px;\n color: var(--plv-text-muted);\n}\n\n.plv-header-actions {\n margin-left: auto;\n display: flex;\n gap: 8px;\n}\n\n.plv-header-actions button,\n.plv-player-controls button,\n.plv-prompt-actions button,\n.plv-chip-row button,\n.plv-pill-group button,\n.plv-image-overlay-controls button {\n border: 1px solid var(--plv-border);\n background: rgba(255, 255, 255, 0.02);\n color: var(--plv-text);\n border-radius: 10px;\n padding: 8px 12px;\n font-size: 13px;\n transition: all var(--plv-transition);\n}\n\n.plv-header-actions button:hover,\n.plv-player-controls button:hover,\n.plv-prompt-actions button:hover,\n.plv-chip-row button:hover,\n.plv-pill-group button:hover,\n.plv-image-overlay-controls button:hover {\n border-color: rgba(0, 212, 255, 0.45);\n box-shadow: 0 0 0 1px rgba(0, 212, 255, 0.22);\n}\n\n.plv-main-canvas {\n padding: 18px;\n}\n\n.plv-main-canvas h2 {\n margin: 0 0 8px;\n font-family: ${aiVideoGenerationTokens.typography.headingFontFamily};\n font-size: ${aiVideoGenerationTokens.typography.h2Px}px;\n}\n\n.plv-muted {\n margin: 0 0 14px;\n color: var(--plv-text-muted);\n font-size: ${aiVideoGenerationTokens.typography.smallPx}px;\n}\n\n.plv-image-grid {\n display: grid;\n gap: ${aiVideoGenerationTokens.layout.gridGapPx}px;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n}\n\n.plv-image-card,\n.plv-skeleton-card {\n aspect-ratio: ${aiVideoGenerationTokens.layout.cardAspectRatio};\n border-radius: ${aiVideoGenerationTokens.radius.cardPx}px;\n position: relative;\n overflow: hidden;\n}\n\n.plv-image-card {\n border: 1px solid var(--plv-border);\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);\n transition: transform var(--plv-transition), box-shadow var(--plv-transition), border-color var(--plv-transition);\n}\n\n.plv-image-card:hover {\n transform: scale(1.02);\n border-color: rgba(0, 212, 255, 0.55);\n box-shadow: 0 14px 36px rgba(0, 0, 0, 0.48);\n}\n\n.plv-image-card.is-selected {\n border: 2px solid var(--plv-accent-secondary);\n box-shadow: 0 0 0 1px rgba(108, 92, 231, 0.35), 0 16px 32px rgba(0, 0, 0, 0.55);\n}\n\n.plv-image-select-hitbox {\n border: 0;\n margin: 0;\n width: 100%;\n height: 100%;\n padding: 0;\n background: none;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n cursor: pointer;\n}\n\n.plv-image-media {\n position: absolute;\n inset: 0;\n}\n\n.plv-image-caption {\n z-index: 1;\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 8px;\n padding: 10px;\n background: linear-gradient(180deg, transparent 0%, rgba(15, 17, 23, 0.84) 60%);\n}\n\n.plv-chip {\n font-size: 11px;\n border-radius: 999px;\n padding: 2px 8px;\n background: rgba(0, 212, 255, 0.14);\n border: 1px solid rgba(0, 212, 255, 0.36);\n}\n\n.plv-selected-checkmark {\n position: absolute;\n top: 10px;\n right: 10px;\n width: 24px;\n height: 24px;\n display: grid;\n place-items: center;\n border-radius: 999px;\n color: #00121a;\n background: #7ff3ff;\n font-weight: 900;\n}\n\n.plv-image-overlay-controls {\n position: absolute;\n top: 10px;\n left: 10px;\n display: flex;\n gap: 8px;\n opacity: 0;\n transform: translateY(-6px);\n transition: opacity var(--plv-transition), transform var(--plv-transition);\n}\n\n.plv-image-card:hover .plv-image-overlay-controls {\n opacity: 1;\n transform: translateY(0);\n}\n\n.plv-skeleton-card {\n background: linear-gradient(\n 100deg,\n rgba(255, 255, 255, 0.03) 20%,\n rgba(255, 255, 255, 0.14) 40%,\n rgba(255, 255, 255, 0.03) 60%\n );\n background-size: 200% 100%;\n animation: plv-shimmer 1.25s linear infinite;\n}\n\n.plv-split-panel {\n display: grid;\n grid-template-columns: 1.1fr 0.9fr;\n gap: 16px;\n}\n\n.plv-preview-box,\n.plv-motion-panel,\n.plv-progress-panel,\n.plv-player-shell,\n.plv-voiceover-panel,\n.plv-idle-canvas,\n.plv-context-panel,\n.plv-prompt-area {\n background: var(--plv-surface);\n border: 1px solid var(--plv-border);\n border-radius: ${aiVideoGenerationTokens.radius.panelPx}px;\n}\n\n.plv-preview-box,\n.plv-motion-panel {\n padding: 14px;\n}\n\n.plv-preview-title {\n font-size: ${aiVideoGenerationTokens.typography.smallPx}px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--plv-text-muted);\n margin-bottom: 10px;\n}\n\n.plv-preview-media {\n width: 100%;\n aspect-ratio: ${aiVideoGenerationTokens.layout.cardAspectRatio};\n border-radius: ${aiVideoGenerationTokens.radius.cardPx}px;\n background: linear-gradient(135deg, #2d3e67 0%, #6c5ce7 45%, #00d4ff 100%);\n}\n\n.plv-motion-panel label {\n display: block;\n font-size: ${aiVideoGenerationTokens.typography.smallPx}px;\n color: var(--plv-text-muted);\n margin-bottom: 10px;\n}\n\n.plv-motion-panel textarea,\n.plv-voiceover-panel textarea {\n width: 100%;\n margin-top: 6px;\n border: 1px solid var(--plv-border);\n border-radius: 10px;\n min-height: 62px;\n resize: none;\n background: rgba(255, 255, 255, 0.02);\n color: var(--plv-text);\n padding: 10px;\n font-family: ${aiVideoGenerationTokens.typography.bodyFontFamily};\n}\n\n.plv-progress-panel {\n margin-top: 16px;\n padding: 12px 14px;\n}\n\n.plv-progress-topline {\n display: flex;\n justify-content: space-between;\n font-size: ${aiVideoGenerationTokens.typography.smallPx}px;\n margin-bottom: 8px;\n}\n\n.plv-progress-track {\n height: 8px;\n border-radius: 999px;\n background: rgba(255, 255, 255, 0.08);\n overflow: hidden;\n}\n\n.plv-progress-fill {\n height: 100%;\n background: linear-gradient(135deg, var(--plv-accent-primary), var(--plv-accent-secondary));\n transition: width var(--plv-transition);\n}\n\n.plv-waveform {\n margin-top: 10px;\n height: 32px;\n border-radius: 10px;\n background:\n repeating-linear-gradient(\n 90deg,\n rgba(108, 92, 231, 0.24) 0,\n rgba(108, 92, 231, 0.24) 4px,\n rgba(0, 212, 255, 0.28) 4px,\n rgba(0, 212, 255, 0.28) 8px\n );\n animation: plv-wave 1.2s linear infinite;\n}\n\n.plv-waveform.is-voiceover {\n height: 46px;\n}\n\n.plv-player-shell {\n padding: 14px;\n}\n\n.plv-player-frame {\n position: relative;\n aspect-ratio: ${aiVideoGenerationTokens.layout.cardAspectRatio};\n background: #020202;\n border-radius: ${aiVideoGenerationTokens.radius.cardPx}px;\n overflow: hidden;\n}\n\n.plv-player-glow {\n position: absolute;\n inset: -20%;\n background: radial-gradient(circle at center, rgba(0, 212, 255, 0.26), transparent 60%);\n}\n\n.plv-player-screen {\n position: absolute;\n inset: 0;\n display: grid;\n place-items: center;\n color: rgba(230, 234, 242, 0.74);\n font-size: 15px;\n}\n\n.plv-player-controls {\n margin-top: 12px;\n display: grid;\n grid-template-columns: repeat(6, minmax(0, 1fr));\n gap: 8px;\n}\n\n.plv-voiceover-panel {\n margin-top: 14px;\n padding: 14px;\n animation: plv-slide-up var(--plv-transition);\n}\n\n.plv-voice-grid {\n margin-top: 10px;\n display: grid;\n gap: 10px;\n}\n\n.plv-pill-group {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.plv-pill-group .is-active,\n.plv-chip-row .is-active {\n border-color: rgba(0, 212, 255, 0.6);\n box-shadow: 0 0 0 1px rgba(0, 212, 255, 0.24);\n}\n\n.plv-field-label {\n font-size: ${aiVideoGenerationTokens.typography.smallPx}px;\n color: var(--plv-text-muted);\n margin-bottom: 6px;\n}\n\n.plv-slider-track {\n height: 8px;\n border-radius: 999px;\n background: linear-gradient(135deg, rgba(108, 92, 231, 0.7), rgba(0, 212, 255, 0.7));\n}\n\n.plv-export-modal {\n margin-top: 14px;\n padding: 14px;\n border-radius: ${aiVideoGenerationTokens.radius.panelPx}px;\n border: 1px solid rgba(255, 176, 32, 0.4);\n background: rgba(255, 176, 32, 0.08);\n}\n\n.plv-export-modal h3 {\n margin: 0 0 6px;\n font-size: 18px;\n}\n\n.plv-export-modal p {\n margin: 0 0 10px;\n color: var(--plv-text-muted);\n font-size: ${aiVideoGenerationTokens.typography.smallPx}px;\n}\n\n.plv-export-modal button {\n border: 0;\n border-radius: 10px;\n background: linear-gradient(135deg, #ffb020, #ffd386);\n color: #161a23;\n font-weight: 700;\n padding: 8px 12px;\n}\n\n.plv-idle-canvas {\n min-height: 180px;\n display: grid;\n place-items: center;\n gap: 10px;\n padding: 16px;\n}\n\n.plv-upload-chip,\n.plv-required-chip {\n border-radius: 999px;\n padding: 8px 12px;\n font-size: ${aiVideoGenerationTokens.typography.smallPx}px;\n}\n\n.plv-upload-chip {\n background: rgba(255, 255, 255, 0.04);\n border: 1px solid var(--plv-border);\n}\n\n.plv-required-chip {\n background: rgba(255, 176, 32, 0.12);\n border: 1px solid rgba(255, 176, 32, 0.4);\n color: #ffd18a;\n}\n\n.plv-context-panel {\n margin: 0 18px 16px;\n padding: 14px;\n}\n\n.plv-context-title {\n margin-bottom: 10px;\n font-size: ${aiVideoGenerationTokens.typography.smallPx}px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--plv-text-muted);\n}\n\n.plv-chip-row {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.plv-metadata-grid {\n margin-top: 12px;\n display: grid;\n gap: 8px;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n\n.plv-metadata-grid div {\n display: grid;\n gap: 4px;\n}\n\n.plv-metadata-grid span {\n font-size: ${aiVideoGenerationTokens.typography.smallPx}px;\n color: var(--plv-text-muted);\n}\n\n.plv-metadata-grid strong {\n font-size: 14px;\n line-height: 1.35;\n}\n\n.plv-stage-row {\n margin-top: 10px;\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n\n.plv-stage-row span {\n border-radius: 999px;\n padding: 5px 10px;\n border: 1px solid var(--plv-border);\n color: var(--plv-text-muted);\n font-size: 12px;\n}\n\n.plv-stage-row .is-active {\n color: var(--plv-text);\n border-color: rgba(0, 212, 255, 0.55);\n}\n\n.plv-prompt-area {\n margin: 0 18px 18px;\n padding: 14px;\n}\n\n.plv-prompt-area textarea {\n width: 100%;\n min-height: ${aiVideoGenerationTokens.layout.promptBarMinHeightPx}px;\n border: 1px solid var(--plv-border);\n border-radius: ${aiVideoGenerationTokens.radius.promptPx}px;\n background: rgba(255, 255, 255, 0.02);\n color: var(--plv-text);\n font-family: ${aiVideoGenerationTokens.typography.bodyFontFamily};\n font-size: 17px;\n line-height: 1.45;\n padding: 12px;\n resize: vertical;\n}\n\n.plv-prompt-area textarea::placeholder {\n color: var(--plv-prompt-placeholder);\n}\n\n.plv-prompt-actions {\n margin-top: 10px;\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.plv-prompt-actions .is-generate {\n margin-left: auto;\n border: 0;\n background: linear-gradient(135deg, #6c5ce7, #00d4ff);\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), 0 12px 28px rgba(0, 212, 255, 0.22);\n}\n\n.plv-prompt-actions .is-generate:hover {\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), 0 14px 34px rgba(0, 212, 255, 0.34);\n}\n\n.plv-prompt-actions .is-generate:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.plv-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n\n.plv-reduce-motion * {\n animation: none !important;\n transition: none !important;\n}\n\n@media (max-width: 1024px) {\n .plv-video-screen {\n min-height: 920px;\n }\n\n .plv-split-panel {\n grid-template-columns: 1fr;\n }\n\n .plv-player-controls {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n .plv-metadata-grid {\n grid-template-columns: 1fr;\n }\n}\n\n@media (max-width: 720px) {\n .plv-header {\n flex-wrap: wrap;\n height: auto;\n min-height: var(--plv-header-height);\n padding-top: 10px;\n padding-bottom: 10px;\n }\n\n .plv-header-actions {\n width: 100%;\n justify-content: space-between;\n }\n\n .plv-image-grid {\n grid-template-columns: 1fr;\n }\n\n .plv-prompt-actions {\n flex-wrap: wrap;\n }\n\n .plv-prompt-actions .is-generate {\n margin-left: 0;\n width: 100%;\n }\n}\n\n@keyframes plv-shimmer {\n from {\n background-position: 120% 0;\n }\n to {\n background-position: -120% 0;\n }\n}\n\n@keyframes plv-wave {\n from {\n background-position: 0 0;\n }\n to {\n background-position: 64px 0;\n }\n}\n\n@keyframes plv-slide-up {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n`;\n","import { useMemo, useState } from \"react\";\nimport { createAIVideoGenerationDemoModel } from \"./demo-model.js\";\nimport { AIVideoGenerationScreen } from \"./screen.js\";\nimport { aiVideoStageFlow } from \"./stages.js\";\nimport type { AIVideoGenerationStage } from \"./types.js\";\n\nexport interface AIVideoGenerationStudioDemoProps {\n initialStage?: AIVideoGenerationStage;\n}\n\nexport function AIVideoGenerationStudioDemo({\n initialStage = \"idle\",\n}: AIVideoGenerationStudioDemoProps) {\n const [stage, setStage] = useState<AIVideoGenerationStage>(initialStage);\n\n const model = useMemo(() => createAIVideoGenerationDemoModel(stage), [stage]);\n\n return (\n <div style={{ display: \"grid\", gap: \"12px\" }}>\n <div\n role=\"group\"\n aria-label=\"Stage selector\"\n style={{\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: \"8px\",\n }}\n >\n {aiVideoStageFlow.map((item) => (\n <button\n type=\"button\"\n key={item.stage}\n onClick={() => setStage(item.stage)}\n style={{\n borderRadius: \"999px\",\n border: \"1px solid rgba(255,255,255,0.14)\",\n color: stage === item.stage ? \"#0F1117\" : \"#E6EAF2\",\n background: stage === item.stage ? \"#00D4FF\" : \"rgba(255,255,255,0.04)\",\n padding: \"6px 10px\",\n fontSize: \"12px\",\n cursor: \"pointer\",\n }}\n >\n {item.label}\n </button>\n ))}\n </div>\n\n <AIVideoGenerationScreen\n model={model}\n onGenerate={() => {\n setStage(\"generatingImages\");\n }}\n onUseForVideo={() => {\n setStage(\"generatingVideo\");\n }}\n onAddVoiceover={() => {\n setStage(\"voiceover\");\n }}\n onRegenerateVideo={() => {\n setStage(\"generatingVideo\");\n }}\n onExport={() => {\n setStage(\"export\");\n }}\n />\n </div>\n );\n}\n","export interface VideoPackageInfo {\n name: \"@plasius/video\";\n version: string;\n}\n\nexport const videoPackageInfo: VideoPackageInfo = {\n name: \"@plasius/video\",\n version: \"0.1.2\",\n};\n\nexport * from \"./ai-video-generation/index.js\";\n"],"mappings":"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","names":["jsx","jsxs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasius/video",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Standalone npm package for video generation components and helpers for the Plasius ecosystem",
5
5
  "type": "module",
6
6
  "private": false,
@@ -75,17 +75,19 @@
75
75
  "@types/react": "^19.2.14",
76
76
  "@types/react-dom": "^19.2.3",
77
77
  "@types/uuid": "^10.0.0",
78
- "@typescript-eslint/eslint-plugin": "^7.0.0",
79
- "@typescript-eslint/parser": "^6.15.0",
78
+ "@typescript-eslint/eslint-plugin": "^8.56.0",
79
+ "@typescript-eslint/parser": "^8.56.0",
80
80
  "@vitest/coverage-v8": "^4.0.18",
81
81
  "ajv": "^6.12.6",
82
82
  "eslint": "^10.0.1",
83
83
  "npm-run-all": "^1.1.3",
84
+ "react": "^19.1.0",
85
+ "react-dom": "^19.1.0",
84
86
  "rimraf": "^6.0.1",
85
87
  "tsup": "^8.5.0",
86
88
  "tsx": "^4.21.0",
87
89
  "typescript": "^5.9.3",
88
- "vitest": "^3.2.4",
90
+ "vitest": "^4.0.18",
89
91
  "zod": "^4.1.12"
90
92
  },
91
93
  "publishConfig": {
@@ -104,5 +106,8 @@
104
106
  "engines": {
105
107
  "node": ">=22.12"
106
108
  },
107
- "packageManager": "npm@11.4.2"
109
+ "packageManager": "npm@11.4.2",
110
+ "overrides": {
111
+ "minimatch": "^10.2.1"
112
+ }
108
113
  }
@@ -0,0 +1,115 @@
1
+ import type {
2
+ AIVideoGenerationScreenModel,
3
+ AIVideoGenerationStage,
4
+ AIVideoImageVariant,
5
+ } from "./types.js";
6
+
7
+ const basePrompt = "Mountain village at sunset";
8
+ const refinement = "Add fog rolling through the valley";
9
+
10
+ const baseVariants: AIVideoImageVariant[] = [
11
+ { id: "img-1", label: "Variant 1", alt: "Village view with warm skyline" },
12
+ { id: "img-2", label: "Variant 2", alt: "Village rooftops and distant mountains" },
13
+ { id: "img-3", label: "Variant 3", alt: "Bridge over misted valley" },
14
+ { id: "img-4", label: "Variant 4", alt: "Forest edge overlooking village lights" },
15
+ { id: "img-5", label: "Variant 5", alt: "Cloud bank drifting above the town" },
16
+ { id: "img-6", label: "Variant 6", alt: "Cinematic wide frame across the valley" },
17
+ ];
18
+
19
+ const stageStatusText: Record<AIVideoGenerationStage, string> = {
20
+ idle: "Ready to generate image directions.",
21
+ generatingImages: "Generating course-setting image variants...",
22
+ imageSelection: "Choose a visual anchor for motion extraction.",
23
+ generatingVideo: "Generating video from selected course image...",
24
+ playback: "Video ready for review.",
25
+ voiceover: "Voiceover tools ready.",
26
+ export: "Review export profile and metadata.",
27
+ };
28
+
29
+ function withSelectedVariant(
30
+ variants: AIVideoImageVariant[],
31
+ selectedId: string,
32
+ ): AIVideoImageVariant[] {
33
+ return variants.map((variant) => ({
34
+ ...variant,
35
+ isSelected: variant.id === selectedId,
36
+ }));
37
+ }
38
+
39
+ export function createAIVideoGenerationDemoModel(
40
+ stage: AIVideoGenerationStage = "idle",
41
+ ): AIVideoGenerationScreenModel {
42
+ const selectedId = "img-3";
43
+ const selectedVariants = withSelectedVariant(baseVariants, selectedId);
44
+
45
+ const model: AIVideoGenerationScreenModel = {
46
+ stage,
47
+ projectName: "Mountain Valley Storyboard",
48
+ prompt: basePrompt,
49
+ promptPlaceholder:
50
+ "Describe your scene, camera movement, mood, and intended spoken narration...",
51
+ canGenerate: stage !== "generatingImages" && stage !== "generatingVideo",
52
+ statusText: stageStatusText[stage],
53
+ generationProgress: stage === "generatingVideo" ? 62 : 100,
54
+ imageVariants:
55
+ stage === "idle" ? [] : stage === "generatingImages" ? baseVariants.slice(0, 8) : selectedVariants,
56
+ selectedImageId:
57
+ stage === "imageSelection" ||
58
+ stage === "generatingVideo" ||
59
+ stage === "playback" ||
60
+ stage === "voiceover" ||
61
+ stage === "export"
62
+ ? selectedId
63
+ : undefined,
64
+ promptVersions: [
65
+ {
66
+ id: "v1",
67
+ label: "Version 1",
68
+ basePrompt,
69
+ },
70
+ {
71
+ id: "v2",
72
+ label: "Version 2",
73
+ basePrompt,
74
+ refinement,
75
+ },
76
+ {
77
+ id: "v3",
78
+ label: "Version 3",
79
+ basePrompt,
80
+ refinement: `${refinement}; camera starts low and pans left.`,
81
+ isActive: true,
82
+ },
83
+ ],
84
+ motionDraft: {
85
+ cameraMotion: "Camera slowly pans left, then settles into a medium-wide frame.",
86
+ environmentalMotion: "Fog layers move through the valley while lantern light flickers.",
87
+ subjectMotion: "Foreground flags sway and distant birds cross near the skyline.",
88
+ },
89
+ motionPrompt: "Camera slowly pans left with drifting fog and gentle ambient motion.",
90
+ voiceSettings: {
91
+ script: "Welcome to the ancient valley. Each light tells a story waiting to be explored.",
92
+ voiceId: "narrator-documentary",
93
+ speed: 1,
94
+ emotion: "Neutral",
95
+ },
96
+ voicePresets: [
97
+ { id: "male-warm", label: "Male Warm" },
98
+ { id: "female-calm", label: "Female Calm" },
99
+ { id: "narrator-documentary", label: "Narrator Documentary" },
100
+ ],
101
+ videoSource:
102
+ stage === "playback" || stage === "voiceover" || stage === "export"
103
+ ? "https://example.invalid/plasius/video/demo.mp4"
104
+ : undefined,
105
+ };
106
+
107
+ if (stage === "idle") {
108
+ model.uploadedImageName = "uploaded-village-frame.png";
109
+ model.motionPrompt = "";
110
+ model.canGenerate = false;
111
+ model.statusText = "Upload Image: complete. Add motion instructions (required).";
112
+ }
113
+
114
+ return model;
115
+ }
@@ -0,0 +1,69 @@
1
+ import { useMemo, useState } from "react";
2
+ import { createAIVideoGenerationDemoModel } from "./demo-model.js";
3
+ import { AIVideoGenerationScreen } from "./screen.js";
4
+ import { aiVideoStageFlow } from "./stages.js";
5
+ import type { AIVideoGenerationStage } from "./types.js";
6
+
7
+ export interface AIVideoGenerationStudioDemoProps {
8
+ initialStage?: AIVideoGenerationStage;
9
+ }
10
+
11
+ export function AIVideoGenerationStudioDemo({
12
+ initialStage = "idle",
13
+ }: AIVideoGenerationStudioDemoProps) {
14
+ const [stage, setStage] = useState<AIVideoGenerationStage>(initialStage);
15
+
16
+ const model = useMemo(() => createAIVideoGenerationDemoModel(stage), [stage]);
17
+
18
+ return (
19
+ <div style={{ display: "grid", gap: "12px" }}>
20
+ <div
21
+ role="group"
22
+ aria-label="Stage selector"
23
+ style={{
24
+ display: "flex",
25
+ flexWrap: "wrap",
26
+ gap: "8px",
27
+ }}
28
+ >
29
+ {aiVideoStageFlow.map((item) => (
30
+ <button
31
+ type="button"
32
+ key={item.stage}
33
+ onClick={() => setStage(item.stage)}
34
+ style={{
35
+ borderRadius: "999px",
36
+ border: "1px solid rgba(255,255,255,0.14)",
37
+ color: stage === item.stage ? "#0F1117" : "#E6EAF2",
38
+ background: stage === item.stage ? "#00D4FF" : "rgba(255,255,255,0.04)",
39
+ padding: "6px 10px",
40
+ fontSize: "12px",
41
+ cursor: "pointer",
42
+ }}
43
+ >
44
+ {item.label}
45
+ </button>
46
+ ))}
47
+ </div>
48
+
49
+ <AIVideoGenerationScreen
50
+ model={model}
51
+ onGenerate={() => {
52
+ setStage("generatingImages");
53
+ }}
54
+ onUseForVideo={() => {
55
+ setStage("generatingVideo");
56
+ }}
57
+ onAddVoiceover={() => {
58
+ setStage("voiceover");
59
+ }}
60
+ onRegenerateVideo={() => {
61
+ setStage("generatingVideo");
62
+ }}
63
+ onExport={() => {
64
+ setStage("export");
65
+ }}
66
+ />
67
+ </div>
68
+ );
69
+ }
@@ -0,0 +1,6 @@
1
+ export type * from "./types.js";
2
+ export * from "./tokens.js";
3
+ export * from "./stages.js";
4
+ export * from "./demo-model.js";
5
+ export * from "./screen.js";
6
+ export * from "./demo.js";