@churchapps/apphelper
Version:
Library of helper functions for React and NextJS ChurchApps
98 lines • 5.47 kB
JavaScript
"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useEffect, useRef, Suspense, lazy } from "react";
import { InputBox, SmallButton, Loading } from ".";
import { Locale } from "../helpers";
import "../../public/css/cropper.css";
// Lazy load the Cropper component
const Cropper = lazy(() => import("react-cropper").then(module => ({ default: module.default })));
export function ImageEditor(props) {
const [photoSrc, setPhotoSrc] = useState("");
const [croppedImageDataUrl, setCroppedImageDataUrl] = useState("");
const cropperRef = useRef(null);
let timeout = null;
const handleSave = () => {
console.log('ImageEditor handleSave called, croppedImageDataUrl:', croppedImageDataUrl ? 'Data URL available' : 'No data URL');
props.onUpdate(croppedImageDataUrl);
};
const handleDelete = () => props.onUpdate("");
const handleUpload = (e) => {
e.preventDefault();
let files;
if (e.target) {
files = e.target.files;
}
if (!files || files.length === 0)
return;
const reader = new FileReader();
reader.onload = () => {
const url = reader.result.toString();
console.log('ImageEditor file uploaded, setting photoSrc');
setPhotoSrc(url);
setCroppedImageDataUrl("");
};
reader.readAsDataURL(files[0]);
// Clear the input value to allow re-uploading the same file
e.target.value = "";
};
const selectDefaultCropZone = () => {
const imageElement = cropperRef?.current;
let cropper = imageElement?.cropper;
if (props.aspectRatio === 0) {
let containerData = cropper.getContainerData();
const imgWidth = cropper.getImageData().width;
const imgHeight = cropper.getImageData().height;
const effectiveWidth = (containerData.width > imgWidth) ? imgWidth : containerData.width;
const effectiveHeight = (containerData.height > imgHeight) ? imgHeight : containerData.height;
cropper.setCropBoxData({ width: effectiveWidth, height: effectiveHeight, left: (containerData.width - effectiveWidth) / 2.0, top: (containerData.height - effectiveHeight) / 2.0 });
}
else {
let desiredAspect = props.aspectRatio;
let containerData = cropper.getContainerData();
let imgAspect = cropper.getImageData().aspectRatio;
let scale = imgAspect / desiredAspect;
if (scale < 1) {
const imgWidth = cropper.getImageData().width;
let l = (containerData.width - imgWidth) / 2.0;
let t = (containerData.height - (containerData.height * scale)) / 2.0;
cropper.setCropBoxData({ width: imgWidth, height: imgWidth / desiredAspect, left: l, top: t });
}
else {
const imgHeight = cropper.getImageData().height;
let l = (containerData.width - (imgHeight * desiredAspect)) / 2.0;
let t = cropper.canvasData.top;
cropper.setCropBoxData({ width: imgHeight * desiredAspect, height: imgHeight, left: l, top: t });
}
}
};
const handleCrop = () => {
if (timeout !== null) {
window.clearTimeout(timeout);
timeout = null;
}
timeout = window.setTimeout(() => {
if (cropperRef.current !== null) {
const imageElement = cropperRef?.current;
const cropper = imageElement?.cropper;
//Do not enlarge if less
const imageData = cropper.getImageData();
let width = props.outputWidth || 400;
let height = props.outputHeight || 300;
if (imageData.naturalWidth < width && imageData.naturalHeight < height) {
width = imageData.naturalWidth;
height = imageData.naturalHeight;
}
const url = cropper.getCroppedCanvas({ width, height }).toDataURL("image/png", 0.4);
console.log('ImageEditor handleCrop setting croppedImageDataUrl');
setCroppedImageDataUrl(url);
}
}, 200);
};
useEffect(() => { setPhotoSrc(props.photoUrl); }, [props.photoUrl]);
return (_jsx(InputBox, { id: "cropperBox", headerIcon: "", headerText: props.title, ariaLabelDelete: "deletePhoto", saveText: Locale.label("common.update"), saveFunction: handleSave, cancelFunction: props.onCancel, deleteFunction: (!props.hideDelete) && handleDelete, headerActionContent: _jsxs("div", { children: [_jsx("input", { type: "file", onChange: handleUpload, id: "fileUpload", accept: "image/*", style: { display: "none" } }), _jsx(SmallButton, { icon: "upload", text: "Upload", onClick: () => {
document.getElementById("fileUpload").click();
} })] }), children: _jsx(Suspense, { fallback: _jsx(Loading, {}), children: _jsx(Cropper, { ref: cropperRef, src: photoSrc, style: { height: 240, width: "100%" }, aspectRatio: props.aspectRatio, guides: false, crop: handleCrop, autoCropArea: 1, viewMode: 0, responsive: true, restore: false, checkOrientation: false, background: false, ready: () => {
setTimeout(selectDefaultCropZone, 100);
} }, photoSrc) }) }));
}
//# sourceMappingURL=ImageEditor.js.map