import { useEffect, useCallback } from 'react'; import { useInputBarStore } from '../store/inputBar'; import { useGenerationStore } from '../store/generation'; import { Dropdown } from './Dropdown'; import type { CreationMode, AspectRatio, Duration, GenerationType, ModelOption } from '../types'; import styles from './Toolbar.module.css'; const VideoIcon = () => ( ); const ImageIcon = () => ( ); const DiamondIcon = () => ( ); const LightningIcon = () => ( ); const StarIcon = () => ( ); const SwapIcon = () => ( ); const MonitorIcon = () => ( ); const ClockIcon = () => ( ); const ChevronDown = () => ( ); const generationTypeItems = [ { label: '视频生成', value: 'video' as GenerationType, icon: }, { label: '图片生成', value: 'image' as GenerationType, icon: }, ]; const modelItems = [ { label: 'Seedance 2.0', value: 'seedance_2.0' as ModelOption, icon: }, { label: 'Seedance 2.0 Fast', value: 'seedance_2.0_fast' as ModelOption, icon: }, ]; const modeItems = [ { label: '全能参考', value: 'universal' as CreationMode, icon: }, { label: '首尾帧', value: 'keyframe' as CreationMode, icon: }, ]; const ratioItems = [ { label: '16:9', value: '16:9' as AspectRatio }, { label: '9:16', value: '9:16' as AspectRatio }, { label: '1:1', value: '1:1' as AspectRatio }, { label: '21:9', value: '21:9' as AspectRatio }, { label: '4:3', value: '4:3' as AspectRatio }, { label: '3:4', value: '3:4' as AspectRatio }, ]; const durationItems = [ { label: '5s', value: '5' }, { label: '10s', value: '10' }, { label: '15s', value: '15' }, ]; const modeLabels: Record = { universal: '全能参考', keyframe: '首尾帧', }; export function Toolbar() { const generationType = useInputBarStore((s) => s.generationType); const setGenerationType = useInputBarStore((s) => s.setGenerationType); const model = useInputBarStore((s) => s.model); const setModel = useInputBarStore((s) => s.setModel); const mode = useInputBarStore((s) => s.mode); const switchMode = useInputBarStore((s) => s.switchMode); const aspectRatio = useInputBarStore((s) => s.aspectRatio); const setAspectRatio = useInputBarStore((s) => s.setAspectRatio); const duration = useInputBarStore((s) => s.duration); const setDuration = useInputBarStore((s) => s.setDuration); const isSubmittable = useInputBarStore((s) => s.canSubmit()); const triggerInsertAt = useInputBarStore((s) => s.triggerInsertAt); const isKeyframe = mode === 'keyframe'; const addTask = useGenerationStore((s) => s.addTask); const handleSend = useCallback(() => { if (!isSubmittable) return; addTask(); }, [isSubmittable, addTask]); const handleInsertAt = useCallback(() => { triggerInsertAt(); }, [triggerInsertAt]); // Keyboard shortcut: Ctrl/Cmd + Enter useEffect(() => { const handler = (e: KeyboardEvent) => { if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { handleSend(); } }; document.addEventListener('keydown', handler); return () => document.removeEventListener('keydown', handler); }, [handleSend]); return (
{/* Generation type dropdown */} setGenerationType(v as GenerationType)} minWidth={150} trigger={ } /> {/* Model selector dropdown */} setModel(v as ModelOption)} minWidth={190} trigger={ } /> {/* Mode selector */} switchMode(v as CreationMode)} minWidth={150} trigger={ } /> {/* Aspect ratio */} {isKeyframe ? ( ) : ( setAspectRatio(v as AspectRatio)} minWidth={100} trigger={ } /> )} {/* Duration */} setDuration(Number(v) as Duration)} minWidth={100} trigger={ } /> {/* @ button - universal mode only */} {!isKeyframe && ( )} {/* Spacer */}
{/* Credits indicator */}
30
{/* Send button */}
); }