@brizy/ui
Version:
React elements in Brizy style
63 lines (62 loc) • 3.73 kB
JavaScript
import { classNames } from "../classNamesFn";
import React, { useCallback, useEffect, useMemo, useRef, useState, } from "react";
import Draggable from "react-draggable";
import { Loading } from "..";
import { getSizeProperties } from "./utils";
import { BRZ_PREFIX } from "../constants";
import { useTranslation } from "../utils/localization/useTranslation";
export const ImagePointer = ({ value, src, errorMessage, size = "middle", maxBy = "both", onChange, onError, }) => {
const { t } = useTranslation();
const [imageWidth, setImageWidth] = useState(0);
const [imageHeight, setImageHeight] = useState(0);
const fromPercentageToPosition = useMemo(() => ({
x: (imageWidth * value.x) / 100,
y: (imageHeight * value.y) / 100,
}), [imageHeight, imageWidth, value]);
const [position, setPosition] = useState(fromPercentageToPosition);
const [isError, setIsError] = useState(false);
const node = useRef(null);
const draggable = useRef(null);
const handleChange = useCallback(({ x, y }) => {
const xPercentage = x / (imageWidth / 100);
const yPercentage = y / (imageHeight / 100);
const xResult = xPercentage < 0 ? 0 : xPercentage > 100 ? 100 : xPercentage;
const yResult = yPercentage < 0 ? 0 : yPercentage > 100 ? 100 : yPercentage;
onChange === null || onChange === void 0 ? void 0 : onChange({ x: xResult, y: yResult });
}, [imageHeight, imageWidth, onChange]);
const onStop = useCallback(() => {
handleChange(position);
}, [handleChange, position]);
const handleDrag = useCallback((_, data) => {
setPosition(pos => ({ x: pos.x + data.deltaX, y: pos.y + data.deltaY }));
}, [setPosition]);
const _onClick = useCallback((event) => {
if (node.current) {
const nodeRect = node.current.getBoundingClientRect();
handleChange({ x: event.clientX - nodeRect.x, y: event.clientY - nodeRect.y });
}
}, [handleChange, node]);
const handleLoad = useCallback((e) => {
const el = e.target;
setImageWidth(el.clientWidth);
setImageHeight(el.clientHeight);
}, [setImageWidth, setImageHeight]);
const handleError = useCallback(() => {
setIsError(true);
onError === null || onError === void 0 ? void 0 : onError();
}, [setIsError, onError]);
const className = classNames()("image-pointer__container", {
"image-pointer__hidden": !imageHeight && !imageWidth && !isError,
});
useEffect(() => {
setPosition(fromPercentageToPosition);
}, [setPosition, fromPercentageToPosition]);
return (React.createElement("div", { className: `${BRZ_PREFIX}-image-pointer`, style: getSizeProperties({ size, maxBy }) }, isError ? (React.createElement("div", { className: `${BRZ_PREFIX}-image-pointer__error` }, errorMessage !== null && errorMessage !== void 0 ? errorMessage : t("Upload image error"))) : (React.createElement(React.Fragment, null,
!imageHeight && !imageWidth && (React.createElement("div", { className: `${BRZ_PREFIX}-image-pointer__loading-container` },
React.createElement(Loading, null))),
React.createElement("div", { className: className, ref: node, onClick: _onClick },
React.createElement(Draggable, { bounds: "parent", nodeRef: draggable, position: fromPercentageToPosition, onDrag: handleDrag, onStop: onStop },
React.createElement("div", { className: `${BRZ_PREFIX}-image-pointer__draggable`, ref: draggable })),
React.createElement("div", { className: `${BRZ_PREFIX}-image-pointer__children` },
React.createElement("img", { onError: handleError, onLoad: handleLoad, src: src })))))));
};