UNPKG

react-advanced-cropper

Version:

The react cropper library that gives the possibility to create croppers exactly suited for your website design

1,011 lines (974 loc) 88.5 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var tslib = require('tslib'); var React = require('react'); var advancedCropper = require('advanced-cropper'); var service = require('advanced-cropper/service'); var state = require('advanced-cropper/state'); var cn = require('classnames'); var stencilSize = require('advanced-cropper/extensions/stencil-size'); var defaults = require('advanced-cropper/defaults'); var algorithms = require('advanced-cropper/algorithms'); var image = require('advanced-cropper/image'); var canvas = require('advanced-cropper/canvas'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var cn__default = /*#__PURE__*/_interopDefaultLegacy(cn); function hybridStencilAutoZoomAlgorithm(state$1, settings) { if (service.isInitializedState(state$1)) { var result = state.copyState(state$1); // Checks that coordinates has the same ratio that coordinates: var stencil = { width: 0, height: 0, }; if (service.ratio(result.boundary) > service.ratio(result.coordinates)) { stencil.height = result.boundary.height * 0.8; stencil.width = stencil.height * service.ratio(result.coordinates); } else { stencil.width = result.boundary.width * 0.8; stencil.height = stencil.width * service.ratio(result.coordinates); } // First of all try to resize visible area as much as possible: result.visibleArea = service.applyScale(result.visibleArea, (result.coordinates.width * result.boundary.width) / (result.visibleArea.width * stencil.width)); // Check that visible area doesn't break the area restrictions: var scale = service.fitToSizeRestrictions(result.visibleArea, service.getAreaSizeRestrictions(result, settings)); result.visibleArea = service.applyScale(result.visibleArea, scale); if (scale !== 1) { stencil.height /= scale; stencil.width /= scale; } result.visibleArea = service.applyMove(result.visibleArea, service.diff(service.getCenter(result.coordinates), service.getCenter(result.visibleArea))); // Center stencil in visible area: result.visibleArea = service.moveToPositionRestrictions(result.visibleArea, service.getAreaPositionRestrictions(result, settings)); result.coordinates = service.moveToPositionRestrictions(result.coordinates, service.mergePositionRestrictions(service.coordinatesToPositionRestrictions(result.visibleArea), service.getPositionRestrictions(result, settings))); return result; } return state$1; } function hybridStencilAutoZoom(state, settings, action) { if (action.immediately) { return hybridStencilAutoZoomAlgorithm(state, settings); } return state; } function deprecationWarning(text) { if (process.env.NODE_ENV === 'development') { console.warn("Deprecation warning: ".concat(text)); } } function useDeprecationWarning() { var fired = React.useRef([]); return function (message) { if (fired.current.indexOf(message) === -1) { deprecationWarning(message); fired.current.push(message); } }; } function createCropper(render) { return React.forwardRef(render); } function useFirstMountState() { var isFirst = React.useRef(true); if (isFirst.current) { isFirst.current = false; return true; } return isFirst.current; } var useUpdateEffect = function (effect, deps) { var isFirstMount = useFirstMountState(); React.useEffect(function () { if (!isFirstMount) { return effect(); } }, deps); }; function useStateWithCallback(initialState) { var _a = tslib.__read(React.useState(initialState), 2), state = _a[0], setState = _a[1]; var _b = tslib.__read(React.useState(null), 2), callback = _b[0], setCallback = _b[1]; var previousState = React.useRef(initialState); useUpdateEffect(function () { if (callback) { callback(state, previousState.current); } }, [callback]); return [ state, function (value, callback) { previousState.current = state; setState(value); setCallback(function () { return callback; }); } ]; } var CropperInstance = /** @class */ (function (_super) { tslib.__extends(CropperInstance, _super); function CropperInstance(props, onChange) { var _this = _super.call(this) || this; _this.props = props; _this.notify = onChange; _this.data = { state: null, transitions: false, interactions: advancedCropper.getEmptyInteractions(), }; return _this; } CropperInstance.prototype.getProps = function () { return this.props(); }; CropperInstance.prototype.setData = function (data) { this.data = data; this.notify(); }; CropperInstance.prototype.getData = function () { return this.data; }; return CropperInstance; }(advancedCropper.AbstractCropperInstance)); function useForceRerender() { var _a = tslib.__read(React.useState({}), 2); _a[0]; var setTick = _a[1]; return function () { setTick({}); }; } function usePersistentFunction(props) { var propsRef = React.useRef(props); propsRef.current = props; return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return propsRef.current.apply(propsRef, tslib.__spreadArray([], tslib.__read(args), false)); }; } function useCropperInstance(props) { var rerender = useForceRerender(); var getProps = usePersistentFunction(function () { var _a = props(), settings = _a.settings, parameters = tslib.__rest(_a, ["settings"]); var extendedSettings = tslib.__assign({ imageRestriction: advancedCropper.ImageRestriction.fitArea, transformImage: { adjustStencil: true, } }, settings); var extendedParameters = tslib.__assign({ transitions: true }, parameters); return tslib.__assign({ settings: tslib.__assign(tslib.__assign({}, extendedSettings), advancedCropper.createDefaultSettings(extendedSettings)) }, extendedParameters); }); var cropper = React.useRef(new CropperInstance(getProps, rerender)); return cropper.current; } function useCropperImage(options) { var src = options.src, onLoadingStart = options.onLoadingStart, onLoadingEnd = options.onLoadingEnd, onError = options.onError, onLoad = options.onLoad, crossOrigin = options.crossOrigin, checkOrientation = options.checkOrientation, canvas = options.canvas, unloadTime = options.unloadTime; var _a = tslib.__read(React.useState(null), 2), image = _a[0], setImage = _a[1]; var _b = tslib.__read(React.useState(false), 2), loading = _b[0], setLoading = _b[1]; var _c = tslib.__read(useStateWithCallback(false), 2), loaded = _c[0], setLoaded = _c[1]; var currentSrc = React.useRef(null); React.useEffect(function () { if (currentSrc.current !== src) { currentSrc.current = src || null; setLoaded(false); if (src) { setLoading(true); onLoadingStart === null || onLoadingStart === void 0 ? void 0 : onLoadingStart(); var promises = [ advancedCropper.loadImage(src, { crossOrigin: advancedCropper.isUndefined(crossOrigin) ? canvas : crossOrigin, checkOrientation: checkOrientation, }), ]; if (loaded && unloadTime) { promises.push(advancedCropper.promiseTimeout(unloadTime)); } Promise.all(promises) .then(function (responses) { var _a = tslib.__read(responses, 1), image = _a[0]; if (currentSrc.current === src) { setImage(image); } }) .catch(function () { if (currentSrc.current === src) { onError === null || onError === void 0 ? void 0 : onError(); } }) .finally(function () { if (currentSrc.current === src) { onLoadingEnd === null || onLoadingEnd === void 0 ? void 0 : onLoadingEnd(); setLoading(false); } }); } else { if (unloadTime) { advancedCropper.promiseTimeout(unloadTime).then(function () { if (currentSrc.current === src) { setImage(null); } }); } else { setImage(null); } } } }, [src, image]); React.useEffect(function () { if (image) { setLoaded(true, function () { onLoad === null || onLoad === void 0 ? void 0 : onLoad(image); }); } }, [image]); return { isLoading: function () { return loading; }, isLoaded: function () { return loaded; }, getImage: function () { return image; }, setImage: setImage, }; } var useWindowResize = function (callback) { var callbackRef = React.useRef(callback); var internalCallback = function () { if (callbackRef.current) { callbackRef.current(); } }; React.useEffect(function () { callbackRef.current = callback; }, [callback]); React.useEffect(function () { window.addEventListener('resize', internalCallback); window.addEventListener('orientationchange', internalCallback); return function () { window.removeEventListener('resize', internalCallback); window.removeEventListener('orientationchange', internalCallback); }; }, []); }; function useCropperAutoReconcile(cropper, enabled) { if (enabled === void 0) { enabled = true; } var _a = tslib.__read(React.useState(enabled), 2), active = _a[0], setActive = _a[1]; React.useLayoutEffect(function () { if (active && !cropper.hasInteractions()) { cropper.reconcileState(); } }); return { pause: function () { setActive(false); }, resume: function () { setActive(true); }, }; } function useAbstractCropper(props) { var _this = this; var _a = props(), src = _a.src, onReady = _a.onReady, onError = _a.onError, onUpdate = _a.onUpdate, _b = _a.canvas, canvas = _b === void 0 ? true : _b, _c = _a.unloadTime, unloadTime = _c === void 0 ? 500 : _c, _d = _a.crossOrigin, crossOrigin = _d === void 0 ? true : _d, _e = _a.checkOrientation, checkOrientation = _e === void 0 ? true : _e, _f = _a.autoReconcileState, autoReconcileState = _f === void 0 ? true : _f; var imageRef = React.useRef(null); var boundaryRef = React.useRef(null); var canvasRef = React.useRef(null); var cropperRef = React.useRef(null); var _g = tslib.__read(useStateWithCallback(null), 2), currentImage = _g[0], setCurrentImage = _g[1]; var cropper = useCropperInstance(function () { return (tslib.__assign(tslib.__assign({}, props()), { getInstance: function () { return cropperRef.current; } })); }); var cropperImage = useCropperImage({ src: src, crossOrigin: crossOrigin, checkOrientation: checkOrientation, unloadTime: unloadTime, canvas: canvas, onError: function () { if (cropperRef.current) { onError === null || onError === void 0 ? void 0 : onError(cropperRef.current); } }, }); var autoReconcile = useCropperAutoReconcile(cropper, autoReconcileState); var resetCropper = function () { return tslib.__awaiter(_this, void 0, void 0, function () { var image_1, boundary_1; var _a; return tslib.__generator(this, function (_b) { switch (_b.label) { case 0: if (!boundaryRef.current) return [3 /*break*/, 2]; autoReconcile.pause(); image_1 = cropperImage.getImage(); return [4 /*yield*/, ((_a = boundaryRef.current) === null || _a === void 0 ? void 0 : _a.stretchTo(image_1))]; case 1: boundary_1 = _b.sent(); setCurrentImage(image_1, function () { if (boundary_1 && image_1) { cropper.reset(boundary_1, image_1); } else { cropper.clear(); } }); autoReconcile.resume(); _b.label = 2; case 2: return [2 /*return*/]; } }); }); }; var refreshCropper = function () { return tslib.__awaiter(_this, void 0, void 0, function () { var image, boundary, state; var _a; return tslib.__generator(this, function (_b) { switch (_b.label) { case 0: if (!boundaryRef.current) return [3 /*break*/, 2]; autoReconcile.pause(); image = cropperImage.getImage(); return [4 /*yield*/, ((_a = boundaryRef.current) === null || _a === void 0 ? void 0 : _a.stretchTo(image))]; case 1: boundary = _b.sent(); if (boundary && image) { state = cropper.getState(); if (state) { if (boundary.width !== state.boundary.width || boundary.height !== state.boundary.height) { cropper.setBoundary(boundary); // It's important because, probably, after the boundary reset // the cropper can meet some restrictions that were broken before cropper.reconcileState(); } } else { cropper.reset(boundary, image); } } else { cropper.clear(); } autoReconcile.resume(); _b.label = 2; case 2: return [2 /*return*/]; } }); }); }; var cropperInterface = { reset: function () { return resetCropper(); }, refresh: function () { return refreshCropper(); }, setImage: function (image) { return setCurrentImage(image); }, reconcileState: cropper.reconcileState, moveCoordinates: cropper.moveCoordinates, moveCoordinatesEnd: cropper.moveCoordinatesEnd, resizeCoordinates: cropper.resizeCoordinates, clear: cropper.clear, resizeCoordinatesEnd: cropper.resizeCoordinatesEnd, moveImage: cropper.moveImage, flipImage: cropper.flipImage, zoomImage: cropper.zoomImage, rotateImage: cropper.rotateImage, transformImage: cropper.transformImage, transformImageEnd: cropper.transformImageEnd, setCoordinates: cropper.setCoordinates, setVisibleArea: cropper.setVisibleArea, startTransitions: cropper.startTransitions, setState: cropper.setState, hasInteractions: cropper.hasInteractions, getStencilCoordinates: cropper.getStencilCoordinates, getCoordinates: cropper.getCoordinates, getVisibleArea: cropper.getVisibleArea, getTransforms: cropper.getTransforms, getTransitions: cropper.getTransitions, getInteractions: cropper.getInteractions, getSettings: cropper.getSettings, getState: cropper.getState, getDefaultState: function () { var state = cropper.getState(); var image = cropperImage.getImage(); if (state && image) { return cropper.createDefaultState(state.boundary, image); } else { return null; } }, getCanvas: function (options) { var state = cropper.getState(); if (imageRef.current && canvasRef.current && state) { return canvasRef.current.draw(state, imageRef.current, options); } else { return null; } }, getImage: function () { return currentImage ? tslib.__assign({}, currentImage) : null; }, isLoading: cropperImage.isLoading, isLoaded: cropperImage.isLoaded, }; useWindowResize(function () { refreshCropper(); }); useUpdateEffect(function () { resetCropper(); }, [cropperImage.getImage()]); useUpdateEffect(function () { if (cropperRef.current && currentImage) { onReady === null || onReady === void 0 ? void 0 : onReady(cropperRef.current); } }, [currentImage]); useUpdateEffect(function () { if (cropperRef.current) { onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(cropperRef.current); } }, [cropperImage.isLoaded(), cropperImage.isLoading()]); React.useImperativeHandle(cropperRef, function () { return cropperInterface; }); return { cropper: cropperInterface, refs: { image: imageRef, boundary: boundaryRef, canvas: canvasRef, }, image: currentImage, }; } var StretchableBoundary = React.forwardRef(function (_a, ref) { var className = _a.className, style = _a.style, stretcherClassName = _a.stretcherClassName, contentClassName = _a.contentClassName, _b = _a.stretchAlgorithm, stretchAlgorithm = _b === void 0 ? advancedCropper.stretchCropperBoundary : _b, _c = _a.sizeAlgorithm, sizeAlgorithm = _c === void 0 ? advancedCropper.fillBoundary : _c, children = _a.children; var stretcherRef = React.useRef(null); var boundaryRef = React.useRef(null); React.useImperativeHandle(ref, function () { return ({ reset: function () { var stretcher = stretcherRef.current; if (stretcher) { stretcher.style.height = ''; stretcher.style.width = ''; } }, stretchTo: function (size) { var stretcher = stretcherRef.current; var boundary = boundaryRef.current; if ((size === null || size === void 0 ? void 0 : size.width) && (size === null || size === void 0 ? void 0 : size.height) && stretcher && boundary) { stretchAlgorithm(boundary, stretcher, size); var result = sizeAlgorithm(boundary, size); return Promise.resolve(result.width && result.height ? result : null); } else { if (stretcher) { stretcher.style.height = ''; stretcher.style.width = ''; } return Promise.resolve(null); } }, }); }); return (React__default["default"].createElement("div", { ref: boundaryRef, style: style, className: cn__default["default"]('advanced-cropper-boundary', className) }, React__default["default"].createElement("div", { ref: stretcherRef, className: cn__default["default"](['advanced-cropper-boundary__stretcher', stretcherClassName]) }), React__default["default"].createElement("div", { className: cn__default["default"](['advanced-cropper-boundary__content', contentClassName]) }, children))); }); StretchableBoundary.displayName = 'StretchableBoundary'; var CropperFade = function (_a) { var visible = _a.visible, className = _a.className, style = _a.style, children = _a.children; return (React__default["default"].createElement("div", { style: style, className: cn__default["default"](className, 'advanced-cropper-fade', Boolean(visible) && 'advanced-cropper-fade--visible') }, children)); }; var CropperWrapper = function (_a) { var cropper = _a.cropper, children = _a.children, className = _a.className, style = _a.style; var state = cropper ? cropper.getState() : null; var loaded = cropper ? cropper.isLoaded() : false; return (React__default["default"].createElement("div", { className: cn__default["default"](className, 'advanced-cropper-wrapper'), style: style }, React__default["default"].createElement(CropperFade, { visible: state && loaded, className: 'advanced-cropper-wrapper__fade' }, children))); }; function preventDefault(e) { e.preventDefault(); } var CropperBackgroundImage = React.forwardRef(function (_a, ref) { var className = _a.className, style = _a.style, cropper = _a.cropper, _b = _a.crossOrigin, crossOrigin = _b === void 0 ? true : _b; var state = cropper.getState(); var transitions = cropper.getTransitions(); var image = cropper.getImage(); var transformStyles = image && state ? advancedCropper.getBackgroundStyle(image, state, transitions) : {}; var src = image ? image.src : undefined; return src ? (React__default["default"].createElement("img", { key: src, ref: ref, className: cn__default["default"]('advanced-cropper-background-image', className), src: src, crossOrigin: crossOrigin === true ? 'anonymous' : crossOrigin || undefined, style: tslib.__assign(tslib.__assign({}, transformStyles), style), onMouseDown: preventDefault })) : null; }); CropperBackgroundImage.displayName = 'CropperBackgroundImage'; var CropperCanvas = React.forwardRef(function (_, ref) { var canvasRef = React.useRef(null); var spareCanvasRef = React.useRef(null); React.useImperativeHandle(ref, function () { return ({ draw: function (state, image, options) { if (options === void 0) { options = {}; } if (image && canvasRef.current && spareCanvasRef.current) { return advancedCropper.drawCroppedArea(state, image, canvasRef.current, spareCanvasRef.current, options); } else { return null; } }, }); }); return (React__default["default"].createElement(React__default["default"].Fragment, null, React__default["default"].createElement("canvas", { className: "advanced-cropper-canvas", ref: canvasRef }), React__default["default"].createElement("canvas", { className: "advanced-cropper-canvas", ref: spareCanvasRef }))); }); CropperCanvas.displayName = 'CropperCanvas'; var DraggableElement = /** @class */ (function (_super) { tslib.__extends(DraggableElement, _super); function DraggableElement(props) { var _this = _super.call(this, props) || this; _this.processMove = function (e, newTouches) { var _a; var container = _this.container.current; if (container && _this.touches.length) { var _b = container.getBoundingClientRect(), left = _b.left, top_1 = _b.top; if (_this.touches.length === 1 && newTouches.length === 1) { if (_this.props.onMove) { var movingToAnchor = { left: Math.abs(newTouches[0].clientX - _this.anchor.left - left) < Math.abs(_this.touches[0].clientX - _this.anchor.left - left), top: Math.abs(newTouches[0].clientY - _this.anchor.top - top_1) < Math.abs(_this.touches[0].clientY - _this.anchor.top - top_1), }; var direction = { left: 0, top: 0, }; if (!_this.props.useAnchor || !movingToAnchor.left) { direction.left = newTouches[0].clientX - _this.touches[0].clientX; } if (!_this.props.useAnchor || !movingToAnchor.top) { direction.top = newTouches[0].clientY - _this.touches[0].clientY; } (_a = _this.props) === null || _a === void 0 ? void 0 : _a.onMove(direction, e); _this.touches = tslib.__spreadArray([], tslib.__read(newTouches), false); } } } }; _this.processEnd = function () { var _a = _this.props, onMoveEnd = _a.onMoveEnd, onLeave = _a.onLeave; if (!_this.props.disabled && _this.touches.length) { onMoveEnd === null || onMoveEnd === void 0 ? void 0 : onMoveEnd(); } if (_this.hovered) { onLeave === null || onLeave === void 0 ? void 0 : onLeave(); _this.hovered = false; } _this.touches = []; }; _this.initAnchor = function (touch) { var container = _this.container.current; if (container) { var _a = container.getBoundingClientRect(), left = _a.left, top_2 = _a.top; _this.anchor = { left: touch.clientX - left, top: touch.clientY - top_2, }; } }; _this.onMouseOver = function () { var _a = _this.props, onEnter = _a.onEnter, disabled = _a.disabled; if (!_this.hovered && !disabled) { _this.hovered = true; onEnter === null || onEnter === void 0 ? void 0 : onEnter(); } }; _this.onMouseLeave = function () { var onLeave = _this.props.onLeave; if (_this.hovered && !_this.touches.length) { _this.hovered = false; onLeave === null || onLeave === void 0 ? void 0 : onLeave(); } }; _this.onTouchStart = function (e) { var _a = _this.props, onEnter = _a.onEnter, onMoveStart = _a.onMoveStart, disabled = _a.disabled; if (e.cancelable) { _this.touches = Array.from(e.touches); var shouldStartMove = !disabled && e.touches.length === 1; if (shouldStartMove) { _this.touches = Array.from(e.touches); onMoveStart === null || onMoveStart === void 0 ? void 0 : onMoveStart(); } if (!_this.hovered && !disabled) { _this.hovered = true; onEnter === null || onEnter === void 0 ? void 0 : onEnter(); } if (_this.started || shouldStartMove) { e.preventDefault(); e.stopPropagation(); } } }; _this.onTouchEnd = function () { _this.started = false; _this.processEnd(); }; _this.onTouchMove = function (e) { if (_this.touches.length >= 1) { if (_this.started) { _this.processMove(e, Array.from(e.touches)); e.preventDefault(); e.stopPropagation(); } else if (advancedCropper.distance({ left: _this.touches[0].clientX, top: _this.touches[0].clientY }, { left: e.touches[0].clientX, top: e.touches[0].clientY }) > (_this.props.activationDistance || 0)) { _this.initAnchor({ clientX: e.touches[0].clientX, clientY: e.touches[0].clientY, }); _this.started = true; } } }; _this.onMouseDown = function (e) { var _a = _this.props, onMoveStart = _a.onMoveStart, disabled = _a.disabled; if (!disabled && e.button === 0) { var touch = { clientX: e.clientX, clientY: e.clientY, }; _this.touches = [touch]; _this.initAnchor(touch); e.stopPropagation(); onMoveStart === null || onMoveStart === void 0 ? void 0 : onMoveStart(); } }; _this.onMouseMove = function (e) { if (!_this.props.disabled && _this.touches.length) { _this.processMove(e, [ { clientX: e.clientX, clientY: e.clientY, }, ]); if (e.preventDefault && e.cancelable) { e.preventDefault(); } e.stopPropagation(); } }; _this.onMouseUp = function () { _this.processEnd(); }; _this.touches = []; _this.hovered = false; _this.started = false; _this.anchor = { left: 0, top: 0, }; _this.container = React.createRef(); return _this; } DraggableElement.prototype.componentWillUnmount = function () { window.removeEventListener('mouseup', this.onMouseUp); window.removeEventListener('mousemove', this.onMouseMove); window.removeEventListener('touchmove', this.onTouchMove); window.removeEventListener('touchend', this.onTouchEnd); var container = this.container.current; if (container) { container.removeEventListener('touchstart', this.onTouchStart); container.removeEventListener('mousedown', this.onMouseDown); } }; DraggableElement.prototype.componentDidMount = function () { window.addEventListener('mouseup', this.onMouseUp, { passive: false }); window.addEventListener('mousemove', this.onMouseMove, { passive: false }); window.addEventListener('touchmove', this.onTouchMove, { passive: false }); window.addEventListener('touchend', this.onTouchEnd, { passive: false }); var container = this.container.current; if (container) { // Add event listeners here due to https://github.com/facebook/react/issues/9809#issuecomment-414072263 container.addEventListener('touchstart', this.onTouchStart, { passive: false, }); container.addEventListener('mousedown', this.onMouseDown, { passive: false, }); } }; DraggableElement.prototype.componentDidUpdate = function (prevProps) { if (this.props.disabled && !prevProps.disabled) { this.touches = []; } }; DraggableElement.prototype.render = function () { var _a = this.props, children = _a.children, className = _a.className; return (React__default["default"].createElement("div", { className: cn__default["default"]('advanced-cropper-draggable-element', className), ref: this.container, onMouseOver: this.onMouseOver, onMouseLeave: this.onMouseLeave }, children)); }; DraggableElement.defaultProps = { disabled: false, activationDistance: 30, useAnchor: true, rerender: true, }; return DraggableElement; }(React.Component)); var LineWrapper = function (_a) { var position = _a.position, className = _a.className, disabled = _a.disabled, onDrag = _a.onDrag, onDragEnd = _a.onDragEnd, onLeave = _a.onLeave, onEnter = _a.onEnter, children = _a.children; return (React__default["default"].createElement(DraggableElement, { className: cn__default["default"]([ 'advanced-cropper-line-wrapper', position && "advanced-cropper-line-wrapper--".concat(position), disabled && "advanced-cropper-line-wrapper--disabled", className, ]), disabled: disabled, onMove: onDrag, onMoveEnd: onDragEnd, onLeave: onLeave, onEnter: onEnter, activationDistance: 0 }, React__default["default"].createElement("div", { className: cn__default["default"]([ 'advanced-cropper-line-wrapper__content', position && "advanced-cropper-line-wrapper__content--".concat(position), ]) }, children))); }; var SimpleLine = function (_a) { var _b, _c; var position = _a.position, hoverClassName = _a.hoverClassName, wrapperClassName = _a.wrapperClassName, defaultClassName = _a.defaultClassName, disabled = _a.disabled, onMove = _a.onMove, onMoveEnd = _a.onMoveEnd; var _d = tslib.__read(React.useState(false), 2), hover = _d[0], setHover = _d[1]; var onEnter = function () { setHover(true); }; var onLeave = function () { setHover(false); }; return (React__default["default"].createElement(LineWrapper, { className: cn__default["default"]('advanced-cropper-simple-line-wrapper', wrapperClassName, (_b = {}, _b["advanced-cropper-simple-line-wrapper--".concat(position)] = !!position, _b)), position: position, disabled: disabled, onDrag: onMove, onDragEnd: onMoveEnd, onLeave: onLeave, onEnter: onEnter }, React__default["default"].createElement("div", { className: cn__default["default"]('advanced-cropper-simple-line', hover && 'advanced-cropper-simple-line--hover', defaultClassName, hover && hoverClassName, (_c = {}, _c["advanced-cropper-simple-line--".concat(position)] = !!position, _c)) }))); }; var HandlerWrapper = function (_a) { var horizontalPosition = _a.horizontalPosition, verticalPosition = _a.verticalPosition, className = _a.className, disabled = _a.disabled, onDrag = _a.onDrag, onDragEnd = _a.onDragEnd, onLeave = _a.onLeave, onEnter = _a.onEnter, children = _a.children, style = _a.style; var position = horizontalPosition || verticalPosition ? advancedCropper.getDirectionNames(horizontalPosition, verticalPosition).snakeCase : null; return (React__default["default"].createElement("div", { style: style, className: cn__default["default"](className, 'advanced-cropper-handler-wrapper', position && "advanced-cropper-handler-wrapper--".concat(position), disabled && 'advanced-cropper-handler-wrapper--disabled') }, React__default["default"].createElement(DraggableElement, { className: 'advanced-cropper-handler-wrapper__draggable', disabled: disabled, onMove: onDrag, onMoveEnd: onDragEnd, onLeave: onLeave, onEnter: onEnter, activationDistance: 0 }, children))); }; var SimpleHandler = function (_a) { var _b; var verticalPosition = _a.verticalPosition, horizontalPosition = _a.horizontalPosition, hoverClassName = _a.hoverClassName, wrapperClassName = _a.wrapperClassName, defaultClassName = _a.defaultClassName, wrapperStyle = _a.wrapperStyle, disabled = _a.disabled, onMove = _a.onMove, onMoveEnd = _a.onMoveEnd; var _c = tslib.__read(React.useState(false), 2), hover = _c[0], setHover = _c[1]; var onEnter = function () { setHover(true); }; var onLeave = function () { setHover(false); }; return (React__default["default"].createElement(HandlerWrapper, { style: wrapperStyle, className: cn__default["default"]('advanced-cropper-simple-handler-wrapper', wrapperClassName, verticalPosition && "advanced-cropper-simple-handler-wrapper--".concat(verticalPosition), horizontalPosition && "advanced-cropper-simple-handler-wrapper--".concat(horizontalPosition), horizontalPosition && verticalPosition && "advanced-cropper-simple-handler-wrapper--".concat(horizontalPosition, "-").concat(verticalPosition), hover && 'advanced-cropper-simple-handler-wrapper--hover'), verticalPosition: verticalPosition, horizontalPosition: horizontalPosition, disabled: disabled, onDrag: onMove, onDragEnd: onMoveEnd, onLeave: onLeave, onEnter: onEnter }, React__default["default"].createElement("div", { className: cn__default["default"]('advanced-cropper-simple-handler', hover && 'advanced-cropper-simple-handler--hover', defaultClassName, hover && hoverClassName, (_b = {}, _b["advanced-cropper-simple-handler--".concat(verticalPosition)] = !!verticalPosition, _b["advanced-cropper-simple-handler--".concat(horizontalPosition)] = !!horizontalPosition, _b["advanced-cropper-simple-handler--".concat(horizontalPosition, "-").concat(verticalPosition)] = horizontalPosition && verticalPosition, _b)) }))); }; var HORIZONTAL_DIRECTIONS = ['east', 'west', null]; var VERTICAL_DIRECTIONS = ['south', 'north', null]; var BoundingBox = function (_a) { var style = _a.style, className = _a.className, children = _a.children, onResize = _a.onResize, onResizeEnd = _a.onResizeEnd, _b = _a.handlerComponent, handlerComponent = _b === void 0 ? SimpleHandler : _b, _c = _a.handlers, handlers = _c === void 0 ? { eastNorth: true, north: true, westNorth: true, west: true, westSouth: true, south: true, eastSouth: true, east: true, } : _c, _d = _a.handlerClassNames, handlerClassNames = _d === void 0 ? {} : _d, _e = _a.handlerWrapperClassNames, handlerWrapperClassNames = _e === void 0 ? {} : _e, _f = _a.lines, lines = _f === void 0 ? { west: true, north: true, east: true, south: true, } : _f, _g = _a.lineComponent, lineComponent = _g === void 0 ? SimpleLine : _g, _h = _a.lineClassNames, lineClassNames = _h === void 0 ? {} : _h, _j = _a.lineWrapperClassNames, lineWrapperClassNames = _j === void 0 ? {} : _j, _k = _a.disabled, disabled = _k === void 0 ? false : _k, _l = _a.reference, reference = _l === void 0 ? null : _l; var _m = tslib.__read(React.useState(null), 2), lastReference = _m[0], setLastReference = _m[1]; var points = React.useMemo(function () { var result = []; HORIZONTAL_DIRECTIONS.forEach(function (hDirection) { VERTICAL_DIRECTIONS.forEach(function (vDirection) { if (hDirection !== vDirection) { var _a = advancedCropper.getDirectionNames(hDirection, vDirection), snakeCase = _a.snakeCase, camelCase = _a.camelCase; if (snakeCase && camelCase) { result.push({ name: camelCase, className: snakeCase, verticalPosition: vDirection, horizontalPosition: hDirection, }); } } }); }); return result; }, []); var lineNodes = React.useMemo(function () { var result = []; points.forEach(function (point) { if (advancedCropper.isCardinalDirection(point.name) && (advancedCropper.isObject(lines) ? lines[point.name] : lines)) { result.push({ name: point.name, component: lineComponent, className: cn__default["default"](lineClassNames.default, lineClassNames[point.name], disabled && lineClassNames.disabled), wrapperClassName: cn__default["default"]("advanced-cropper-bounding-box__line", "advanced-cropper-bounding-box__line--".concat(point.name), lineWrapperClassNames.default, lineWrapperClassNames[point.name], disabled && lineWrapperClassNames.disabled), hoverClassName: lineClassNames.hover, verticalPosition: point.verticalPosition, horizontalPosition: point.horizontalPosition, disabled: disabled, }); } }); return result; }, [points, lines, lineComponent, lineClassNames, lineWrapperClassNames, disabled]); var handlerNodes = React.useMemo(function () { var result = []; points.forEach(function (point) { if (advancedCropper.isObject(handlers) ? handlers[point.name] : handlers) { result.push({ name: point.name, component: handlerComponent, className: cn__default["default"](handlerClassNames.default, handlerClassNames[point.name]), containerClassName: cn__default["default"]("advanced-cropper-bounding-box__handler-wrapper", "advanced-cropper-bounding-box__handler-wrapper--".concat(point.className)), wrapperClassName: cn__default["default"]("advanced-cropper-bounding-box__handler", "advanced-cropper-bounding-box__handler--".concat(point.className), handlerWrapperClassNames.default, handlerWrapperClassNames[point.name]), hoverClassName: handlerClassNames.hover, verticalPosition: point.verticalPosition, horizontalPosition: point.horizontalPosition, disabled: disabled, }); } }); return result; }, [points, handlers, handlerComponent, handlerClassNames, handlerWrapperClassNames, disabled]); var onHandlerMove = function (horizontalPosition, verticalPosition) { return function (_a, nativeEvent) { var left = _a.left, top = _a.top; var directions = { left: left, top: top, }; var respectDirection; if (!verticalPosition && horizontalPosition) { respectDirection = 'width'; } else if (verticalPosition && !horizontalPosition) { respectDirection = 'height'; } if (!disabled) { if (onResize) { var anchor = advancedCropper.getDirectionNames(horizontalPosition, verticalPosition).camelCase; if (anchor) { onResize(anchor, directions, { reference: lastReference || reference, preserveAspectRatio: nativeEvent && nativeEvent.shiftKey, respectDirection: respectDirection, compensate: true, }); } } if (!lastReference) { setLastReference(reference); } } }; }; var onHandlerMoveEnd = function () { onResizeEnd === null || onResizeEnd === void 0 ? void 0 : onResizeEnd(); setLastReference(null); }; return (React__default["default"].createElement("div", { className: cn__default["default"]('advanced-cropper-bounding-box', className), style: style }, children, React__default["default"].createElement("div", null, lineNodes.map(function (line) { return (React__default["default"].createElement(line.component, { key: line.name, defaultClassName: line.className, hoverClassName: line.hoverClassName, wrapperClassName: line.wrapperClassName, position: line.name, disabled: line.disabled, onMove: onHandlerMove(line.horizontalPosition, line.verticalPosition), onMoveEnd: onHandlerMoveEnd })); })), React__default["default"].createElement("div", null, handlerNodes.map(function (handler) { var handlerElement = (React__default["default"].createElement(handler.component, { defaultClassName: handler.className, hoverClassName: handler.hoverClassName, wrapperClassName: handler.wrapperClassName, horizontalPosition: handler.horizontalPosition, verticalPosition: handler.verticalPosition, disabled: handler.disabled, onMove: onHandlerMove(handler.horizontalPosition, handler.verticalPosition), onMoveEnd: onHandlerMoveEnd })); return (React__default["default"].createElement("div", { key: handler.name, className: handler.containerClassName }, handlerElement)); })))); }; var StencilOverlay = function (_a) { var className = _a.className, children = _a.children; return React__default["default"].createElement("div", { className: cn__default["default"]('advanced-cropper-stencil-overlay', className) }, children); }; function useTransition(transitions) { if (transitions === void 0) { transitions = null; } var animation = React.useRef(new advancedCropper.Animation()); var _a = tslib.__read(React.useState(false), 2), active = _a[0], setActive = _a[1]; return [ function (callback) { if (transitions && transitions.active) { animation.current.start(tslib.__assign(tslib.__assign({}, transitions), { onStart: function () { setActive(true); }, onProgress: function (progress) { callback(progress); }, onStop: function () { setActive(false); } })); } else if (!animation.current.active) { callback(1); } }, active, ]; } var ArtificialTransition = function (_a) { var className = _a.className, transitions = _a.transitions, children = _a.children, values = tslib.__rest(_a, ["className", "transitions", "children"]); var root = React.useRef(null); var transitionValues = React.useRef(values); var _b = tslib.__read(React.useState(values), 2), rememberedValues = _b[0], setRememberedValues = _b[1]; var _c = tslib.__read(useTransition(transitions), 2), runTransitions = _c[0], transitionsActive = _c[1]; React.useLayoutEffect(function () { if (!advancedCropper.deepCompare(rememberedValues, values)) { setRememberedValues(values); var startValues_1 = transitionsActive ? tslib.__assign({}, transitionValues.current) : rememberedValues; runTransitions(function (progress) { var properties = ['left', 'top', 'height', 'width']; properties.forEach(function (property) { var desiredValue = values[property]; var startValue = startValues_1[property]; transitionValues.current[property] = advancedCropper.isNumber(startValue) && advancedCropper.isNumber(desiredValue) ? startValue + (desiredValue - startValue) * progress : desiredValue; }); if (root.current) { root.current.style.width = "".concat(transitionValues.current.width, "px"); root.current.style.height = "".concat(transitionValues.current.height, "px"); root.current.style.transform = "translate3d(".concat(transitionValues.current.left, "px, ").concat(transitionValues.current.top, "px, 0px)"); } }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [rememberedValues, transitionsActive, values.width, values.height, values.top, values.left]); var currentValues = transitionsActive ? transitionValues.current : values; var rootStyle = { left: 0, top: 0, width: "".concat(currentValues.width, "px"), height: "".concat(currentValues.height, "px"), transform: "translate3d(".concat(currentValues.left, "px, ").concat(currentValues.top, "px, 0px)"), }; return (React__default["default"].createElement("div", { ref: root, className: cn__default["default"]('advanced-cropper-artificial-transition', className), style: rootStyle }, children)); }; var StencilWrapper = function (_a) { var className = _a.className, transitions = _a.transitions, width = _a.width, height = _a.height, left = _a.left, top = _a.top, children = _a.children; return (React__default["default"].createElement(ArtificialTransition, { className: cn__default["default"]('advanced-cropper-stencil-wrapper', className), transitions: transitions, width: width, height: height, top: top, left: left }, children)); }; var StencilGrid = function (_a) { var _b = _a.columns, columns = _b === void 0 ? 3 : _b, _c = _a.rows, rows = _c === void 0 ? 3 : _c, _d = _a.visible, visible = _d === void 0 ? false : _d, className = _a.className; var nodes = []; var _e = tslib.__read(React.useState(columns), 2), currentColumns = _e[0], setCurrentColumns = _e[1]; var _f = tslib.__read(React.useState(rows), 2), currentRows = _f[0], setCurrentRows = _f[1]; useUpdateEffect(function () { if (visible) { setCurrentRows(rows); setCurrentColumns(columns); } }, [visible, columns, rows]); for (var i = 0; i < currentRows; i++) { var cells = []; for (var j = 0; j < currentColumns; j++) { cells.push(React__default["default"].createElement("div", { key: j, className: cn__default["default"]('advanced-cropper-stencil-grid__cell', i === 0 && 'advanced-cropper-stencil-grid__cell--top', i === currentRows - 1 && 'advanced-cropper-stencil-grid__cell--bottom', j === 0 && 'advanced-cropper-stencil-grid__cell--left', j === currentColumns - 1 && 'advanced-cropper-stencil-grid__cell--right') })); } nodes.push(React__default["default"].createElement("div", { key: i, className: 'advanced-cropper-stencil-grid__row' }, cells)); } return (React__default["default"].createElement("div", { className: cn__default["default"]('advanced-cropper-stencil-grid', visible && 'advanced-cropper-stencil-grid--visible', className) }, nodes)); }; var RectangleStencil = React.forwardRef(function (_a, ref) { var cropper = _a.cropper, coor