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
JavaScript
'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