Spaces:
Sleeping
Sleeping
| import { useCallback, useRef, useState } from 'preact/hooks'; | |
| interface UploadProps { | |
| onFile: (file: File) => void; | |
| disabled?: boolean; | |
| } | |
| export function Upload({ onFile, disabled }: UploadProps) { | |
| const [dragOver, setDragOver] = useState(false); | |
| const inputRef = useRef<HTMLInputElement>(null); | |
| const handleFile = useCallback( | |
| (file: File | undefined) => { | |
| if (file && (file.type === 'image/jpeg' || file.type === 'image/png')) { | |
| onFile(file); | |
| } | |
| }, | |
| [onFile] | |
| ); | |
| const onDrop = useCallback( | |
| (e: DragEvent) => { | |
| e.preventDefault(); | |
| setDragOver(false); | |
| handleFile(e.dataTransfer?.files[0]); | |
| }, | |
| [handleFile] | |
| ); | |
| const onDragOver = useCallback((e: DragEvent) => { | |
| e.preventDefault(); | |
| setDragOver(true); | |
| }, []); | |
| const onDragLeave = useCallback(() => setDragOver(false), []); | |
| const onChange = useCallback( | |
| (e: Event) => { | |
| const input = e.target as HTMLInputElement; | |
| handleFile(input.files?.[0]); | |
| }, | |
| [handleFile] | |
| ); | |
| return ( | |
| <div | |
| class={`upload-zone ${dragOver ? 'drag-over' : ''} ${disabled ? 'disabled' : ''}`} | |
| onDrop={onDrop} | |
| onDragOver={onDragOver} | |
| onDragLeave={onDragLeave} | |
| onClick={() => !disabled && inputRef.current?.click()} | |
| > | |
| <input | |
| ref={inputRef} | |
| type="file" | |
| accept="image/jpeg,image/png" | |
| onChange={onChange} | |
| hidden | |
| /> | |
| <p class="upload-icon">+</p> | |
| <p>Drag & drop an aerial image here, or click to browse</p> | |
| <p class="upload-hint">JPEG or PNG</p> | |
| </div> | |
| ); | |
| } | |