import { Box, Button, IconButton, Modal, Slider, SxProps, Theme, Typography, useMediaQuery, useTheme, } from "@mui/material"; import React, { FC, useEffect, useRef, useState } from "react"; import ReactCrop, { Crop, PixelCrop } from "react-image-crop"; import { canvasPreview } from "./utils/canvasPreview"; import { ResetIcon } from "@icons/ResetIcon"; import { CropIcon } from "@icons/CropIcon"; import "react-image-crop/dist/ReactCrop.css"; const styleSlider: SxProps = { color: "#7E2AEA", height: "12px", "& .MuiSlider-track": { border: "none", }, "& .MuiSlider-rail": { backgroundColor: "#F2F3F7", border: `1px solid #9A9AAF`, }, "& .MuiSlider-thumb": { height: 26, width: 26, border: `6px solid #7E2AEA`, backgroundColor: "white", boxShadow: `0px 0px 0px 3px white, 0px 4px 4px 3px #C3C8DD`, "&:focus, &:hover, &.Mui-active, &.Mui-focusVisible": { boxShadow: `0px 0px 0px 3px white, 0px 4px 4px 3px #C3C8DD`, }, }, }; interface Iprops { opened: boolean; onClose: () => void; picture?: string; onCropPress?: (imageUrl: string) => void; } export const CropModal: FC = ({ opened, onClose, picture, onCropPress }) => { const theme = useTheme(); const [crop, setCrop] = useState(); const [completedCrop, setCompletedCrop] = useState(); const [darken, setDarken] = useState(0); const [rotate, setRotate] = useState(0); const [imgSrc, setImgSrc] = useState(""); const [width, setWidth] = useState(0); const blobUrlRef = useRef(""); const fileInputRef = useRef(null); const imgRef = useRef(null); const isMobile = useMediaQuery(theme.breakpoints.down(786)); useEffect(() => { if (picture) setImgSrc(picture); }, [picture]); const handleFileChange = (event: React.ChangeEvent) => { if (!event.target.files?.length) return; setCrop(undefined); try { const url = URL.createObjectURL(event.target.files[0]); setImgSrc(url); } catch (error) { console.error("Failed to create object url for image", error); } }; const handleCropClick = () => { if (!completedCrop) throw new Error("No completed crop"); if (!imgRef.current) throw new Error("No image"); const canvasCopy = document.createElement("canvas"); const ctx = canvasCopy.getContext("2d"); if (!ctx) throw new Error("No 2d context"); canvasCopy.width = completedCrop.width; canvasCopy.height = completedCrop.height; ctx.filter = `brightness(${100 - darken}%)`; canvasPreview(imgRef.current, canvasCopy, completedCrop, rotate); canvasCopy.toBlob((blob) => { if (!blob) { throw new Error("Failed to create blob"); } if (blobUrlRef.current) { URL.revokeObjectURL(blobUrlRef.current); } blobUrlRef.current = URL.createObjectURL(blob); setImgSrc(blobUrlRef.current); onCropPress?.(blobUrlRef.current); setCrop(undefined); }); }; const getImageSize = () => { if (imgRef.current) { const imageWidth = imgRef.current.naturalWidth; const imageHeight = imgRef.current.naturalHeight; const aspect = imageWidth / imageHeight; if (aspect <= 1.333) { setWidth(240); } if (aspect >= 1.5) { setWidth(580); } if (aspect >= 1.778) { setWidth(580); } } }; function handleSaveClick() { onClose(); } return ( {imgSrc && ( setCrop(percentCrop)} onComplete={(c) => setCompletedCrop(c)} maxWidth={500} minWidth={50} maxHeight={320} minHeight={50} > Crop me )} {crop?.width ? Math.round(crop.width) + "px" : ""} {crop?.height ? Math.round(crop.height) + "px" : ""} setRotate(r => (r + 90) % 360)}> Размер { setWidth(newValue as number); }} /> Затемнение setDarken(newValue as number)} /> ); };