Spaces:
Runtime error
Runtime error
| 'use client'; | |
| import React, { useRef, useState } from "react"; | |
| import { FiTrash2 } from "react-icons/fi"; // Use trash bin icon | |
| interface ImageInputProps { | |
| image: File | null; | |
| setImage: (f: File | null) => void; | |
| classify: (input: string | Blob) => void; | |
| ready: boolean | null; | |
| } | |
| export const ImageInput = ({ image, setImage, classify, ready }: ImageInputProps) => { | |
| const inputRef = useRef<HTMLInputElement>(null); | |
| const [dragOver, setDragOver] = useState(false); // NEW: Track drag-over state | |
| const handleFile = (file: File) => { | |
| setImage(file); | |
| const reader = new FileReader(); | |
| reader.onload = (ev) => { | |
| classify(ev.target?.result as string); | |
| }; | |
| reader.readAsDataURL(file); | |
| }; | |
| // NEW: Handle delete image | |
| const handleDelete = (e: React.MouseEvent) => { | |
| e.stopPropagation(); | |
| setImage(null); | |
| }; | |
| return ( | |
| <div | |
| className={`flex flex-col items-center justify-center border-2 border-dashed rounded-lg p-8 min-h-[220px] transition-all duration-300 cursor-pointer bg-gray-50 relative | |
| ${ready === false ? 'opacity-50 pointer-events-none' : ''} | |
| ${dragOver ? 'border-blue-600 bg-blue-50 scale-105 shadow-lg' : 'hover:border-blue-400'}`} | |
| tabIndex={0} | |
| onClick={() => inputRef.current?.click()} | |
| onDrop={e => { | |
| e.preventDefault(); | |
| setDragOver(false); | |
| if (e.dataTransfer.files.length > 0 && e.dataTransfer.files[0].type.startsWith('image/')) { | |
| handleFile(e.dataTransfer.files[0]); | |
| } | |
| }} | |
| onDragOver={e => { | |
| e.preventDefault(); | |
| setDragOver(true); | |
| }} | |
| onDragLeave={() => setDragOver(false)} | |
| > | |
| {image ? ( | |
| <div className="relative w-full flex flex-col items-center"> | |
| {/* Delete button at top-right of image container */} | |
| <button | |
| onClick={handleDelete} | |
| className="absolute -top-3 -right-3 z-10 bg-white border border-gray-200 hover:bg-red-500 hover:text-white text-gray-700 rounded-full p-1 shadow transition-colors w-7 h-7 flex items-center justify-center" | |
| aria-label="Remove image" | |
| tabIndex={0} | |
| type="button" | |
| > | |
| <FiTrash2 size={16} className="text-red-500 overflow-visible" /> | |
| </button> | |
| <img | |
| src={URL.createObjectURL(image)} | |
| alt="Uploaded" | |
| className="mx-auto max-h-48 rounded-lg shadow-md mb-4 animate-fade-in" | |
| /> | |
| </div> | |
| ) : ( | |
| <span className={`text-lg ${dragOver ? 'text-blue-600 animate-pulse' : 'text-gray-400 animate-pulse'}`}> | |
| Drop image here, or click to select | |
| </span> | |
| )} | |
| <input | |
| ref={inputRef} | |
| type="file" | |
| accept="image/*" | |
| style={{ display: 'none' }} | |
| onChange={e => { | |
| if (e.target.files && e.target.files[0]) { | |
| handleFile(e.target.files[0]); | |
| } | |
| }} | |
| /> | |
| </div> | |
| ); | |
| }; |