stem-separator / frontend /src /components /UploadZone.tsx
sourav-das's picture
Upload folder using huggingface_hub
7dfae77 verified
import { useState, useRef, useCallback } from "react";
interface UploadZoneProps {
onFile: (file: File) => void;
disabled?: boolean;
}
const ACCEPTED = ".wav,.mp3,.flac,.ogg,.m4a,.aac,.wma,.opus";
const MAX_SIZE = 100 * 1024 * 1024;
export function UploadZone({ onFile, disabled }: UploadZoneProps) {
const [isDragOver, setIsDragOver] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);
const handleFile = useCallback(
(file: File) => {
if (file.size > MAX_SIZE) {
alert("File too large (max 100MB)");
return;
}
onFile(file);
},
[onFile]
);
const handleDrop = useCallback(
(e: React.DragEvent) => {
e.preventDefault();
setIsDragOver(false);
const file = e.dataTransfer.files[0];
if (file) handleFile(file);
},
[handleFile]
);
const handleChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) handleFile(file);
},
[handleFile]
);
return (
<div
className={`
relative rounded-xl border-2 border-dashed p-8 md:p-12
text-center cursor-pointer transition-all duration-200
${
isDragOver
? "border-accent bg-accent/10"
: "border-border hover:border-text-secondary hover:bg-bg-hover/50"
}
${disabled ? "opacity-50 pointer-events-none" : ""}
`}
onDragOver={(e) => {
e.preventDefault();
setIsDragOver(true);
}}
onDragLeave={() => setIsDragOver(false)}
onDrop={handleDrop}
onClick={() => inputRef.current?.click()}
>
<input
ref={inputRef}
type="file"
accept={ACCEPTED}
className="hidden"
onChange={handleChange}
/>
<div className="flex flex-col items-center gap-3">
<svg
className="w-12 h-12 text-text-secondary"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={1.5}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15m0-3l-3-3m0 0l-3 3m3-3v11.25"
/>
</svg>
<div>
<p className="text-base md:text-lg font-medium text-text-primary">
Drop audio file here or click to browse
</p>
<p className="text-sm text-text-secondary mt-1">
WAV, MP3, FLAC, OGG, M4A, AAC (max 100MB)
</p>
</div>
</div>
</div>
);
}