EmberClone/apps/web/src/components/FileUpload.tsx

83 lines
2.5 KiB
TypeScript

import React, { useRef } from 'react';
interface FileUploadProps {
onFiles: (files: File[]) => void;
accept?: string;
multiple?: boolean;
maxSizeMB?: number;
}
export default function FileUpload({
onFiles,
accept,
multiple = false,
maxSizeMB
}: FileUploadProps) {
const inputRef = useRef<HTMLInputElement>(null);
const handleFileSelection = (files: FileList | null) => {
if (!files) return;
const fileArray = Array.from(files);
const filteredFiles = fileArray.filter(file => {
if (maxSizeMB && file.size > maxSizeMB * 1024 * 1024) {
console.warn(`File ${file.name} exceeds size limit of ${maxSizeMB}MB`);
return false;
}
return true;
});
onFiles(filteredFiles);
};
const handleDrop = (e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
handleFileSelection(e.dataTransfer.files);
};
const handleDragOver = (e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
};
const handleClick = () => {
inputRef.current?.click();
};
return (
<div
onClick={handleClick}
onDragOver={handleDragOver}
onDrop={handleDrop}
className="relative group cursor-pointer border-2 border-dashed border-slate-300 dark:border-slate-600 rounded-lg p-8 text-center transition-colors hover:border-blue-500 dark:hover:border-blue-400 hover:bg-slate-50 dark:hover:bg-slate-800/50"
>
<input
type="file"
ref={inputRef}
onChange={(e) => handleFileSelection(e.target.files)}
accept={accept}
multiple={multiple}
className="hidden"
/>
<div className="flex flex-col items-center justify-center gap-2">
<svg
className="w-10 h-10 text-slate-400 group-hover:text-blue-500 transition-colors"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13L15.01 13m-1.01 0L14 13m1.01 0L15 13" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
</svg>
<p className="text-sm text-slate-600 dark:text-slate-400">
<span className="font-semibold text-blue-600 dark:text-blue-400">Drop files here</span> or click to upload
</p>
{maxSizeMB && (
<p className="text-xs text-slate-400">Max size: {maxSizeMB}MB</p>
)}
</div>
</div>
);
}