react-icons/md#MdAddAPhoto TypeScript Examples
The following examples show how to use
react-icons/md#MdAddAPhoto.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: InputFileField.tsx From hub with Apache License 2.0 | 4 votes |
InputFileField = (props: Props) => {
const imgRef = useRef(null);
const previewCanvasRef = useRef(null);
const [upImg, setUpImg] = useState<ArrayBuffer | string | null>(null);
const [crop, setCrop] = useState<Crop | undefined>();
const [completedCrop, setCompletedCrop] = useState<PixelCrop | null>(null);
const fileInput = useRef<HTMLInputElement | null>(null);
const [isSending, setIsSending] = useState<boolean>(false);
const [openStatus, setOpenStatus] = useState<boolean>(false);
const [image, setImage] = useState<any>(null);
async function saveImage(data: string | ArrayBuffer) {
try {
const logo: LogoImage = await API.saveImage(data);
setIsSending(false);
if (!isUndefined(props.onImageChange)) {
props.onImageChange(logo.imageId);
}
} catch (err: any) {
setIsSending(false);
if (err.kind !== ErrorKind.Unauthorized) {
alertDispatcher.postAlert({
type: 'danger',
message: 'An error occurred saving the image, please try again later.',
});
} else {
props.onAuthError();
}
}
}
const onClose = () => {
setOpenStatus(false);
if (!isNull(fileInput) && !isNull(fileInput.current)) {
fileInput.current!.value = '';
}
setCrop(undefined);
setUpImg(null);
setCompletedCrop(null);
setImage(null);
};
const saveOriginal = (file: any) => {
setIsSending(true);
const reader = new FileReader();
reader.onloadend = (r: ProgressEvent<FileReader>) => {
if (!isNull(r.target) && !isNull(r.target.result)) {
saveImage(r.target.result);
}
};
reader.readAsArrayBuffer(file);
};
const saveCroppedImage = (canvas: any, crop: any) => {
if (!crop || !canvas) {
alertDispatcher.postAlert({
type: 'danger',
message: 'An error occurred saving the image, please try again later.',
});
return;
}
setIsSending(true);
canvas.toBlob(
(blob: any) => {
saveImage(blob);
onClose();
},
'image/png',
1
);
};
const onSelectFile = () => {
if (
!isNull(fileInput) &&
!isNull(fileInput.current) &&
!isNull(fileInput.current.files) &&
fileInput.current.files.length > 0
) {
setIsSending(false);
setImage(fileInput.current.files[0]);
const file = fileInput.current.files[0];
if (!file.type.startsWith('image/')) {
alertDispatcher.postAlert({
type: 'danger',
message: 'Sorry, only images are accepted',
});
} else {
const type = file.type;
if (type === 'image/svg+xml') {
saveOriginal(file);
} else {
setOpenStatus(true);
const reader = new FileReader();
reader.addEventListener('load', () => {
setUpImg(reader.result);
});
reader.readAsDataURL(file);
}
}
setIsSending(false);
}
};
const onImageLoad = useCallback((e: any) => {
const { width, height } = e.currentTarget;
const cropped = centerCrop(
makeAspectCrop(
{
// You don't need to pass a complete crop into
// makeAspectCrop or centerCrop.
unit: '%',
width: 90,
},
1,
width,
height
),
width,
height
);
imgRef.current = e.currentTarget;
setCrop(cropped);
}, []);
useEffect(() => {
if (!isNull(completedCrop) && openStatus) {
const img: any = imgRef.current;
const canvas: any = previewCanvasRef.current;
if (!isNull(canvas) && !isNull(img)) {
const tmpCrop: any = completedCrop;
const scaleX = img.naturalWidth / img.width;
const scaleY = img.naturalHeight / img.height;
const ctx = canvas.getContext('2d');
const pixelRatio = window.devicePixelRatio;
canvas.width = tmpCrop.width * pixelRatio;
canvas.height = tmpCrop.height * pixelRatio;
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
ctx.imageSmoothingQuality = 'high';
ctx.drawImage(
img,
tmpCrop.x * scaleX,
tmpCrop.y * scaleY,
tmpCrop.width * scaleX,
tmpCrop.height * scaleY,
0,
0,
tmpCrop.width,
tmpCrop.height
);
}
}
}, [completedCrop]); /* eslint-disable-line react-hooks/exhaustive-deps */
const onClick = () => {
if (!isNull(fileInput) && !isNull(fileInput.current)) {
fileInput.current.click();
}
};
return (
<>
<div className={` mb-4 ${props.className}`}>
<div className="d-flex flex-column">
<label className={`form-label ${styles.label}`} htmlFor={props.name}>
<span className="fw-bold">{props.label}</span>
{props.labelLegend && <>{props.labelLegend}</>}
</label>
<div className="position-relative">
<button
className={classnames(
'btn p-0 overflow-hidden position-relative border border-3 lh-1 rounded-circle fs-2 bg-white',
styles.btn,
{ 'opacity-50': isSending }
)}
type="button"
onClick={onClick}
aria-label="Add image"
disabled={isSending}
>
{props.value ? (
<Image
imageId={props.value}
className="mh-100 mw-100"
classNameForSquare={`position-absolute w-100 h-100 top-0 start-0 ${styles.imageAsBg}`}
alt="Logo"
/>
) : (
<>{props.placeholderIcon ? <>{props.placeholderIcon}</> : <MdAddAPhoto data-testid="defaultIcon" />}</>
)}
</button>
{isSending && (
<span className={`position-absolute spinner-border spinner-border-lg text-primary ${styles.spinner}`} />
)}
</div>
</div>
<input
type="file"
id={props.name}
name={props.name}
ref={fileInput}
className="d-none"
onChange={onSelectFile}
/>
</div>
{openStatus && (
<Modal
header={<div className={`h3 m-2 flex-grow-1 ${styles.title}`}>Crop image</div>}
open={openStatus}
modalClassName={styles.modal}
onClose={onClose}
closeButton={
<>
<button
className="btn btn-sm btn-outline-secondary"
onClick={() => {
if (!isNull(image)) {
saveImage(image);
onClose();
}
}}
disabled={isNull(image)}
aria-label="Save original"
>
<div className="d-flex flex-row align-items-center">
<BiImageAlt className="me-2" />
<span>Save original</span>
</div>
</button>
<button
type="button"
className="btn btn-sm btn-secondary ms-3"
disabled={!completedCrop?.width || !completedCrop?.height}
onClick={() => saveCroppedImage(previewCanvasRef.current, completedCrop)}
>
<div className="d-flex flex-row align-items-center">
<BiCrop className="me-2" />
<span>Save cropped image</span>
</div>
</button>
</>
}
>
<div className="w-100 h-100 d-flex flex-column">
<div className={`flex-grow-1 d-flex align-items-center justify-content-center pt-1 ${styles.cropWrapper}`}>
<div className="overflow-auto mx-auto mw-100 mh-100">
{upImg && (
<ReactCrop
crop={crop}
aspect={1}
circularCrop
onChange={(c, percentCrop) => setCrop(c)}
onComplete={(c: PixelCrop, percentCrop: PercentCrop) => setCompletedCrop(c)}
>
<img alt={props.label} src={upImg as string} onLoad={onImageLoad} />
</ReactCrop>
)}
</div>
</div>
<div className="d-flex flex-row align-items-center mt-3">
<div className="fw-bold me-3 text-uppercase">Preview</div>
<div
className={`overflow-hidden position-relative border border-3 rounded-circle bg-white ${styles.imageWrapper}`}
>
{completedCrop && (
<canvas className={`rounded-circle mw-100 mh-100 ${styles.imageAsBg}`} ref={previewCanvasRef} />
)}
</div>
</div>
</div>
</Modal>
)}
</>
);
}