import Button from "../layout/Button"; import Stack from "../layout/Stack"; import { ImagePlus, X } from "lucide-react"; import React, { DetailedHTMLProps } from "react"; import Card from "../elements/Card"; import Span from "../layout/Span"; import Center from "../layout/Center"; import imageInputToBase64, { ImageInputToBase64FunctionReturn, } from "../utils/form/imageInputToBase64"; import { twMerge } from "tailwind-merge"; import Tag from "../elements/Tag"; type ImageUploadProps = DetailedHTMLProps< React.HTMLAttributes, HTMLDivElement > & { onChangeHandler?: ( imgData: ImageInputToBase64FunctionReturn | undefined ) => any; fileInputProps?: DetailedHTMLProps< React.InputHTMLAttributes, HTMLInputElement >; placeHolderWrapper?: DetailedHTMLProps< React.HTMLAttributes, HTMLDivElement >; previewImageWrapperProps?: DetailedHTMLProps< React.HTMLAttributes, HTMLDivElement >; previewImageProps?: DetailedHTMLProps< React.ImgHTMLAttributes, HTMLImageElement >; label?: string; disablePreview?: boolean; multiple?: boolean; existingImageUrl?: string; externalSetImage?: React.Dispatch< React.SetStateAction >; externalSetImages?: React.Dispatch< React.SetStateAction >; setLoading?: React.Dispatch>; externalImage?: ImageInputToBase64FunctionReturn; restoreImageFn?: () => void; }; /** * @note use the `onChangeHandler` prop to grab the parsed base64 image object */ export default function ImageUpload({ onChangeHandler, fileInputProps, placeHolderWrapper, previewImageWrapperProps, previewImageProps, label, disablePreview, existingImageUrl, externalSetImage, externalSetImages, externalImage, multiple, restoreImageFn, setLoading, ...props }: ImageUploadProps) { const [imageObject, setImageObject] = React.useState< ImageInputToBase64FunctionReturn | undefined >(externalImage); const [src, setSrc] = React.useState(existingImageUrl); const inputRef = React.useRef(null); React.useEffect(() => { if (existingImageUrl) setSrc(existingImageUrl); }, [existingImageUrl]); return ( { setLoading?.(true); if (multiple) { (async () => { const files = e.target.files; if (!files?.[0]) return; let imgArr: ImageInputToBase64FunctionReturn[] = []; for (let i = 0; i < files.length; i++) { const file = files[i]; const fileObj = await imageInputToBase64({ file, }); imgArr.push(fileObj); } externalSetImages?.(imgArr); setLoading?.(false); })(); } else { imageInputToBase64({ imageInput: e.target }).then( (res) => { setSrc(res.imageBase64Full); onChangeHandler?.(res); setImageObject?.(res); externalSetImage?.(res); fileInputProps?.onChange?.(e); setLoading?.(false); } ); } }} ref={inputRef as any} /> {src || imageObject?.imageBase64Full ? ( {label && ( )} {disablePreview ? ( Image Uploaded! ) : ( )} ) : ( { const targetEl = e.target as HTMLElement | undefined; if (targetEl?.closest(".cancel-upload")) { e.preventDefault(); return; } inputRef.current?.click(); placeHolderWrapper?.onClick?.(e); }} {...placeHolderWrapper} >
{label || "Click to Upload Image"} {existingImageUrl && ( )}
)}
); }