Spaces:
Sleeping
Sleeping
| import { useRef, useState, type DragEvent } from "react"; | |
| import { Upload } from "lucide-react"; | |
| import { ACCEPTED_DATA_EXTS, MAX_DATA_FILE_SIZE } from "../utils/data-files"; | |
| interface UploadZoneProps { | |
| onFiles: (files: FileList | File[]) => void | Promise<void>; | |
| disabled?: boolean; | |
| compact?: boolean; | |
| } | |
| const ACCEPT_ATTR = ACCEPTED_DATA_EXTS.map((e) => `.${e}`).join(","); | |
| const MAX_MB = (MAX_DATA_FILE_SIZE / (1024 * 1024)).toFixed(0); | |
| export function UploadZone({ onFiles, disabled, compact }: UploadZoneProps) { | |
| const inputRef = useRef<HTMLInputElement>(null); | |
| const [isDragging, setIsDragging] = useState(false); | |
| const handleDrop = (e: DragEvent<HTMLDivElement>) => { | |
| e.preventDefault(); | |
| setIsDragging(false); | |
| if (disabled) return; | |
| if (e.dataTransfer.files?.length) void onFiles(e.dataTransfer.files); | |
| }; | |
| const handleDragOver = (e: DragEvent<HTMLDivElement>) => { | |
| e.preventDefault(); | |
| if (!disabled) setIsDragging(true); | |
| }; | |
| const handleDragLeave = () => setIsDragging(false); | |
| return ( | |
| <div | |
| className={`es-upload-zone ${isDragging ? "es-upload-zone--active" : ""} ${compact ? "es-upload-zone--compact" : ""}`} | |
| onDrop={handleDrop} | |
| onDragOver={handleDragOver} | |
| onDragLeave={handleDragLeave} | |
| onClick={() => !disabled && inputRef.current?.click()} | |
| role="button" | |
| tabIndex={disabled ? -1 : 0} | |
| aria-label="Upload data file" | |
| > | |
| <input | |
| ref={inputRef} | |
| type="file" | |
| accept={ACCEPT_ATTR} | |
| multiple | |
| onChange={(e) => { | |
| if (e.target.files?.length) void onFiles(e.target.files); | |
| e.target.value = ""; | |
| }} | |
| style={{ display: "none" }} | |
| /> | |
| <Upload size={compact ? 14 : 18} /> | |
| {compact ? ( | |
| <span>Add data file</span> | |
| ) : ( | |
| <div className="es-upload-zone__text"> | |
| <strong>Drop a data file</strong> | |
| <span>CSV, TSV, JSON, NDJSON, TXT - up to {MAX_MB} MB</span> | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } | |