Spaces:
Running
Running
| import React, { useState, useCallback, useRef } from 'react'; | |
| import { UploadCloudIcon } from './Icons'; | |
| interface FileUploaderProps { | |
| onFilesAdded: (files: File[]) => void; | |
| } | |
| const FileUploader: React.FC<FileUploaderProps> = ({ onFilesAdded }) => { | |
| const [isDragging, setIsDragging] = useState(false); | |
| const fileInputRef = useRef<HTMLInputElement>(null); | |
| const handleDragEnter = useCallback((e: React.DragEvent<HTMLDivElement>) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| setIsDragging(true); | |
| }, []); | |
| const handleDragLeave = useCallback((e: React.DragEvent<HTMLDivElement>) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| setIsDragging(false); | |
| }, []); | |
| const handleDragOver = useCallback((e: React.DragEvent<HTMLDivElement>) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| }, []); | |
| const handleDrop = useCallback((e: React.DragEvent<HTMLDivElement>) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| setIsDragging(false); | |
| const files = Array.from(e.dataTransfer.files); | |
| if (files && files.length > 0) { | |
| onFilesAdded(files); | |
| } | |
| }, [onFilesAdded]); | |
| const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => { | |
| const files = Array.from(e.target.files || []); | |
| if (files && files.length > 0) { | |
| onFilesAdded(files); | |
| } | |
| }; | |
| const openFileDialog = () => { | |
| fileInputRef.current?.click(); | |
| }; | |
| return ( | |
| <div | |
| className={`relative border-2 border-dashed rounded-lg p-12 text-center transition-colors duration-200 ease-in-out ${ | |
| isDragging ? 'border-indigo-400 bg-gray-800' : 'border-gray-600 hover:border-indigo-500' | |
| }`} | |
| onDragEnter={handleDragEnter} | |
| onDragLeave={handleDragLeave} | |
| onDragOver={handleDragOver} | |
| onDrop={handleDrop} | |
| onClick={openFileDialog} | |
| > | |
| <input | |
| ref={fileInputRef} | |
| type="file" | |
| multiple | |
| accept="image/*,video/*,.txt" | |
| className="hidden" | |
| onChange={handleFileSelect} | |
| /> | |
| <div className="flex flex-col items-center justify-center space-y-4"> | |
| <UploadCloudIcon className="w-12 h-12 text-gray-400" /> | |
| <p className="text-gray-400"> | |
| <span className="font-semibold text-indigo-400">Click to upload</span> or drag and drop | |
| </p> | |
| <p className="text-xs text-gray-500">Upload media and optional .txt captions (must have matching filenames)</p> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default FileUploader; | |