{!videoUrl && (
<>
{/* Mode indicator */}
{mode === 'i2v' ? '🖼️ Image-to-Video' : '✨ Text-to-Video'}
{mode === 'i2v' ? '(animates your image)' : '(generates from text only)'}
{/* Image Input Section */}
{/* Image preview or upload area */}
{(imageUrl || imageBase64) ? (

{
(e.target as HTMLImageElement).style.display = 'none'
setError('Failed to load image from URL')
}}
/>
) : (
{/* Upload button */}
)}
{/* URL input (collapsible) */}
{!imageBase64 && (
{
setImageUrl(e.target.value)
setImageBase64('')
}}
placeholder="Or paste image URL..."
disabled={isGenerating}
onPointerDown={(e) => e.stopPropagation()}
onTouchStart={(e) => e.stopPropagation()}
onMouseDown={(e) => e.stopPropagation()}
style={{
width: '100%',
padding: '8px 10px',
backgroundColor: '#fff',
color: '#333',
border: '1px solid #ddd',
borderRadius: '6px',
fontSize: '12px',
boxSizing: 'border-box',
touchAction: 'manipulation',
minHeight: '44px',
}}
/>
)}
{/* Prompt */}
{
editor.updateShape({
id: shape.id,
type: shape.type,
props: { ...shape.props, duration: parseInt(e.target.value) || 3 }
})
}}
disabled={isGenerating}
onPointerDown={(e) => e.stopPropagation()}
onTouchStart={(e) => e.stopPropagation()}
onMouseDown={(e) => e.stopPropagation()}
style={{
width: '100%',
padding: '8px',
backgroundColor: '#fff',
color: '#333',
border: '1px solid #ddd',
borderRadius: '6px',
fontSize: '13px',
boxSizing: 'border-box',
touchAction: 'manipulation',
minHeight: '44px',
}}
/>
{error && (
Error: {error}
)}
fal.ai WAN 2.1 Video Generation
{mode === 'i2v'
? 'Animates your image based on the motion prompt'
: 'Creates video from your text description'
}
Output: ~4 seconds | Fast startup
Processing: 30-90 seconds (no cold start)
>
)}
{videoUrl && (
<>