All files / src/shared/ProfileImage/EditProfileImageModal/components/hooks useImageCropper.ts

100% Statements 34/34
92.3% Branches 12/13
100% Functions 9/9
100% Lines 32/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90                                  1x             1x       22x   22x 22x   22x   22x 10x 10x   9x 9x   9x     22x 3x 3x 3x     22x 3x 3x     22x 2x 2x     22x 2x 1x       22x 7x 7x     22x                         1x 9x 9x    
import { isArray } from "lodash";
import { useRef, useState } from "react";
import { ReactCropperElement } from "react-cropper";
 
interface StateType {
  zoom: number;
  rotation: number;
  croppedAreaPixels: any;
  file: File | null;
}
 
type TZoomParams = {
  minZoom: number;
  maxZoom: number;
  step: number;
};
 
const initialState: StateType = {
  zoom: 0,
  rotation: 0,
  croppedAreaPixels: null,
  file: null,
};
 
const useImageCropper = (
  zoomParams: TZoomParams,
  handleUpdateImage: (url: HTMLCanvasElement) => void,
) => {
  const { minZoom, maxZoom, step } = zoomParams;
 
  const cropperRef = useRef<ReactCropperElement>(null);
  const [{ zoom, rotation }, setCustomize] = useState<StateType>(initialState);
 
  const zoomValue = Math.round((zoom / maxZoom) * 100);
 
  const handleZoomCanvas = (zoom: number) => {
    const cropper = cropperRef.current?.cropper;
    if (!cropper) return;
 
    const scale = normalizeScale(zoom);
    cropper.scale(scale);
 
    setCustomize((p) => ({ ...p, zoom }));
  };
 
  const getNewZoomValue = (value: number, isAdd: boolean) => {
    const addValue = value + step >= maxZoom ? maxZoom : value + step;
    const subtractValue = value - step <= minZoom ? minZoom : value - step;
    return isAdd ? addValue : subtractValue;
  };
 
  const handleZoom = (isAdd = false) => {
    const newValue = getNewZoomValue(zoom, isAdd);
    handleZoomCanvas(newValue);
  };
 
  const rotate = () => {
    const cropper = cropperRef.current?.cropper;
    cropper?.rotate(-90);
  };
 
  const getCropData = () => {
    if (typeof cropperRef.current?.cropper !== "undefined") {
      handleUpdateImage(cropperRef.current?.cropper.getCroppedCanvas());
    }
  };
 
  const handleUpdateSlider = (event: Event, zoom: number | number[]) => {
    const newZoomValue = isArray(zoom) ? zoom[0] : zoom;
    handleZoomCanvas(newZoomValue);
  };
 
  return {
    cropperRef,
    handleUpdateSlider,
    getCropData,
    rotate,
    handleZoom,
    zoomValue,
    rotation,
  };
};
 
export default useImageCropper;
 
const normalizeScale = (zoom: number) => {
  const newVal = Math.min(100, Math.max(0, zoom));
  return 1 + newVal / 100;
};