import React, { useCallback, useEffect, useState } from 'react'; import { Upload, FileIcon, AlertCircle, Trash2 } from 'lucide-react'; import { Button } from '../button/button'; interface FileWithPreview extends File { preview?: string; } export interface FileUploaderProps { onFilesChange?: (files: File[]) => void; multiple?: boolean; supportedExtensions?: string[]; } export const FileUploader: React.FC = ({ onFilesChange, multiple, supportedExtensions, }) => { const [files, setFiles] = useState([]); const [isDragging, setIsDragging] = useState(false); const [error, setError] = useState(null); const isFileSupported = useCallback( (file: File) => { if (!supportedExtensions) return true; const fileExtension = file.name.split('.').pop()?.toLowerCase(); return fileExtension ? supportedExtensions.includes(`.${fileExtension}`) : false; }, [supportedExtensions] ); const handleFiles = useCallback( (selectedFiles: FileList) => { const newFiles = Array.from(selectedFiles) .filter((file) => { if (!isFileSupported(file)) { setError( `File type not supported. Supported types: ${supportedExtensions?.join(', ')}` ); return false; } return true; }) .map((file) => Object.assign(file, { preview: URL.createObjectURL(file) }) ); if (newFiles.length === 0) return; setError(null); setFiles((prevFiles) => { if (multiple) { return [...prevFiles, ...newFiles]; } else { return newFiles.slice(0, 1); } }); }, [multiple, supportedExtensions, isFileSupported] ); const onDragOver = useCallback((e: React.DragEvent) => { e.preventDefault(); setIsDragging(true); }, []); const onDragLeave = useCallback((e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); }, []); const onDrop = useCallback( (e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { handleFiles(e.dataTransfer.files); } }, [handleFiles] ); useEffect(() => { if (onFilesChange) { onFilesChange(files.length > 0 ? files : []); } }, [files, onFilesChange]); const removeFile = useCallback((fileToRemove: File) => { setFiles((prevFiles) => prevFiles.filter((file) => file !== fileToRemove) ); }, []); return (
e.target.files && handleFiles(e.target.files) } className="hidden" id="fileInput" accept={supportedExtensions?.join(',')} />
{error ? (
{error}
) : null} {files.length > 0 ? (
    {files.map((file) => (
  • {file.name}
  • ))}
) : null}
); };