import { ImagePlus, XCircle } from "lucide-react"; import React, { useCallback, useEffect, useRef, useState } from "react"; import type { ControllerRenderProps, FieldError } from "react-hook-form"; import { Button } from "./button"; // Your existing Button component // Props for our custom field component interface IconUploadFieldProps { field: ControllerRenderProps; // Provided by RHF's FormField render prop error?: FieldError; // Optional: if you want to pass error for internal styling accept?: string; // e.g., "image/png, image/jpeg" previewContainerClassName?: string; // Style for the preview box itself // Add any other props you might want to customize its appearance/behavior } export function IconUploadField({ field, error, accept = "image/*", previewContainerClassName = "w-24 h-24 rounded-full", // Default circular preview }: IconUploadFieldProps) { const [previewUrl, setPreviewUrl] = useState(null); const fileInputRef = useRef(null); const currentFileValue = field.value as File | undefined | null; useEffect(() => { let objectUrl: string | null = null; if (currentFileValue && currentFileValue instanceof File) { objectUrl = URL.createObjectURL(currentFileValue); setPreviewUrl(objectUrl); } else { setPreviewUrl(null); } return () => { if (objectUrl) { URL.revokeObjectURL(objectUrl); } }; }, [currentFileValue]); const handleFileChange = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; field.onChange(file || undefined); if (event.target) { event.target.value = ""; } }; const handleRemoveImage = useCallback((e: React.MouseEvent) => { e.preventDefault(); field.onChange(undefined); if (fileInputRef.current) { fileInputRef.current.value = ""; } }, [field]); const triggerFileInput = useCallback(() => { fileInputRef.current?.click(); }, []); return (
{/* Main clickable area for upload, also receives RHF's ref */}
{ if (e.key === "Enter" || e.key === " ") { e.preventDefault(); triggerFileInput(); } }} role="button" tabIndex={0} aria-label={previewUrl ? "Change icon" : "Upload icon"} aria-invalid={!!error} aria-describedby={error ? `${field.name}-error` : undefined} > {previewUrl ? ( Icon preview ) : ( )}
{/* */} {currentFileValue && ( // Show remove button only if a file is selected )}
); }