hydropd / website /src /components /FileDropZone.tsx
rikardsaqe's picture
Impeccable deep pass on interior pages
9d74e85 verified
Raw
History Blame Contribute Delete
1.85 kB
import { useRef, useState } from 'react'
interface FileDropZoneProps {
onFile: (text: string, filename: string) => void
accept?: string
}
export default function FileDropZone({
onFile,
accept = '.fasta,.fa,.faa,.txt,.csv',
}: FileDropZoneProps) {
const [dragging, setDragging] = useState(false)
const inputRef = useRef<HTMLInputElement>(null)
function readFile(file: File) {
const reader = new FileReader()
reader.onload = () => onFile(String(reader.result ?? ''), file.name)
reader.readAsText(file)
}
return (
<div
className={'dropzone' + (dragging ? ' dragging' : '')}
onClick={() => inputRef.current?.click()}
onDragOver={(e) => {
e.preventDefault()
setDragging(true)
}}
onDragLeave={() => setDragging(false)}
onDrop={(e) => {
e.preventDefault()
setDragging(false)
const file = e.dataTransfer.files?.[0]
if (file) readFile(file)
}}
>
<div className="dropzone-icon" aria-hidden>
<svg
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M12 15V4M8 8l4-4 4 4M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3" />
</svg>
</div>
<div className="dropzone-main">
Drag &amp; drop a file, or click to browse
</div>
<div className="dropzone-sub">FASTA (.fasta / .fa) or plain text (.txt)</div>
<input
ref={inputRef}
type="file"
accept={accept}
style={{ display: 'none' }}
onChange={(e) => {
const file = e.target.files?.[0]
if (file) readFile(file)
e.target.value = ''
}}
/>
</div>
)
}