52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
import { useState, useRef, DragEvent, ChangeEvent } from 'react'
|
|
|
|
interface Props {
|
|
onUpload: (file: File) => void
|
|
}
|
|
|
|
const ACCEPTED_EXTENSIONS = /\.(mp4|mov|avi|webm|mkv)$/i
|
|
|
|
export default function Upload({ onUpload }: Props) {
|
|
const [dragging, setDragging] = useState(false)
|
|
const inputRef = useRef<HTMLInputElement>(null)
|
|
|
|
const submit = (file: File) => {
|
|
if (!ACCEPTED_EXTENSIONS.test(file.name)) return
|
|
onUpload(file)
|
|
}
|
|
|
|
const onDrop = (e: DragEvent<HTMLDivElement>) => {
|
|
e.preventDefault()
|
|
setDragging(false)
|
|
const file = e.dataTransfer.files[0]
|
|
if (file) submit(file)
|
|
}
|
|
|
|
const onChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
const file = e.target.files?.[0]
|
|
if (file) submit(file)
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className={`upload-zone ${dragging ? 'dragging' : ''}`}
|
|
onClick={() => inputRef.current?.click()}
|
|
onDragOver={(e) => { e.preventDefault(); setDragging(true) }}
|
|
onDragLeave={() => setDragging(false)}
|
|
onDrop={onDrop}
|
|
>
|
|
<div className="upload-icon">↑</div>
|
|
<p className="upload-label">Drop your A-roll clip here</p>
|
|
<p className="upload-sub">or click to browse</p>
|
|
<p className="upload-formats">MP4 · MOV · AVI · WebM · MKV</p>
|
|
<input
|
|
ref={inputRef}
|
|
type="file"
|
|
accept="video/*"
|
|
style={{ display: 'none' }}
|
|
onChange={onChange}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|