'use client'; import { FileUpload, FileUploadDropzone, FileUploadItem, FileUploadItemDelete, FileUploadItemMetadata, FileUploadItemPreview, FileUploadItemProgress, FileUploadList, FileUploadTrigger, type FileUploadProps, } from '@/components/file-upload'; import { Button } from '@/components/ui/button'; import { Textarea } from '@/components/ui/textarea'; import { cn } from '@/lib/utils'; import { t } from 'i18next'; import { CircleStop, Paperclip, Send, Upload, X } from 'lucide-react'; import * as React from 'react'; import { useCallback, useEffect, useState } from 'react'; import { toast } from 'sonner'; import { AudioButton } from '../ui/audio-button'; interface NextMessageInputProps { disabled: boolean; value: string; sendDisabled: boolean; sendLoading: boolean; conversationId: string; uploadMethod?: string; isShared?: boolean; showUploadIcon?: boolean; isUploading?: boolean; onPressEnter({ enableThinking }: { enableThinking: boolean }): void; onInputChange: React.ChangeEventHandler; createConversationBeforeUploadDocument?(message: string): Promise; stopOutputMessage?(): void; onUpload?: NonNullable; removeFile?(file: File): void; showReasoning?: boolean; } export type NextMessageInputOnPressEnterParameter = Parameters< NextMessageInputProps['onPressEnter'] >; export function NextMessageInput({ isUploading = false, value, sendDisabled, sendLoading, disabled, showUploadIcon = true, onUpload, onInputChange, stopOutputMessage, onPressEnter, removeFile, showReasoning = false, }: NextMessageInputProps) { const [files, setFiles] = React.useState([]); const [audioInputValue, setAudioInputValue] = React.useState( null, ); const [enableThinking, setEnableThinking] = useState(false); const handleThinkingToggle = useCallback(() => { setEnableThinking((prev) => !prev); }, []); useEffect(() => { if (audioInputValue !== null) { onInputChange({ target: { value: audioInputValue }, } as React.ChangeEvent); setTimeout(() => { onPressEnter({ enableThinking }); setAudioInputValue(null); }, 0); } }, [audioInputValue, onInputChange, onPressEnter, enableThinking]); const onFileReject = React.useCallback((file: File, message: string) => { toast(message, { description: `"${file.name.length > 20 ? `${file.name.slice(0, 20)}...` : file.name}" has been rejected`, }); }, []); const submit = React.useCallback(() => { if (isUploading) return; onPressEnter({ enableThinking }); setFiles([]); }, [isUploading, onPressEnter, enableThinking]); const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); submit(); } }; const onSubmit = React.useCallback( (event: React.FormEvent) => { event.preventDefault(); submit(); }, [submit], ); const handleRemoveFile = React.useCallback( (file: File) => () => { removeFile?.(file); }, [removeFile], ); return ( event.preventDefault()} className="absolute top-0 left-0 z-0 flex size-full items-center justify-center rounded-none border-none bg-background/50 p-0 opacity-0 backdrop-blur transition-opacity duration-200 ease-out data-[dragging]:z-10 data-[dragging]:opacity-100" >

Drag & drop files here

Upload max 5 files each up to 5MB

{files.map((file, index) => ( ))}