UNPKG

@onesy/ui-react

Version:
1,082 lines (1,025 loc) 45.6 kB
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; const _excluded = ["ref", "image", "minWidth", "minHeight", "maxWidth", "maxHeight", "selectorDefault", "selector", "onSelectorChange", "type", "quality", "aspectRatio", "gridLines", "dynamicParent", "onFocus", "onBlur", "TooltipProps", "Component", "className"]; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import React from 'react'; import { is, clamp, isEnvironment } from '@onesy/utils'; import { classNames, style as styleMethod, useOnesyTheme } from '@onesy/style-react'; import TooltipElement from '../Tooltip'; import { staticClassName, image as imageMethod } from '../utils'; import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; const useStyle = styleMethod(theme => { const dot = { display: 'inline-block', position: 'absolute', width: '6px', height: '6px', borderRadius: '50%', background: '#a4a4a4', outline: '1px solid white' }; return { root: { width: '100%', minHeight: '1px', lineHeight: '0', userSelect: 'none', overflow: 'hidden' }, mouseDown_move: { '& *': { cursor: 'grab !important' } }, mouseDown_top: { '& *': { cursor: 'ns-resize !important' } }, mouseDown_left: { '& *': { cursor: 'ew-resize !important' } }, mouseDown_right: { '& *': { cursor: 'ew-resize !important' } }, mouseDown_bottom: { '& *': { cursor: 'ns-resize !important' } }, mouseDown_top_left: { '& *': { cursor: 'nwse-resize !important' } }, mouseDown_top_right: { '& *': { cursor: 'nesw-resize !important' } }, mouseDown_bottom_left: { '& *': { cursor: 'nesw-resize !important' } }, mouseDown_bottom_right: { '& *': { cursor: 'nwse-resize !important' } }, canvas: { position: 'absolute', zIndex: '0' }, canvas_main: { position: 'relative', width: '100%', height: 'auto' }, canvas_imageSelector: { zIndex: -1 }, background: { position: 'absolute', inset: '0', width: '100%', height: '100%', opacity: '0', background: theme.methods.palette.color.colorToRgb(theme.palette.text.default.primary, 44), transition: theme.methods.transitions.make('opacity', { duration: 'xxs' }), zIndex: '1' }, background_in: { opacity: '1' }, imageSelector_main: { position: 'absolute', top: '0', left: '0', width: '0', height: '0', outline: '2px dashed white', background: 'transparent', touchAction: 'none', opacity: '0', zIndex: '14', userSelect: 'none', transition: theme.methods.transitions.make('opacity') }, imageSelector_main_in: { opacity: '1' }, imageSelector: { position: 'absolute', top: '0', left: '0', width: '0', height: '0', touchAction: 'none', overflow: 'hidden', userSelect: 'none', zIndex: '11' }, move: { position: 'absolute', inset: '0', width: '100%', height: '100%', cursor: 'grab', '&:active': { cursor: 'grabbing !important' } }, grid_line: { position: 'absolute', background: 'white', mixBlendMode: 'difference' }, grid_line_top_start: { top: '33.3333%', insetInline: '0', width: '100%', height: '1px' }, grid_line_top_end: { top: '66.6666%', insetInline: '0', width: '100%', height: '1px' }, grid_line_left_start: { left: '33.3333%', insetBlock: '0', width: '1px', height: '100%' }, grid_line_left_end: { left: '66.6666%', insetBlock: '0', width: '1px', height: '100%' }, dot: _objectSpread({}, dot), dot_top_left: { top: '-1px', left: '-1px', transform: 'translate(-50%, -50%)', cursor: 'nwse-resize' }, dot_top_right: { top: '-1px', right: '-1px', transform: 'translate(50%, -50%)', cursor: 'nesw-resize' }, dot_bottom_left: { bottom: '-1px', left: '-1px', transform: 'translate(-50%, 50%)', cursor: 'nesw-resize' }, dot_bottom_right: { bottom: '-1px', right: '-1px', transform: 'translate(50%, 50%)', cursor: 'nwse-resize' }, border: { position: 'absolute' }, border_top: { top: '-2px', height: '2px', width: '100%', cursor: 'ns-resize', '&::before': _objectSpread(_objectSpread({}, dot), {}, { content: '""', top: '50%', left: '50%', transform: 'translate(-50%, -50%)' }) }, border_left: { left: '-2px', height: '100%', width: '2px', cursor: 'ew-resize', '&::before': _objectSpread(_objectSpread({}, dot), {}, { content: '""', top: '50%', left: '50%', transform: 'translate(-50%, -50%)' }) }, border_right: { right: '-2px', height: '100%', width: '2px', cursor: 'ew-resize', '&::before': _objectSpread(_objectSpread({}, dot), {}, { content: '""', top: '50%', right: '50%', transform: 'translate(50%, -50%)' }) }, border_bottom: { bottom: '-2px', height: '2px', width: '100%', cursor: 'ns-resize', '&::before': _objectSpread(_objectSpread({}, dot), {}, { content: '""', bottom: '50%', left: '50%', transform: 'translate(-50%, 50%)' }) } }; }, { name: 'onesy-ImageCrop' }); const ImageCrop = props_ => { const theme = useOnesyTheme(); const props = _objectSpread(_objectSpread(_objectSpread({}, theme?.ui?.elements?.all?.props?.default), theme?.ui?.elements?.onesyImageCrop?.props?.default), props_); const Tooltip = theme?.elements?.Tooltip || TooltipElement; const { ref, // url, datauri or canvas image: image_, minWidth, minHeight, maxWidth, maxHeight, selectorDefault, selector: selector_, onSelectorChange: onSelectorChange_, type = `image/jpeg`, quality = 1, aspectRatio, gridLines, dynamicParent, onFocus: onFocus_, onBlur: onBlur_, TooltipProps, Component = 'div', className } = props, other = _objectWithoutProperties(props, _excluded); const { classes } = useStyle(); const [image, setImage] = React.useState(); const [focus, setFocus] = React.useState(); const [mouseDown, setMouseDown] = React.useState(); const [selector, setSelector] = React.useState(selectorDefault !== undefined ? selectorDefault : selector_); const [selectorRelative, setSelectorRelative] = React.useState(); const refs = { root: React.useRef(null), image: React.useRef(null), mouseDown: React.useRef(null), selector: React.useRef(null), imageSelectorMain: React.useRef(null), imageSelector: React.useRef(null), previousMouseEvent: React.useRef(null), canvasMain: React.useRef(null), canvasImageSelector: React.useRef(null), move: React.useRef(null), borderTop: React.useRef(null), borderLeft: React.useRef(null), borderRight: React.useRef(null), borderBottom: React.useRef(null), dotTopLeft: React.useRef(null), dotTopRight: React.useRef(null), dotBottomLeft: React.useRef(null), dotBottomRight: React.useRef(null), props: React.useRef(null), dynamicParent: React.useRef(null), focus: React.useRef(null), aspectRatio: React.useRef(null) }; refs.image.current = image; refs.mouseDown.current = mouseDown; refs.selector.current = selector; refs.props.current = props; refs.focus.current = focus; refs.dynamicParent.current = dynamicParent; refs.aspectRatio.current = aspectRatio; const onSelectorChange = valueNew => { // min, max for width, height // + resolve it to max width and height for aspect ratio if (is('object', valueNew) && !!Object.keys(valueNew).length && refs.root.current) { const rootRect = refs.root.current?.getBoundingClientRect(); const minWidth_ = refs.props.current.minWidth !== undefined ? refs.props.current.minWidth : Number.MIN_SAFE_INTEGER; const minHeight_ = refs.props.current.minHeight !== undefined ? refs.props.current.minHeight : Number.MIN_SAFE_INTEGER; const maxWidth_ = refs.props.current.maxWidth !== undefined ? refs.props.current.maxWidth : Number.MAX_SAFE_INTEGER; const maxHeight_ = refs.props.current.maxHeight !== undefined ? refs.props.current.maxHeight : Number.MAX_SAFE_INTEGER; valueNew.width = clamp(valueNew.width, minWidth_, maxWidth_); valueNew.height = clamp(valueNew.height, minHeight_, maxHeight_); if (refs.aspectRatio.current !== undefined) { if (valueNew.width + valueNew.width / refs.aspectRatio.current >= valueNew.height + valueNew.height * refs.aspectRatio.current) { valueNew.height = valueNew.width / refs.aspectRatio.current; } else { valueNew.width = valueNew.height * refs.aspectRatio.current; } // Max width if (valueNew.left + valueNew.width > rootRect.width) { valueNew.width = rootRect.width - valueNew.left; valueNew.height = valueNew.width / refs.aspectRatio.current; } // Max height if (valueNew.top + valueNew.height > rootRect.height) { valueNew.height = rootRect.height - valueNew.top; valueNew.width = valueNew.height * refs.aspectRatio.current; } // Max width, height per maxWidth and maxHeight if (valueNew.width < minWidth_ || valueNew.width > maxWidth_) { valueNew.width = clamp(valueNew.width, minWidth_, maxWidth_); valueNew.height = valueNew.width / refs.aspectRatio.current; } if (valueNew.height < minHeight_ || valueNew.height > maxHeight_) { valueNew.height = clamp(valueNew.height, minHeight_, maxHeight_); valueNew.width = valueNew.height / refs.aspectRatio.current; } } // If previous values are within maxWidth and/or maxHeight // and left or top are not same as before // return if (!['move'].includes(refs.mouseDown.current?.version)) { if (maxWidth_ !== undefined || maxHeight_ !== undefined) { if ((valueNew.top < refs.selector.current?.top || valueNew.left < refs.selector.current?.left) && (refs.selector.current?.width === maxWidth_ || refs.selector.current?.height === maxHeight_)) return; } } } const rootRect_ = refs.root.current.getBoundingClientRect(); const selectorRelative_ = { top: valueNew.top / rootRect_?.height * refs.canvasMain.current?.height, left: valueNew.left / rootRect_?.width * refs.canvasMain.current?.width, width: valueNew.width / rootRect_?.width * refs.canvasMain.current?.width, height: valueNew.height / rootRect_?.height * refs.canvasMain.current?.height }; // Update inner or controlled if (!props.hasOwnProperty('selector')) { setSelector(valueNew); setSelectorRelative(selectorRelative_); } if (is('function', onSelectorChange_)) onSelectorChange_(selectorRelative_); }; React.useEffect(() => { const method = event => { switch (event.key) { case 'Escape': if (refs.focus.current) setSelector({}); break; default: break; } }; const onMouseUp = event_0 => { setMouseDown(false); refs.previousMouseEvent.current = undefined; }; // Move const onMove = (x, y) => { if (refs.mouseDown.current && refs.previousMouseEvent.current) { const { top: previousTop, left: previousLeft } = refs.mouseDown.current; const rootRect_0 = refs.root.current.getBoundingClientRect(); const selectorRect_ = refs.imageSelectorMain.current.getBoundingClientRect(); const selectorRect = {}; // Normalize relative to root selectorRect.width = selectorRect_.width; selectorRect.height = selectorRect_.height; selectorRect.top = selectorRect_.top - rootRect_0.top; selectorRect.left = selectorRect_.left - rootRect_0.left; selectorRect.right = selectorRect.left + selectorRect_.width; selectorRect.bottom = selectorRect.top + selectorRect_.height; if (refs.mouseDown.current?.version === 'make') { const top_ = clamp(y - rootRect_0.top, 0, rootRect_0.height); const left_ = clamp(x - rootRect_0.left, 0, rootRect_0.width); let top = clamp(top_, 0, previousTop); let left = clamp(left_, 0, previousLeft); let width = Math.abs(left_ - previousLeft); let height = Math.abs(top_ - previousTop); if (refs.aspectRatio.current !== undefined) { if (left < previousLeft) { if (refs.selector.current?.left < previousLeft && left < refs.selector.current?.left && (top <= 0 || refs.selector.current?.top + refs.selector.current?.height >= rootRect_0.height)) return; } if (top < previousTop) { if (refs.selector.current?.top < previousTop && top < refs.selector.current?.top && (left <= 0 || refs.selector.current?.left + refs.selector.current?.width >= rootRect_0.width)) return; } // Max surface if (width + width / refs.aspectRatio.current >= height + height * refs.aspectRatio.current) { height = width / refs.aspectRatio.current; } else { width = height * refs.aspectRatio.current; } // Moved left if (left < previousLeft) { left = clamp(previousLeft - width, 0, previousLeft); // Update width, height upto the previousLeft width = clamp(width, 0, previousLeft); height = width / refs.aspectRatio.current; } // Moved top if (top < previousTop) { top = clamp(previousTop - height, 0, previousTop); // Update width, height upto the previousTop height = clamp(height, 0, previousTop); width = height * refs.aspectRatio.current; } // Max width if (left + width > rootRect_0.width) { width = rootRect_0.width - left; height = width / refs.aspectRatio.current; } // Max height if (top + height > rootRect_0.height) { height = rootRect_0.height - top; width = height * refs.aspectRatio.current; } // Min left if (left < previousLeft) left = previousLeft - width; // Min top if (top < previousTop) top = previousTop - height; } onSelectorChange(_objectSpread(_objectSpread({}, refs.selector.current), {}, { top, left, width, height })); } else if (refs.mouseDown.current?.version === 'move') { const top_0 = y - refs.previousMouseEvent.current.clientY; const left_0 = x - refs.previousMouseEvent.current.clientX; onSelectorChange(_objectSpread(_objectSpread({}, refs.selector.current), {}, { top: clamp(refs.selector.current.top + top_0, 0, rootRect_0.height - selectorRect.height), left: clamp(refs.selector.current.left + left_0, 0, rootRect_0.width - selectorRect.width) })); } else if (refs.mouseDown.current?.version === 'top_left') { const incY = y - refs.previousMouseEvent.current.clientY; const incX = x - refs.previousMouseEvent.current.clientX; let top_1 = clamp(selectorRect.top + incY, 0); let left_1 = clamp(selectorRect.left + incX, 0); if (selectorRect.bottom - top_1 < 0 && selectorRect.right - left_1 < 0) refs.mouseDown.current.version = 'bottom_right';else if (selectorRect.bottom - top_1 < 0) refs.mouseDown.current.version = 'bottom_left';else if (selectorRect.right - left_1 < 0) refs.mouseDown.current.version = 'top_right'; let width_0 = clamp(selectorRect.right - left_1, 0); let height_0 = clamp(selectorRect.bottom - top_1, 0); if (refs.aspectRatio.current !== undefined) { // Left if (left_1 < refs.selector.current.left && refs.selector.current.left < previousLeft && refs.selector.current?.top === 0) return; // Max surface if (width_0 + width_0 / refs.aspectRatio.current >= height_0 + height_0 * refs.aspectRatio.current) { height_0 = width_0 / refs.aspectRatio.current; } else { width_0 = height_0 * refs.aspectRatio.current; } // Moved left if (left_1 < previousLeft) { left_1 = clamp(previousLeft - width_0, 0, previousLeft); // Update width, height upto the previousLeft width_0 = clamp(width_0, 0, previousLeft); height_0 = width_0 / refs.aspectRatio.current; } // Moved top if (top_1 < previousTop) { top_1 = clamp(previousTop - height_0, 0, previousTop); // Update width, height upto the previousTop height_0 = clamp(height_0, 0, previousTop); width_0 = height_0 * refs.aspectRatio.current; } // Max width if (left_1 + width_0 > rootRect_0.width) { width_0 = rootRect_0.width - left_1; height_0 = width_0 / refs.aspectRatio.current; } // Max height if (top_1 + height_0 > rootRect_0.height) { height_0 = rootRect_0.height - top_1; width_0 = height_0 * refs.aspectRatio.current; } // Min left if (left_1 < previousLeft) left_1 = previousLeft - width_0; // Min top if (top_1 < previousTop) top_1 = previousTop - height_0; } onSelectorChange(_objectSpread(_objectSpread({}, refs.selector.current), {}, { top: top_1, left: left_1, width: width_0, height: height_0 })); } else if (refs.mouseDown.current?.version === 'top_right') { const incY_0 = y - refs.previousMouseEvent.current.clientY; const incX_0 = x - refs.previousMouseEvent.current.clientX; const top_2 = clamp(selectorRect.top + incY_0, 0); if (selectorRect.bottom - top_2 < 0 && selectorRect.width + incX_0 < 0) refs.mouseDown.current.version = 'bottom_left';else if (selectorRect.bottom - top_2 < 0) refs.mouseDown.current.version = 'bottom_right';else if (selectorRect.width + incX_0 < 0) refs.mouseDown.current.version = 'top_left'; let width_1 = clamp(Math.abs(selectorRect.width + incX_0), 0, rootRect_0.width - selectorRect.left); let height_1 = clamp(selectorRect.bottom - top_2, 0); // Top if (refs.aspectRatio.current !== undefined) { // Top if (top_2 < refs.selector.current.top && refs.selector.current.top < previousTop && refs.selector.current.left + refs.selector.current.width >= rootRect_0.width) return; width_1 = height_1 * refs.aspectRatio.current; height_1 = width_1 / refs.aspectRatio.current; // Max width if (refs.selector.current.left + width_1 > rootRect_0.width) { width_1 = rootRect_0.width - refs.selector.current.left; height_1 = width_1 / refs.aspectRatio.current; } // Max height if (refs.selector.current.top + height_1 > rootRect_0.height) { height_1 = rootRect_0.height - refs.selector.current.top; width_1 = height_1 * refs.aspectRatio.current; } } onSelectorChange(_objectSpread(_objectSpread({}, refs.selector.current), {}, { top: top_2, width: width_1, height: height_1 })); } else if (refs.mouseDown.current?.version === 'bottom_right') { const incY_1 = y - refs.previousMouseEvent.current.clientY; const incX_1 = x - refs.previousMouseEvent.current.clientX; if (selectorRect.height + incY_1 < 0 && selectorRect.width + incX_1 < 0) refs.mouseDown.current.version = 'top_left';else if (selectorRect.height + incY_1 < 0) refs.mouseDown.current.version = 'top_right';else if (selectorRect.width + incX_1 < 0) refs.mouseDown.current.version = 'bottom_left'; let width_2 = clamp(Math.abs(selectorRect.width + incX_1), 0, rootRect_0.width - selectorRect.left); let height_2 = clamp(Math.abs(selectorRect.height + incY_1), 0, rootRect_0.height - selectorRect.top); // Right if (refs.aspectRatio.current !== undefined) { height_2 = width_2 / refs.aspectRatio.current; // Max width if (refs.selector.current.left + width_2 > rootRect_0.width) { width_2 = rootRect_0.width - refs.selector.current.left; height_2 = width_2 / refs.aspectRatio.current; } // Max height if (refs.selector.current.top + height_2 > rootRect_0.height) { height_2 = rootRect_0.height - refs.selector.current.top; width_2 = height_2 * refs.aspectRatio.current; } width_2 = height_2 * refs.aspectRatio.current; // Max width if (refs.selector.current.left + width_2 > rootRect_0.width) { width_2 = rootRect_0.width - refs.selector.current.left; height_2 = width_2 / refs.aspectRatio.current; } // Max height if (refs.selector.current.top + height_2 > rootRect_0.height) { height_2 = rootRect_0.height - refs.selector.current.top; width_2 = height_2 * refs.aspectRatio.current; } } onSelectorChange(_objectSpread(_objectSpread({}, refs.selector.current), {}, { width: width_2, height: height_2 })); } else if (refs.mouseDown.current?.version === 'bottom_left') { const incY_2 = y - refs.previousMouseEvent.current.clientY; const incX_2 = x - refs.previousMouseEvent.current.clientX; const left_2 = clamp(selectorRect.left + incX_2, 0); if (selectorRect.height + incY_2 < 0 && selectorRect.right - left_2 < 0) refs.mouseDown.current.version = 'top_right';else if (selectorRect.height + incY_2 < 0) refs.mouseDown.current.version = 'top_left';else if (selectorRect.right - left_2 < 0) refs.mouseDown.current.version = 'bottom_right'; let width_3 = clamp(selectorRect.right - left_2, 0); let height_3 = clamp(Math.abs(selectorRect.height + incY_2), 0, rootRect_0.height - selectorRect.top); // Left if (refs.aspectRatio.current !== undefined) { // Left if (left_2 < refs.selector.current.left && refs.selector.current?.top + refs.selector.current?.height >= rootRect_0.height) return; height_3 = width_3 / refs.aspectRatio.current; // Max width if (refs.selector.current.left + width_3 > rootRect_0.width) { width_3 = rootRect_0.width - refs.selector.current.left; height_3 = width_3 / refs.aspectRatio.current; } // Max height if (refs.selector.current.top + height_3 > rootRect_0.height) { height_3 = rootRect_0.height - refs.selector.current.top; width_3 = height_3 * refs.aspectRatio.current; } width_3 = height_3 * refs.aspectRatio.current; // Max width if (refs.selector.current.left + width_3 > rootRect_0.width) { width_3 = rootRect_0.width - refs.selector.current.left; height_3 = width_3 / refs.aspectRatio.current; } // Max height if (refs.selector.current.top + height_3 > rootRect_0.height) { height_3 = rootRect_0.height - refs.selector.current.top; width_3 = height_3 * refs.aspectRatio.current; } } onSelectorChange(_objectSpread(_objectSpread({}, refs.selector.current), {}, { left: left_2, width: width_3, height: height_3 })); } else if (refs.mouseDown.current?.version === 'top') { const inc = y - refs.previousMouseEvent.current.clientY; const top_3 = clamp(refs.selector.current.top + inc, 0); if (refs.selector.current.top <= 0 && top_3 <= 0) return; if (selectorRect.bottom - top_3 < 0) refs.mouseDown.current.version = 'bottom'; let width_4 = refs.selector.current.width; let height_4 = clamp(Math.abs(refs.selector.current.height - inc), 0, previousTop - top_3); if (refs.aspectRatio.current !== undefined) { // Top if (top_3 < refs.selector.current.top && refs.selector.current.top < previousTop && refs.selector.current.left + refs.selector.current.width >= rootRect_0.width) return; width_4 = height_4 * refs.aspectRatio.current; // Max width if (refs.selector.current.left + width_4 > rootRect_0.width) { width_4 = rootRect_0.width - refs.selector.current.left; height_4 = width_4 / refs.aspectRatio.current; } // Max height if (top_3 + height_4 > rootRect_0.height) { height_4 = rootRect_0.height - top_3; width_4 = height_4 * refs.aspectRatio.current; } } onSelectorChange(_objectSpread(_objectSpread({}, refs.selector.current), {}, { top: top_3, width: width_4, height: height_4 })); } else if (refs.mouseDown.current?.version === 'bottom') { const inc_0 = y - refs.previousMouseEvent.current.clientY; if (selectorRect.height + inc_0 < 0) refs.mouseDown.current.version = 'top'; let width_5 = refs.selector.current.width; let height_5 = clamp(Math.abs(selectorRect.height + inc_0), 0, rootRect_0.height - refs.selector.current.top); if (refs.aspectRatio.current !== undefined) { width_5 = height_5 * refs.aspectRatio.current; // Max height if (refs.selector.current.top + height_5 > rootRect_0.height) { height_5 = rootRect_0.height - refs.selector.current.top; width_5 = height_5 * refs.aspectRatio.current; } // Max width if (refs.selector.current.left + width_5 > rootRect_0.width) { width_5 = rootRect_0.width - refs.selector.current.left; height_5 = width_5 / refs.aspectRatio.current; } } onSelectorChange(_objectSpread(_objectSpread({}, refs.selector.current), {}, { width: width_5, height: height_5 })); } else if (refs.mouseDown.current?.version === 'left') { const inc_1 = x - refs.previousMouseEvent.current.clientX; const left_3 = clamp(selectorRect.left + inc_1, 0); if (selectorRect.right - left_3 < 0) refs.mouseDown.current.version = 'right'; let width_6 = clamp(selectorRect.right - left_3, 0); let height_6 = refs.selector.current.height; if (refs.aspectRatio.current !== undefined) { if (left_3 < refs.selector.current.left && refs.selector.current?.top + refs.selector.current?.height >= rootRect_0.height) return; height_6 = width_6 / refs.aspectRatio.current; // Max width if (refs.selector.current.left + width_6 > rootRect_0.width) { width_6 = rootRect_0.width - refs.selector.current.left; height_6 = width_6 / refs.aspectRatio.current; } // Max height if (refs.selector.current.top + height_6 > rootRect_0.height) { height_6 = rootRect_0.height - refs.selector.current.top; width_6 = height_6 * refs.aspectRatio.current; } } onSelectorChange(_objectSpread(_objectSpread({}, refs.selector.current), {}, { left: left_3, width: width_6, height: height_6 })); } else if (refs.mouseDown.current?.version === 'right') { const inc_2 = x - refs.previousMouseEvent.current.clientX; if (selectorRect.width + inc_2 < 0) refs.mouseDown.current.version = 'left'; let width_7 = clamp(Math.abs(selectorRect.width + inc_2), 0, rootRect_0.width - selectorRect.left); let height_7 = refs.selector.current.height; if (refs.aspectRatio.current !== undefined) { height_7 = width_7 / refs.aspectRatio.current; // Max width if (refs.selector.current.left + width_7 > rootRect_0.width) { width_7 = rootRect_0.width - refs.selector.current.left; height_7 = width_7 / refs.aspectRatio.current; } // Max height if (refs.selector.current.top + height_7 > rootRect_0.height) { height_7 = rootRect_0.height - refs.selector.current.top; width_7 = height_7 * refs.aspectRatio.current; } } onSelectorChange(_objectSpread(_objectSpread({}, refs.selector.current), {}, { width: width_7, height: height_7 })); } } }; // Mouse move const onMouseMove = event_1 => { if (refs.mouseDown.current) { const { clientY, clientX } = event_1; onMove(clientX, clientY); refs.previousMouseEvent.current = event_1; } }; // Touch move const onTouchMove = event_2 => { if (refs.mouseDown.current) { const { clientY: clientY_0, clientX: clientX_0 } = event_2.touches[0]; onMove(clientX_0, clientY_0); refs.previousMouseEvent.current = event_2; // Normalize for use as a mouseDown value refs.previousMouseEvent.current.clientY = clientY_0; refs.previousMouseEvent.current.clientX = clientX_0; } }; const rootDocument = isEnvironment('browser') ? refs.root.current?.ownerDocument || window.document : undefined; rootDocument.addEventListener('keydown', method); rootDocument.addEventListener('mousemove', onMouseMove); rootDocument.addEventListener('mouseup', onMouseUp); rootDocument.addEventListener('touchmove', onTouchMove, { passive: true }); rootDocument.addEventListener('touchend', onMouseUp); return () => { // Clean up rootDocument.removeEventListener('keydown', method); rootDocument.removeEventListener('mousemove', onMouseMove); rootDocument.removeEventListener('mouseup', onMouseUp); rootDocument.removeEventListener('touchmove', onTouchMove); rootDocument.removeEventListener('touchend', onMouseUp); if (refs.image.current) { setImage(''); if (rootDocument.body.style.overflow === 'hidden') rootDocument.body.style.removeProperty('overflow'); } }; }, []); React.useEffect(() => { if (image_ !== image) { if (image_ instanceof HTMLCanvasElement) setImage(image_);else if (is('string', image_)) !refs.dynamicParent.current ? makeImage(image_) : setTimeout(() => makeImage(image_), 140); } }, [image_]); const updateSelector = (selector__ = refs.selector.current, image__ = refs.image.current) => { if (selector__ !== undefined && image__ !== undefined) { const rootRect_1 = refs.root.current.getBoundingClientRect(); const selectorValue = { top: clamp(selector__.top, 0, image__.height), left: clamp(selector__.left, 0, image__.height) }; selectorValue.width = clamp(selector__.width || 0, 0, rootRect_1.width - selectorValue.left); selectorValue.height = clamp(selector__.height || 0, 0, rootRect_1.height - selectorValue.top); // Aspect ratio if (refs.aspectRatio.current !== undefined) { // Max surface if (selectorValue.width + selectorValue.width / refs.aspectRatio.current >= selectorValue.height + selectorValue.height * refs.aspectRatio.current) { selectorValue.height = selectorValue.width / refs.aspectRatio.current; } else { selectorValue.width = selectorValue.height * refs.aspectRatio.current; } // Max width if (selectorValue.left + selectorValue.width > rootRect_1.width) { selectorValue.width = rootRect_1.width - selectorValue.left; selectorValue.height = selectorValue.width / refs.aspectRatio.current; } // Max height if (selectorValue.top + selectorValue.height > rootRect_1.height) { selectorValue.height = rootRect_1.height - selectorValue.top; selectorValue.width = selectorValue.height * refs.aspectRatio.current; } } // Update selector setSelector(selectorValue); // Update selector relative setSelectorRelative({ top: selectorValue.top / rootRect_1?.height * refs.canvasMain.current?.height, left: selectorValue.left / rootRect_1?.width * refs.canvasMain.current?.width, width: selectorValue.width / rootRect_1?.width * refs.canvasMain.current?.width, height: selectorValue.height / rootRect_1?.height * refs.canvasMain.current?.height }); } }; React.useEffect(() => { updateSelector(); }, [aspectRatio]); React.useEffect(() => { if (selector_ !== selector) updateSelector(selector_); }, [selector_]); React.useEffect(() => { if (image) { refs.canvasMain.current.width = image.width; refs.canvasMain.current.height = image.height; refs.canvasMain.current.getContext('2d').drawImage(image, 0, 0), image.width, image.height; refs.canvasImageSelector.current.width = image.width; refs.canvasImageSelector.current.height = image.height; refs.canvasImageSelector.current.getContext('2d').drawImage(image, 0, 0), image.width, image.height; // Update selector updateSelector(); } }, [image]); const makeImage = async (value = image) => { const img = await imageMethod(value); const rootDocument_0 = isEnvironment('browser') ? refs.root.current?.ownerDocument || window.document : undefined; const canvas = rootDocument_0.createElement('canvas'); const rootRect_2 = refs.root.current.getBoundingClientRect(); const aspectRatioImg = img.width / img.height; // width being parent width img.width = rootRect_2.width; // height keep aspect ratio of the img for the height img.height = img.width / aspectRatioImg; canvas.width = img.width; canvas.height = img.height; canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height); setImage(canvas); }; const onFocus = event_3 => { setFocus(true); if (is('function', onFocus_)) onFocus_(event_3); }; const onBlur = event_4 => { setFocus(false); if (is('function', onBlur_)) onBlur_(event_4); }; const onTouchStart = event_5 => { if (![refs.imageSelectorMain.current, refs.imageSelector.current, refs.move.current, refs.borderTop.current, refs.borderLeft.current, refs.borderRight.current, refs.borderBottom.current, refs.dotTopLeft.current, refs.dotTopRight.current, refs.dotBottomLeft.current, refs.dotBottomRight.current].includes(event_5.target)) { const { clientY: clientY_1, clientX: clientX_1 } = event_5.touches[0]; const rootRect_3 = refs.root.current.getBoundingClientRect(); setMouseDown({ version: 'make', top: clientY_1 - rootRect_3.top, left: clientX_1 - rootRect_3.left }); } }; const onMouseDown = event_6 => { if (![refs.imageSelectorMain.current, refs.imageSelector.current, refs.move.current, refs.borderTop.current, refs.borderLeft.current, refs.borderRight.current, refs.borderBottom.current, refs.dotTopLeft.current, refs.dotTopRight.current, refs.dotBottomLeft.current, refs.dotBottomRight.current].includes(event_6.target)) { const { clientY: clientY_2, clientX: clientX_2 } = event_6; const rootRect_4 = refs.root.current.getBoundingClientRect(); setMouseDown({ version: 'make', top: clientY_2 - rootRect_4.top, left: clientX_2 - rootRect_4.left }); } }; const onTouchStartSelector = event_7 => { const { clientY: clientY_3, clientX: clientX_3 } = event_7.touches[0]; const rootRect_5 = refs.root.current.getBoundingClientRect(); setMouseDown({ version: 'move', top: clientY_3 - rootRect_5.top, left: clientX_3 - rootRect_5.left }); }; const onMouseDownSelector = event_8 => { const { clientY: clientY_4, clientX: clientX_4 } = event_8; const rootRect_6 = refs.root.current.getBoundingClientRect(); setMouseDown({ version: 'move', top: clientY_4 - rootRect_6.top, left: clientX_4 - rootRect_6.left }); }; const onTouchStartBorder = version => event_9 => { setMouseDown({ version, top: refs.selector.current?.top + refs.selector.current?.height, left: refs.selector.current?.left + refs.selector.current?.width }); }; const onMouseDownBorder = version_0 => event_10 => { setMouseDown({ version: version_0, top: refs.selector.current?.top + refs.selector.current?.height, left: refs.selector.current?.left + refs.selector.current?.width }); }; const rect = refs.root.current?.getBoundingClientRect(); return /*#__PURE__*/_jsxs(Component, _objectSpread(_objectSpread({ ref: item => { if (ref) { if (is('function', ref)) ref(item);else ref.current = item; } refs.root.current = item; }, tabIndex: 0, onFocus: onFocus, onBlur: onBlur, onTouchStart: onTouchStart, onMouseDown: onMouseDown, className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-root'], className, classes.root]) }, other), {}, { children: [/*#__PURE__*/_jsx("canvas", { ref: refs.canvasMain, className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-canvas', 'onesy-ImageCrop-canvas-main'], classes.canvas, classes.canvas_main]) }), /*#__PURE__*/_jsx("div", { className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-background'], classes.background, image && classes.background_in]) }), /*#__PURE__*/_jsx(Tooltip, _objectSpread(_objectSpread({ open: mouseDown && selector?.width + selector?.height > 0, label: `${Math.round(selectorRelative?.width || 0)} x ${Math.round(selectorRelative?.height || 0)}`, position: "bottom" }, TooltipProps), {}, { children: /*#__PURE__*/_jsxs("div", { ref: refs.imageSelectorMain, className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-image-selector-main'], classes.imageSelector_main, selector && classes.imageSelector_main_in]), style: _objectSpread({}, selector), children: [/*#__PURE__*/_jsx("div", { ref: refs.move, onTouchStart: onTouchStartSelector, onMouseDown: onMouseDownSelector, className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-move'], classes.move]) }), gridLines && /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx("div", { className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-grid-line', 'onesy-ImageCrop-grid-line-top-start'], classes.grid_line, classes.grid_line_top_start]) }), /*#__PURE__*/_jsx("div", { className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-grid-line', 'onesy-ImageCrop-grid-line-top-end'], classes.grid_line, classes.grid_line_top_end]) }), /*#__PURE__*/_jsx("div", { className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-grid-line', 'onesy-ImageCrop-grid-line-left-start'], classes.grid_line, classes.grid_line_left_start]) }), /*#__PURE__*/_jsx("div", { className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-grid-line', 'onesy-ImageCrop-grid-line-left-end'], classes.grid_line, classes.grid_line_left_end]) })] }), /*#__PURE__*/_jsx("div", { ref: refs.dotTopLeft, onTouchStart: onTouchStartBorder('top_left'), onMouseDown: onMouseDownBorder('top_left'), className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-dot', 'onesy-ImageCrop-dot-top-left'], classes.dot, classes.dot_top_left]) }), /*#__PURE__*/_jsx("div", { ref: refs.dotTopRight, onTouchStart: onTouchStartBorder('top_right'), onMouseDown: onMouseDownBorder('top_right'), className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-dot', 'onesy-ImageCrop-dot-top-right'], classes.dot, classes.dot_top_right]) }), /*#__PURE__*/_jsx("div", { ref: refs.dotBottomLeft, onTouchStart: onTouchStartBorder('bottom_left'), onMouseDown: onMouseDownBorder('bottom_left'), className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-dot', 'onesy-ImageCrop-dot-bottom-left'], classes.dot, classes.dot_bottom_left]) }), /*#__PURE__*/_jsx("div", { ref: refs.dotBottomRight, onTouchStart: onTouchStartBorder('bottom_right'), onMouseDown: onMouseDownBorder('bottom_right'), className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-dot', 'onesy-ImageCrop-dot-bottom-right'], classes.dot, classes.dot_bottom_right]) }), /*#__PURE__*/_jsx("div", { ref: refs.borderTop, onTouchStart: onTouchStartBorder('top'), onMouseDown: onMouseDownBorder('top'), className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-border', 'onesy-ImageCrop-border-top'], classes.border, classes.border_top]) }), /*#__PURE__*/_jsx("div", { ref: refs.borderLeft, onTouchStart: onTouchStartBorder('left'), onMouseDown: onMouseDownBorder('left'), className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-border', 'onesy-ImageCrop-border-left'], classes.border, classes.border_left]) }), /*#__PURE__*/_jsx("div", { ref: refs.borderRight, onTouchStart: onTouchStartBorder('right'), onMouseDown: onMouseDownBorder('right'), className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-border', 'onesy-ImageCrop-border-right'], classes.border, classes.border_right]) }), /*#__PURE__*/_jsx("div", { ref: refs.borderBottom, onTouchStart: onTouchStartBorder('bottom'), onMouseDown: onMouseDownBorder('bottom'), className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-border', 'onesy-ImageCrop-border-bottom'], classes.border, classes.border_bottom]) })] }) })), /*#__PURE__*/_jsx("div", { ref: refs.imageSelector, className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-image-selector'], classes.imageSelector]), style: _objectSpread({}, selector), children: /*#__PURE__*/_jsx("canvas", { ref: refs.canvasImageSelector, className: classNames([staticClassName('ImageCrop', theme) && ['onesy-ImageCrop-canvas', 'onesy-ImageCrop-canvas-image-selector'], classes.canvas, classes.canvas_imageSelector]), width: image?.width || 0, height: image?.height || 0, style: { top: `${(selector?.top || 0) * -1}px`, left: `${(selector?.left || 0) * -1}px`, width: rect?.width, height: rect?.height } }) })] })); }; ImageCrop.displayName = 'onesy-ImageCrop'; export default ImageCrop;