(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@alyle/ui'), require('rxjs'), require('rxjs/operators'), require('@angular/cdk/platform'), require('@angular/common'), require('@angular/cdk/scrolling')) :
    typeof define === 'function' && define.amd ? define('@alyle/ui/image-cropper', ['exports', '@angular/core', '@alyle/ui', 'rxjs', 'rxjs/operators', '@angular/cdk/platform', '@angular/common', '@angular/cdk/scrolling'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.ly = global.ly || {}, global.ly['image-Cropper'] = {}), global.ng.core, global.ly.core, global.rxjs, global.rxjs.operators, global.ng.cdk.platform, global.ng.common, global.ng.cdk.scrolling));
}(this, (function (exports, core, ui, rxjs, operators, platform, common, scrolling) { 'use strict';

    /*
     * Hermite resize - fast image resize/resample using Hermite filter.
     * https://github.com/viliusle/Hermite-resize
     */
    function resizeCanvas(canvas, width, height) {
        var width_source = canvas.width;
        var height_source = canvas.height;
        width = Math.round(width);
        height = Math.round(height);
        var ratio_w = width_source / width;
        var ratio_h = height_source / height;
        var ratio_w_half = Math.ceil(ratio_w / 2);
        var ratio_h_half = Math.ceil(ratio_h / 2);
        var ctx = canvas.getContext('2d');
        var img = ctx.getImageData(0, 0, width_source, height_source);
        var img2 = ctx.createImageData(width, height);
        var data = img.data;
        var data2 = img2.data;
        for (var j = 0; j < height; j++) {
            for (var i = 0; i < width; i++) {
                var x2 = (i + j * width) * 4;
                var weight = 0;
                var weights = 0;
                var weights_alpha = 0;
                var gx_r = 0;
                var gx_g = 0;
                var gx_b = 0;
                var gx_a = 0;
                var center_y = j * ratio_h;
                var xx_start = Math.floor(i * ratio_w);
                var xx_stop = Math.ceil((i + 1) * ratio_w);
                var yy_start = Math.floor(j * ratio_h);
                var yy_stop = Math.ceil((j + 1) * ratio_h);
                xx_stop = Math.min(xx_stop, width_source);
                yy_stop = Math.min(yy_stop, height_source);
                for (var yy = yy_start; yy < yy_stop; yy++) {
                    var dy = Math.abs(center_y - yy) / ratio_h_half;
                    var center_x = i * ratio_w;
                    var w0 = dy * dy; // pre-calc part of w
                    for (var xx = xx_start; xx < xx_stop; xx++) {
                        var dx = Math.abs(center_x - xx) / ratio_w_half;
                        var w = Math.sqrt(w0 + dx * dx);
                        if (w >= 1) {
                            // pixel too far
                            continue;
                        }
                        // hermite filter
                        weight = 2 * w * w * w - 3 * w * w + 1;
                        var pos_x = 4 * (xx + yy * width_source);
                        // alpha
                        gx_a += weight * data[pos_x + 3];
                        weights_alpha += weight;
                        // colors
                        if (data[pos_x + 3] < 255) {
                            weight = weight * data[pos_x + 3] / 250;
                        }
                        gx_r += weight * data[pos_x];
                        gx_g += weight * data[pos_x + 1];
                        gx_b += weight * data[pos_x + 2];
                        weights += weight;
                    }
                }
                data2[x2] = gx_r / weights;
                data2[x2 + 1] = gx_g / weights;
                data2[x2 + 2] = gx_b / weights;
                data2[x2 + 3] = gx_a / weights_alpha;
            }
        }
        // clear and resize canvas
        canvas.width = width;
        canvas.height = height;
        // draw
        ctx.putImageData(img2, 0, 0);
        return ctx;
    }

    var activeEventOptions$1 = platform.normalizePassiveListenerOptions({ passive: false });
    var STYLE_PRIORITY = -2;
    var STYLES = function (theme, ref) {
        var cropper = ref.selectorsOf(STYLES);
        var after = theme.after;
        return {
            $name: LyImageCropper.и,
            $priority: STYLE_PRIORITY,
            root: function () { return function (className) { return className + "{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;overflow:hidden;position:relative;justify-content:center;align-items:center;}" + ui.st2c(((theme.cropper
                && theme.cropper.root
                && (theme.cropper.root instanceof ui.StyleCollection
                    ? theme.cropper.root.setTransformer(function (fn) { return fn(cropper); })
                    : theme.cropper.root(cropper)))), "" + className); }; },
            imgContainer: function (className) { return className + "{cursor:move;position:absolute;top:0;left:0;display:flex;touch-action:none;}" + className + " > canvas{display:block;}"; },
            overlay: function (className) { return "" + ui.st2c((ui.LY_COMMON_STYLES.fill), "" + className); },
            area: function (className) { return className + "{pointer-events:none;box-shadow:0 0 0 20000px rgba(0, 0, 0, 0.4);margin:auto;}" + ui.st2c((ui.LY_COMMON_STYLES.fill), "" + className) + ui.st2c((ui.LY_COMMON_STYLES.fill), className + ":before," + className + ":after") + className + ":before," + className + ":after{content:'';}" + className + ":before{width:0;height:0;margin:auto;border-radius:50%;background:#fff;border:solid 2px rgb(255, 255, 255);}" + className + ":after{border:solid 2px rgb(255, 255, 255);border-radius:inherit;}"; },
            resizer: function (className) { return className + "{width:10px;height:10px;background:#fff;border-radius:3px;position:absolute;touch-action:none;bottom:0;" + after + ":0;pointer-events:all;cursor:" + (after === 'right'
                ? 'nwse-resize'
                : 'nesw-resize') + ";}" + ui.st2c((ui.LY_COMMON_STYLES.fill), className + ":before") + className + ":before{content:'';width:20px;height:20px;transform:translate(-25%, -25%);}"; },
            defaultContent: function (className) { return className + "{display:flex;align-items:center;justify-content:center;}" + ui.st2c((ui.LY_COMMON_STYLES.fill), className + "," + className + " > input") + className + " *:not(input){pointer-events:none;}" + className + " > input{background:transparent;opacity:0;width:100%;height:100%;}"; }
        };
    };
    /** Image Cropper Config */
    var ImgCropperConfig = /** @class */ (function () {
        function ImgCropperConfig() {
            /** Cropper area width */
            this.width = 250;
            /** Cropper area height */
            this.height = 200;
            this.minWidth = 40;
            this.minHeight = 40;
            /**
             * Set anti-aliased (default: true)
             * @deprecated this is not necessary as the cropper will automatically resize the image
             * to the best quality
             */
            this.antiAliased = true;
            this.output = exports.ImgResolution.Default;
        }
        return ImgCropperConfig;
    }());
    /** Image output */
    exports.ImgResolution = void 0;
    (function (ImgResolution) {
        /**
         * The output image will be equal to the initial size of the cropper area.
         */
        ImgResolution[ImgResolution["Default"] = 0] = "Default";
        /** Just crop the image without resizing */
        ImgResolution[ImgResolution["OriginalImage"] = 1] = "OriginalImage";
    })(exports.ImgResolution || (exports.ImgResolution = {}));
    /** Image output */
    exports.ImgCropperError = void 0;
    (function (ImgCropperError) {
        /** The loaded image exceeds the size limit set. */
        ImgCropperError[ImgCropperError["Size"] = 0] = "Size";
        /** The file loaded is not image. */
        ImgCropperError[ImgCropperError["Type"] = 1] = "Type";
        /** When the image has not been loaded. */
        ImgCropperError[ImgCropperError["Other"] = 2] = "Other";
    })(exports.ImgCropperError || (exports.ImgCropperError = {}));
    var LyImageCropper = /** @class */ (function () {
        function LyImageCropper(sRenderer, _renderer, _elementRef, cd, _ngZone, _document, viewPortRuler) {
            var _this = this;
            this.sRenderer = sRenderer;
            this._renderer = _renderer;
            this._elementRef = _elementRef;
            this.cd = cd;
            this._ngZone = _ngZone;
            /**
             * styles
             * @docs-private
             */
            this.classes = this.sRenderer.renderSheet(STYLES, true);
            this._imgRect = {};
            this._rotation = 0;
            this.scaleChange = new core.EventEmitter();
            /** Emits minimum supported image scale */
            this.minScaleChange = new core.EventEmitter();
            /** Emits maximum supported image scale */
            this.maxScaleChange = new core.EventEmitter();
            /** @deprecated Emits when the image is loaded, instead use `ready` */
            this.loaded = new core.EventEmitter();
            /** Emits when the image is loaded */
            this.imageLoaded = new core.EventEmitter();
            /** Emits when the cropper is ready to be interacted */
            this.ready = new core.EventEmitter();
            /** On crop new image */
            this.cropped = new core.EventEmitter();
            /** Emits when the cropper is cleaned */
            this.cleaned = new core.EventEmitter();
            /** Emit an error when the loaded image is not valid */
            // tslint:disable-next-line: no-output-native
            this.error = new core.EventEmitter();
            /** Emits whenever the component is destroyed. */
            this._destroy = new rxjs.Subject();
            this._pointerDown = function (event) {
                // Don't do anything if the
                // user is using anything other than the main mouse button.
                if (_this._isSliding || (!isTouchEvent$1(event) && event.button !== 0)) {
                    return;
                }
                _this._ngZone.run(function () {
                    _this._isSliding = true;
                    _this.offset = {
                        x: _this._imgRect.x,
                        y: _this._imgRect.y,
                        left: _this._imgRect.xc,
                        top: _this._imgRect.yc
                    };
                    _this._lastPointerEvent = event;
                    _this._startPointerEvent = getGesturePointFromEvent$1(event);
                    event.preventDefault();
                    _this._bindGlobalEvents(event);
                });
            };
            /**
             * Called when the user has moved their pointer after
             * starting to drag.
             */
            this._pointerMove = function (event) {
                if (_this._isSliding) {
                    event.preventDefault();
                    _this._lastPointerEvent = event;
                    var x = void 0, y = void 0;
                    var canvas = _this._imgCanvas.nativeElement;
                    var scaleFix = _this._scal3Fix;
                    var config = _this.config;
                    var startP = _this.offset;
                    var point = getGesturePointFromEvent$1(event);
                    var deltaX = point.x - _this._startPointerEvent.x;
                    var deltaY = point.y - _this._startPointerEvent.y;
                    if (!scaleFix || !startP) {
                        return;
                    }
                    var isMinScaleY = canvas.height * scaleFix < config.height && config.extraZoomOut;
                    var isMinScaleX = canvas.width * scaleFix < config.width && config.extraZoomOut;
                    var limitLeft = (config.width / 2 / scaleFix) >= startP.left - (deltaX / scaleFix);
                    var limitRight = (config.width / 2 / scaleFix) + (canvas.width) - (startP.left - (deltaX / scaleFix)) <= config.width / scaleFix;
                    var limitTop = ((config.height / 2 / scaleFix) >= (startP.top - (deltaY / scaleFix)));
                    var limitBottom = (((config.height / 2 / scaleFix) + (canvas.height) - (startP.top - (deltaY / scaleFix))) <= (config.height / scaleFix));
                    // Limit for left
                    if ((limitLeft && !isMinScaleX) || (!limitLeft && isMinScaleX)) {
                        x = startP.x + (startP.left) - (config.width / 2 / scaleFix);
                    }
                    // Limit for right
                    if ((limitRight && !isMinScaleX) || (!limitRight && isMinScaleX)) {
                        x = startP.x + (startP.left) + (config.width / 2 / scaleFix) - canvas.width;
                    }
                    // Limit for top
                    if ((limitTop && !isMinScaleY) || (!limitTop && isMinScaleY)) {
                        y = startP.y + (startP.top) - (config.height / 2 / scaleFix);
                    }
                    // Limit for bottom
                    if ((limitBottom && !isMinScaleY) || (!limitBottom && isMinScaleY)) {
                        y = startP.y + (startP.top) + (config.height / 2 / scaleFix) - canvas.height;
                    }
                    // When press shiftKey, deprecated
                    // if (event.srcEvent && event.srcEvent.shiftKey) {
                    //   if (Math.abs(event.deltaX) === Math.max(Math.abs(event.deltaX), Math.abs(event.deltaY))) {
                    //     y = this.offset.top;
                    //   } else {
                    //     x = this.offset.left;
                    //   }
                    // }
                    if (x === void 0) {
                        x = (deltaX / scaleFix) + (startP.x);
                    }
                    if (y === void 0) {
                        y = (deltaY / scaleFix) + (startP.y);
                    }
                    _this._setStylesForContImg({
                        x: x, y: y
                    });
                }
            };
            /** Called when the user has lifted their pointer. */
            this._pointerUp = function (event) {
                if (_this._isSliding) {
                    event.preventDefault();
                    _this._removeGlobalEvents();
                    _this._isSliding = false;
                    _this._startPointerEvent = null;
                    _this._cropIfAutoCrop();
                }
            };
            /** Called when the window has lost focus. */
            this._windowBlur = function () {
                // If the window is blurred while dragging we need to stop dragging because the
                // browser won't dispatch the `mouseup` and `touchend` events anymore.
                if (_this._lastPointerEvent) {
                    _this._pointerUp(_this._lastPointerEvent);
                }
            };
            this._document = _document;
            viewPortRuler.change()
                .pipe(operators.takeUntil(this._destroy))
                .subscribe(function () { return _this._ngZone.run(function () { return _this.updateCropperPosition(); }); });
        }
        Object.defineProperty(LyImageCropper.prototype, "config", {
            get: function () {
                return this._config;
            },
            set: function (val) {
                this._config = ui.mergeDeep({}, new ImgCropperConfig(), val);
                this._configPrimary = ui.mergeDeep({}, this._config);
                this._primaryAreaWidth = this.config.width;
                this._primaryAreaHeight = this.config.height;
                if (this._config.round
                    && this.config.width !== this.config.height) {
                    throw new Error(LyImageCropper.и + ": Both width and height must be equal when using `ImgCropperConfig.round = true`");
                }
                var maxFileSize = this._config.maxFileSize;
                if (maxFileSize) {
                    this.maxFileSize = maxFileSize;
                }
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(LyImageCropper.prototype, "scale", {
            /** Set scale */
            get: function () {
                return this._scale;
            },
            set: function (val) {
                this.setScale(val);
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(LyImageCropper.prototype, "minScale", {
            /** Get min scale */
            get: function () {
                return this._minScale;
            },
            enumerable: false,
            configurable: true
        });
        LyImageCropper.prototype.ngOnInit = function () {
            var _this = this;
            this._ngZone.runOutsideAngular(function () {
                var element = _this._imgContainer.nativeElement;
                element.addEventListener('mousedown', _this._pointerDown, activeEventOptions$1);
                element.addEventListener('touchstart', _this._pointerDown, activeEventOptions$1);
            });
        };
        LyImageCropper.prototype.ngOnDestroy = function () {
            this._destroy.next();
            this._destroy.complete();
            var element = this._imgContainer.nativeElement;
            this._lastPointerEvent = null;
            this._removeGlobalEvents();
            element.removeEventListener('mousedown', this._pointerDown, activeEventOptions$1);
            element.removeEventListener('touchstart', this._pointerDown, activeEventOptions$1);
        };
        /** Load image with canvas */
        LyImageCropper.prototype._imgLoaded = function (imgElement) {
            if (imgElement) {
                this._img = imgElement;
                var canvas = this._imgCanvas.nativeElement;
                canvas.width = imgElement.width;
                canvas.height = imgElement.height;
                var ctx = canvas.getContext('2d');
                ctx.clearRect(0, 0, imgElement.width, imgElement.height);
                ctx.drawImage(imgElement, 0, 0);
                /** set min scale */
                this._updateMinScale(canvas);
                this._updateMaxScale();
            }
        };
        LyImageCropper.prototype._setStylesForContImg = function (values) {
            var newStyles = {};
            if (values.x != null && values.y != null) {
                var rootRect = this._rootRect();
                var x = rootRect.width / 2 - (values.x);
                var y = rootRect.height / 2 - (values.y);
                this._imgRect.x = (values.x);
                this._imgRect.y = (values.y);
                this._imgRect.xc = (x);
                this._imgRect.yc = (y);
            }
            newStyles.transform = "translate3d(" + (this._imgRect.x) + "px," + (this._imgRect.y) + "px, 0)";
            newStyles.transform += "scale(" + this._scal3Fix + ")";
            newStyles.transformOrigin = this._imgRect.xc + "px " + this._imgRect.yc + "px 0";
            newStyles['-webkit-transform'] = newStyles.transform;
            newStyles['-webkit-transform-origin'] = newStyles.transformOrigin;
            for (var key in newStyles) {
                if (newStyles.hasOwnProperty(key)) {
                    this._renderer.setStyle(this._imgContainer.nativeElement, key, newStyles[key]);
                }
            }
        };
        /**
         * Update area and image position only if needed,
         * this is used when window resize
         */
        LyImageCropper.prototype.updateCropperPosition = function () {
            if (this.isLoaded) {
                this.updatePosition();
                this._updateAreaIfNeeded();
            }
        };
        /** Load Image from input event */
        LyImageCropper.prototype.selectInputEvent = function (img) {
            var _this = this;
            this._currentInputElement = img.target;
            var _img = img.target;
            if (_img.files && _img.files.length !== 1) {
                return;
            }
            var fileSize = _img.files[0].size;
            var fileName = _img.value.replace(/.*(\/|\\)/, '');
            if (this.maxFileSize && fileSize > this.maxFileSize) {
                var cropEvent = {
                    name: fileName,
                    type: _img.files[0].type,
                    size: fileSize,
                    error: exports.ImgCropperError.Size
                };
                this.clean();
                this.error.emit(cropEvent);
                return;
            }
            new rxjs.Observable(function (observer) {
                var reader = new FileReader();
                reader.onerror = function (err) { return observer.error(err); };
                reader.onabort = function (err) { return observer.error(err); };
                reader.onload = function (ev) { return setTimeout(function () {
                    observer.next(ev);
                    observer.complete();
                }); };
                reader.readAsDataURL(_img.files[0]);
            })
                .pipe(operators.take(1), operators.takeUntil(this._destroy))
                .subscribe(function (loadEvent) {
                var originalDataURL = loadEvent.target.result;
                _this.loadImage({
                    name: fileName,
                    size: _img.files[0].size,
                    type: _this.config.type || _img.files[0].type,
                    originalDataURL: originalDataURL
                });
                _this.cd.markForCheck();
            }, function () {
                var cropEvent = {
                    name: fileName,
                    size: fileSize,
                    error: exports.ImgCropperError.Other,
                    errorMsg: 'The File could not be loaded.',
                    type: _img.files[0].type
                };
                _this.clean();
                _this.error.emit(cropEvent);
            });
        };
        /** Set the size of the image, the values can be 0 between 1, where 1 is the original size */
        LyImageCropper.prototype.setScale = function (size, noAutoCrop) {
            // fix min scale
            var newSize = size >= this.minScale && size <= 1 ? size : this.minScale;
            // check
            var changed = size != null && size !== this.scale && newSize !== this.scale;
            this._scale = size;
            if (!changed) {
                return;
            }
            this._scal3Fix = newSize;
            this._updateAbsoluteScale();
            if (this.isLoaded) {
                if (changed) {
                    var originPosition = Object.assign({}, this._imgRect);
                    this.offset = {
                        x: originPosition.x,
                        y: originPosition.y,
                        left: originPosition.xc,
                        top: originPosition.yc
                    };
                    this._setStylesForContImg({});
                    this._simulatePointerMove();
                }
                else {
                    return;
                }
            }
            else if (this.minScale) {
                this._setStylesForContImg(Object.assign({}, this._getCenterPoints()));
            }
            else {
                return;
            }
            this.scaleChange.emit(size);
            if (!noAutoCrop) {
                this._cropIfAutoCrop();
            }
        };
        LyImageCropper.prototype._getCenterPoints = function () {
            var root = this._elementRef.nativeElement;
            var img = this._imgCanvas.nativeElement;
            var x = (root.offsetWidth - (img.width)) / 2;
            var y = (root.offsetHeight - (img.height)) / 2;
            return {
                x: x,
                y: y
            };
        };
        /**
         * Fit to screen
         */
        LyImageCropper.prototype.fitToScreen = function () {
            var container = this._elementRef.nativeElement;
            var min = {
                width: container.offsetWidth,
                height: container.offsetHeight
            };
            var _a = this._img, width = _a.width, height = _a.height;
            var minScale = {
                width: min.width / width,
                height: min.height / height
            };
            var result = Math.max(minScale.width, minScale.height);
            this.setScale(result);
        };
        LyImageCropper.prototype.fit = function () {
            this.setScale(this.minScale);
        };
        /**
         * Simulate pointerMove with clientX = 0 and clientY = 0,
         * this is used by `setScale` and `rotate`
         */
        LyImageCropper.prototype._simulatePointerMove = function () {
            this._isSliding = true;
            this._startPointerEvent = {
                x: 0,
                y: 0
            };
            this._pointerMove({
                clientX: 0,
                clientY: 0,
                type: 'n',
                preventDefault: function () { }
            });
            this._isSliding = false;
            this._startPointerEvent = null;
        };
        LyImageCropper.prototype._markForCheck = function () {
            this.cd.markForCheck();
        };
        LyImageCropper.prototype.updatePosition = function (xOrigin, yOrigin) {
            var hostRect = this._rootRect();
            var areaRect = this._areaCropperRect();
            var areaWidth = areaRect.width > hostRect.width
                ? hostRect.width
                : areaRect.width;
            var areaHeight = areaRect.height > hostRect.height
                ? hostRect.height
                : areaRect.height;
            var x, y;
            if (xOrigin == null && yOrigin == null) {
                xOrigin = this._imgRect.xc;
                yOrigin = this._imgRect.yc;
            }
            x = (areaRect.left - hostRect.left);
            y = (areaRect.top - hostRect.top);
            x -= (xOrigin - (areaWidth / 2));
            y -= (yOrigin - (areaHeight / 2));
            this._setStylesForContImg({
                x: x, y: y
            });
        };
        LyImageCropper.prototype._slideEnd = function () {
            this._cropIfAutoCrop();
        };
        LyImageCropper.prototype._cropIfAutoCrop = function () {
            if (this.config.autoCrop) {
                this.crop();
            }
        };
        /** + */
        LyImageCropper.prototype.zoomIn = function () {
            var scale = this._scal3Fix + .05;
            if (scale > this.minScale && scale <= this._maxScale) {
                this.setScale(scale);
            }
            else {
                this.setScale(this._maxScale);
            }
        };
        /** Clean the img cropper */
        LyImageCropper.prototype.clean = function () {
            // fix choosing the same image does not load
            if (this._currentInputElement) {
                this._currentInputElement.value = '';
                this._currentInputElement = null;
            }
            if (this.isLoaded) {
                this._imgRect = {};
                this.offset = undefined;
                this.scale = undefined;
                this._scal3Fix = undefined;
                this._rotation = 0;
                this._minScale = undefined;
                this._isLoadedImg = false;
                this.isLoaded = false;
                this.isCropped = false;
                this._currentLoadConfig = undefined;
                this.config = this._configPrimary;
                var canvas = this._imgCanvas.nativeElement;
                canvas.width = 0;
                canvas.height = 0;
                this.cleaned.emit(null);
                this.cd.markForCheck();
            }
        };
        /** - */
        LyImageCropper.prototype.zoomOut = function () {
            var scale = this._scal3Fix - .05;
            if (scale > this.minScale && scale <= this._maxScale) {
                this.setScale(scale);
            }
            else {
                this.fit();
            }
        };
        LyImageCropper.prototype.center = function () {
            var newStyles = Object.assign({}, this._getCenterPoints());
            this._setStylesForContImg(newStyles);
            this._cropIfAutoCrop();
        };
        /**
         * load an image from a given configuration,
         * or from the result of a cropped image
         */
        LyImageCropper.prototype.loadImage = function (config, fn) {
            var _this = this;
            this.clean();
            var _config = this._currentLoadConfig = typeof config === 'string'
                ? { originalDataURL: config }
                : Object.assign({}, config);
            var src = _config.originalDataURL;
            this._primaryAreaWidth = this._configPrimary.width;
            this._primaryAreaHeight = this._configPrimary.height;
            if (_config.areaWidth && _config.areaHeight) {
                this.config.width = _config.areaWidth;
                this.config.height = _config.areaHeight;
            }
            src = normalizeSVG(src);
            var img = createHtmlImg(src);
            var cropEvent = Object.assign({}, _config);
            new rxjs.Observable(function (observer) {
                img.onerror = function (err) { return observer.error(err); };
                img.onabort = function (err) { return observer.error(err); };
                img.onload = function () { return observer.next(null); };
            })
                .pipe(operators.take(1), operators.takeUntil(this._destroy))
                .subscribe(function () {
                _this._imgLoaded(img);
                _this._isLoadedImg = true;
                _this.imageLoaded.emit(cropEvent);
                _this.cd.markForCheck();
                _this._ngZone.runOutsideAngular(function () {
                    _this._ngZone
                        .onStable
                        .asObservable()
                        .pipe(operators.take(1), operators.takeUntil(_this._destroy))
                        .subscribe(function () { return setTimeout(function () { return _this._ngZone.run(function () { return _this._positionImg(cropEvent, fn); }); }); });
                });
            }, function () {
                var error = {
                    name: _config.name,
                    error: exports.ImgCropperError.Type,
                    type: _config.type,
                    size: _config.size
                };
                _this.error.emit(error);
            });
        };
        LyImageCropper.prototype._updateAreaIfNeeded = function () {
            if (!this._config.responsiveArea) {
                return;
            }
            var rootRect = this._rootRect();
            var areaRect = this._areaCropperRect();
            var minWidth = this.config.minWidth || 1;
            var minHeight = this.config.minHeight || 1;
            if (!(areaRect.width > rootRect.width
                || areaRect.height > rootRect.height
                || areaRect.width < this._primaryAreaWidth
                || areaRect.height < this._primaryAreaHeight)) {
                return;
            }
            var areaWidthConf = Math.max(this.config.width, minWidth);
            var areaWidthMax = Math.max(rootRect.width, minWidth);
            var minHost = Math.min(Math.max(rootRect.width, minWidth), Math.max(rootRect.height, minHeight));
            var currentScale = this._scal3Fix;
            var newScale = 0;
            var roundConf = this.config.round;
            if (roundConf) {
                this.config.width = this.config.height = minHost;
            }
            else {
                if (areaWidthConf === areaRect.width) {
                    if (areaWidthMax > this._primaryAreaWidth) {
                        this.config.width = this._primaryAreaWidth;
                        this.config.height = (this._primaryAreaWidth * areaRect.height) / areaRect.width;
                        newScale = (currentScale * this._primaryAreaWidth) / areaRect.width;
                    }
                    else {
                        this.config.width = areaWidthMax;
                        this.config.height = (areaWidthMax * areaRect.height) / areaRect.width;
                        newScale = (currentScale * areaWidthMax) / areaRect.width;
                    }
                    this._updateMinScale();
                    this._updateMaxScale();
                    this.setScale(newScale, true);
                    this._markForCheck();
                }
            }
        };
        LyImageCropper.prototype._updateAbsoluteScale = function () {
            var scale = this._scal3Fix / (this.config.width / this._primaryAreaWidth);
            this._absoluteScale = scale;
        };
        /**
         * Load Image from URL
         * @deprecated Use `loadImage` instead of `setImageUrl`
         * @param src URL
         * @param fn function that will be called before emit the event loaded
         */
        LyImageCropper.prototype.setImageUrl = function (src, fn) {
            this.loadImage(src, fn);
        };
        LyImageCropper.prototype._positionImg = function (cropEvent, fn) {
            var _this = this;
            var loadConfig = this._currentLoadConfig;
            this._updateMinScale(this._imgCanvas.nativeElement);
            this._updateMaxScale();
            this.isLoaded = false;
            if (fn) {
                fn();
            }
            else {
                if (loadConfig.scale) {
                    this.setScale(loadConfig.scale, true);
                }
                else {
                    this.setScale(this.minScale, true);
                }
                this.rotate(loadConfig.rotation || 0);
                this._updateAreaIfNeeded();
                this._markForCheck();
                this._ngZone.runOutsideAngular(function () {
                    _this._ngZone
                        .onStable
                        .asObservable()
                        .pipe(operators.take(1), operators.takeUntil(_this._destroy))
                        .subscribe(function () {
                        if (loadConfig.xOrigin != null && loadConfig.yOrigin != null) {
                            _this.updatePosition(loadConfig.xOrigin, loadConfig.yOrigin);
                        }
                        _this._updateAreaIfNeeded();
                        _this.isLoaded = true;
                        _this._cropIfAutoCrop();
                        _this._ngZone.run(function () {
                            _this._markForCheck();
                            _this.ready.emit(cropEvent);
                            // tslint:disable-next-line: deprecation
                            _this.loaded.emit(cropEvent);
                        });
                    });
                });
            }
        };
        LyImageCropper.prototype.rotate = function (degrees) {
            var validDegrees = _normalizeDegrees(degrees);
            // If negative convert to positive
            if (validDegrees < 0) {
                validDegrees += 360;
            }
            var newRotation = _normalizeDegrees((this._rotation || 0) + validDegrees);
            if (newRotation === this._rotation) {
                return;
            }
            var degreesRad = validDegrees * Math.PI / 180;
            var canvas = this._imgCanvas.nativeElement;
            var canvasClon = createCanvasImg(canvas);
            var ctx = canvas.getContext('2d');
            this._rotation = newRotation;
            // clear
            ctx.clearRect(0, 0, canvasClon.width, canvasClon.height);
            // rotate canvas image
            var transform = "rotate(" + validDegrees + "deg) scale(" + 1 / this._scal3Fix + ")";
            var transformOrigin = this._imgRect.xc + "px " + this._imgRect.yc + "px 0";
            canvas.style.transform = transform;
            // tslint:disable-next-line: deprecation
            canvas.style.webkitTransform = transform;
            canvas.style.transformOrigin = transformOrigin;
            // tslint:disable-next-line: deprecation
            canvas.style.webkitTransformOrigin = transformOrigin;
            var _a = canvas.getBoundingClientRect(), left = _a.left, top = _a.top;
            // save rect
            var canvasRect = canvas.getBoundingClientRect();
            // remove rotate styles
            canvas.removeAttribute('style');
            // set w & h
            var w = canvasRect.width;
            var h = canvasRect.height;
            ctx.canvas.width = w;
            ctx.canvas.height = h;
            // clear
            ctx.clearRect(0, 0, w, h);
            // translate and rotate
            ctx.translate(w / 2, h / 2);
            ctx.rotate(degreesRad);
            ctx.drawImage(canvasClon, -canvasClon.width / 2, -canvasClon.height / 2);
            // Update min scale
            this._updateMinScale(canvas);
            this._updateMaxScale();
            // set the minimum scale, only if necessary
            if (this.scale < this.minScale) {
                this.setScale(0, true);
            } //                ↑ no AutoCrop
            var rootRect = this._rootRect();
            this._setStylesForContImg({
                x: (left - rootRect.left),
                y: (top - rootRect.top)
            });
            // keep image inside the frame
            var originPosition = Object.assign({}, this._imgRect);
            this.offset = {
                x: originPosition.x,
                y: originPosition.y,
                left: originPosition.xc,
                top: originPosition.yc
            };
            this._setStylesForContImg({});
            this._simulatePointerMove();
            this._cropIfAutoCrop();
        };
        LyImageCropper.prototype._updateMinScale = function (canvas) {
            if (!canvas) {
                canvas = this._imgCanvas.nativeElement;
            }
            var config = this.config;
            var minScale = (config.extraZoomOut ? Math.min : Math.max)(config.width / canvas.width, config.height / canvas.height);
            this._minScale = minScale;
            this.minScaleChange.emit(minScale);
        };
        LyImageCropper.prototype._updateMaxScale = function () {
            var maxScale = (this.config.width / this._primaryAreaWidth);
            this._maxScale = maxScale;
            this.maxScaleChange.emit(maxScale);
        };
        /**
         * Resize & crop image
         */
        LyImageCropper.prototype.crop = function (config) {
            var newConfig = config
                ? ui.mergeDeep({}, this.config || new ImgCropperConfig(), config) : this.config;
            var cropEvent = this._imgCrop(newConfig);
            this.cd.markForCheck();
            return cropEvent;
        };
        /**
         * @docs-private
         */
        LyImageCropper.prototype._imgCrop = function (myConfig) {
            var canvasElement = document.createElement('canvas');
            var areaRect = this._areaCropperRect();
            var canvasRect = this._canvasRect();
            var scaleFix = this._scal3Fix;
            var left = (areaRect.left - canvasRect.left) / scaleFix;
            var top = (areaRect.top - canvasRect.top) / scaleFix;
            var output = myConfig.output;
            var currentImageLoadConfig = this._currentLoadConfig;
            var area = {
                width: myConfig.width,
                height: myConfig.height
            };
            canvasElement.width = area.width / scaleFix;
            canvasElement.height = area.height / scaleFix;
            var ctx = canvasElement.getContext('2d');
            if (myConfig.fill) {
                ctx.fillStyle = myConfig.fill;
                ctx.fillRect(0, 0, canvasElement.width, canvasElement.height);
            }
            ctx.drawImage(this._imgCanvas.nativeElement, -(left), -(top));
            var result = canvasElement;
            if (myConfig.output === exports.ImgResolution.Default) {
                resizeCanvas(result, this._configPrimary.width, this._configPrimary.height);
            }
            else if (typeof output === 'object') {
                if (output.width && output.height) {
                    resizeCanvas(result, output.width, output.height);
                }
                else if (output.width) {
                    var newHeight = area.height * output.width / area.width;
                    resizeCanvas(result, output.width, newHeight);
                }
                else if (output.height) {
                    var newWidth = area.width * output.height / area.height;
                    resizeCanvas(result, newWidth, output.height);
                }
            }
            var type = currentImageLoadConfig.originalDataURL.startsWith('http')
                ? currentImageLoadConfig.type || myConfig.type
                : myConfig.type || currentImageLoadConfig.type;
            var dataURL = result.toDataURL(type);
            var cropEvent = {
                dataURL: dataURL,
                type: type,
                name: currentImageLoadConfig.name,
                areaWidth: this._primaryAreaWidth,
                areaHeight: this._primaryAreaHeight,
                width: result.width,
                height: result.height,
                originalDataURL: currentImageLoadConfig.originalDataURL,
                scale: this._absoluteScale,
                rotation: this._rotation,
                left: (areaRect.left - canvasRect.left) / this._scal3Fix,
                top: (areaRect.top - canvasRect.top) / this._scal3Fix,
                size: currentImageLoadConfig.size,
                xOrigin: this._imgRect.xc,
                yOrigin: this._imgRect.yc,
                position: {
                    x: this._imgRect.xc,
                    y: this._imgRect.yc
                }
            };
            this.isCropped = true;
            this.cropped.emit(cropEvent);
            return cropEvent;
        };
        LyImageCropper.prototype._rootRect = function () {
            return this._elementRef.nativeElement.getBoundingClientRect();
        };
        LyImageCropper.prototype._areaCropperRect = function () {
            return this._areaRef.nativeElement.getBoundingClientRect();
        };
        LyImageCropper.prototype._canvasRect = function () {
            return this._imgCanvas.nativeElement.getBoundingClientRect();
        };
        LyImageCropper.prototype._bindGlobalEvents = function (triggerEvent) {
            var element = this._document;
            var isTouch = isTouchEvent$1(triggerEvent);
            var moveEventName = isTouch ? 'touchmove' : 'mousemove';
            var endEventName = isTouch ? 'touchend' : 'mouseup';
            element.addEventListener(moveEventName, this._pointerMove, activeEventOptions$1);
            element.addEventListener(endEventName, this._pointerUp, activeEventOptions$1);
            if (isTouch) {
                element.addEventListener('touchcancel', this._pointerUp, activeEventOptions$1);
            }
            var window = this._getWindow();
            if (typeof window !== 'undefined' && window) {
                window.addEventListener('blur', this._windowBlur);
            }
        };
        /** Removes any global event listeners that we may have added. */
        LyImageCropper.prototype._removeGlobalEvents = function () {
            var element = this._document;
            element.removeEventListener('mousemove', this._pointerMove, activeEventOptions$1);
            element.removeEventListener('mouseup', this._pointerUp, activeEventOptions$1);
            element.removeEventListener('touchmove', this._pointerMove, activeEventOptions$1);
            element.removeEventListener('touchend', this._pointerUp, activeEventOptions$1);
            element.removeEventListener('touchcancel', this._pointerUp, activeEventOptions$1);
            var window = this._getWindow();
            if (typeof window !== 'undefined' && window) {
                window.removeEventListener('blur', this._windowBlur);
            }
        };
        /** Use defaultView of injected document if available or fallback to global window reference */
        LyImageCropper.prototype._getWindow = function () {
            return this._document.defaultView || window;
        };
        return LyImageCropper;
    }());
    LyImageCropper.и = 'LyImageCropper';
    LyImageCropper.decorators = [
        { type: core.Component, args: [{
                    changeDetection: core.ChangeDetectionStrategy.OnPush,
                    preserveWhitespaces: false,
                    selector: 'ly-img-cropper, ly-image-cropper',
                    template: "<!-- (selectstart): On Safari starting to slide temporarily triggers text selection mode which\nshow the wrong cursor. We prevent it by stopping the `selectstart` event. -->\n<div #_imgContainer\n  [className]=\"classes.imgContainer\"\n  (selectstart)=\"$event.preventDefault()\"\n>\n  <canvas #_imgCanvas></canvas>\n</div>\n<ly-cropper-area #_area\n  [round]=\"!!config.round\"\n  [resizableArea]=\"!!config.resizableArea\"\n  [keepAspectRatio]=\"!!config.keepAspectRatio\"\n  *ngIf=\"_isLoadedImg; else content\"\n  [ngStyle]=\"{\n    width: config.width + 'px',\n    height: config.height + 'px'\n  }\"></ly-cropper-area>\n<ng-template #content>\n  <div [className]=\"classes.defaultContent\">\n    <input #_fileInput type=\"file\" (change)=\"selectInputEvent($event)\" accept=\"image/*\">\n    <ng-content></ng-content>\n  </div>\n</ng-template>\n",
                    providers: [
                        ui.StyleRenderer
                    ]
                },] }
    ];
    LyImageCropper.ctorParameters = function () { return [
        { type: ui.StyleRenderer },
        { type: core.Renderer2 },
        { type: core.ElementRef },
        { type: core.ChangeDetectorRef },
        { type: core.NgZone },
        { type: undefined, decorators: [{ type: core.Inject, args: [common.DOCUMENT,] }] },
        { type: scrolling.ViewportRuler }
    ]; };
    LyImageCropper.propDecorators = {
        _imgContainer: [{ type: core.ViewChild, args: ['_imgContainer', { static: true },] }],
        _areaRef: [{ type: core.ViewChild, args: ['_area', {
                        read: core.ElementRef
                    },] }],
        _imgCanvas: [{ type: core.ViewChild, args: ['_imgCanvas', { static: true },] }],
        config: [{ type: core.Input }],
        scale: [{ type: core.Input }],
        maxFileSize: [{ type: core.Input }],
        scaleChange: [{ type: core.Output }],
        minScaleChange: [{ type: core.Output, args: ['minScale',] }],
        maxScaleChange: [{ type: core.Output, args: ['maxScale',] }],
        loaded: [{ type: core.Output }],
        imageLoaded: [{ type: core.Output }],
        ready: [{ type: core.Output }],
        cropped: [{ type: core.Output }],
        cleaned: [{ type: core.Output }],
        error: [{ type: core.Output }]
    };
    /**
     * Normalize degrees for cropper rotation
     * @docs-private
     */
    function _normalizeDegrees(n) {
        var de = n % 360;
        if (de % 90) {
            throw new Error("LyCropper: Invalid `" + n + "` degree, only accepted values: 0, 90, 180, 270 & 360.");
        }
        return de;
    }
    /**
     * @docs-private
     */
    function createCanvasImg(img) {
        // create a new canvas
        var newCanvas = document.createElement('canvas');
        var context = newCanvas.getContext('2d');
        // set dimensions
        newCanvas.width = img.width;
        newCanvas.height = img.height;
        // apply the old canvas to the new one
        context.drawImage(img, 0, 0);
        // return the new canvas
        return newCanvas;
    }
    var DATA_IMAGE_SVG_PREFIX = 'data:image/svg+xml;base64,';
    function normalizeSVG(dataURL) {
        if (window.atob && isSvgImage(dataURL)) {
            var len = dataURL.length / 5;
            var text = window.atob(dataURL.replace(DATA_IMAGE_SVG_PREFIX, ''));
            var span = document.createElement('span');
            span.innerHTML = text;
            var svg = span.querySelector('svg');
            span.setAttribute('style', 'display:none');
            document.body.appendChild(span);
            var width = parseFloat(getComputedStyle(svg).width) || 1;
            var height = parseFloat(getComputedStyle(svg).height) || 1;
            var max = Math.max(width, height);
            svg.setAttribute('width', len / (width / max) + "px");
            svg.setAttribute('height', len / (height / max) + "px");
            var result = DATA_IMAGE_SVG_PREFIX + window.btoa(span.innerHTML);
            document.body.removeChild(span);
            return result;
        }
        return dataURL;
    }
    function isSvgImage(dataUrl) {
        return dataUrl.startsWith(DATA_IMAGE_SVG_PREFIX);
    }
    function createHtmlImg(src) {
        var img = new Image();
        img.crossOrigin = 'anonymous';
        img.src = src;
        return img;
    }
    function getGesturePointFromEvent$1(event) {
        // `touches` will be empty for start/end events so we have to fall back to `changedTouches`.
        var point = isTouchEvent$1(event)
            ? (event.touches[0] || event.changedTouches[0])
            : event;
        return {
            x: point.clientX,
            y: point.clientY
        };
    }
    /** Returns whether an event is a touch event. */
    function isTouchEvent$1(event) {
        return event.type[0] === 't';
    }
    function round(n) {
        return Math.round(n);
    }

    /*! *****************************************************************************
    Copyright (c) Microsoft Corporation.

    Permission to use, copy, modify, and/or distribute this software for any
    purpose with or without fee is hereby granted.

    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    PERFORMANCE OF THIS SOFTWARE.
    ***************************************************************************** */
    /* global Reflect, Promise */
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b)
                if (Object.prototype.hasOwnProperty.call(b, p))
                    d[p] = b[p]; };
        return extendStatics(d, b);
    };
    function __extends(d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    }
    var __assign = function () {
        __assign = Object.assign || function __assign(t) {
            for (var s, i = 1, n = arguments.length; i < n; i++) {
                s = arguments[i];
                for (var p in s)
                    if (Object.prototype.hasOwnProperty.call(s, p))
                        t[p] = s[p];
            }
            return t;
        };
        return __assign.apply(this, arguments);
    };
    function __rest(s, e) {
        var t = {};
        for (var p in s)
            if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
                t[p] = s[p];
        if (s != null && typeof Object.getOwnPropertySymbols === "function")
            for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
                if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                    t[p[i]] = s[p[i]];
            }
        return t;
    }
    function __decorate(decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
            r = Reflect.decorate(decorators, target, key, desc);
        else
            for (var i = decorators.length - 1; i >= 0; i--)
                if (d = decorators[i])
                    r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    }
    function __param(paramIndex, decorator) {
        return function (target, key) { decorator(target, key, paramIndex); };
    }
    function __metadata(metadataKey, metadataValue) {
        if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
            return Reflect.metadata(metadataKey, metadataValue);
    }
    function __awaiter(thisArg, _arguments, P, generator) {
        function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
        return new (P || (P = Promise))(function (resolve, reject) {
            function fulfilled(value) { try {
                step(generator.next(value));
            }
            catch (e) {
                reject(e);
            } }
            function rejected(value) { try {
                step(generator["throw"](value));
            }
            catch (e) {
                reject(e);
            } }
            function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        });
    }
    function __generator(thisArg, body) {
        var _ = { label: 0, sent: function () { if (t[0] & 1)
                throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
        return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
        function verb(n) { return function (v) { return step([n, v]); }; }
        function step(op) {
            if (f)
                throw new TypeError("Generator is already executing.");
            while (_)
                try {
                    if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
                        return t;
                    if (y = 0, t)
                        op = [op[0] & 2, t.value];
                    switch (op[0]) {
                        case 0:
                        case 1:
                            t = op;
                            break;
                        case 4:
                            _.label++;
                            return { value: op[1], done: false };
                        case 5:
                            _.label++;
                            y = op[1];
                            op = [0];
                            continue;
                        case 7:
                            op = _.ops.pop();
                            _.trys.pop();
                            continue;
                        default:
                            if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
                                _ = 0;
                                continue;
                            }
                            if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
                                _.label = op[1];
                                break;
                            }
                            if (op[0] === 6 && _.label < t[1]) {
                                _.label = t[1];
                                t = op;
                                break;
                            }
                            if (t && _.label < t[2]) {
                                _.label = t[2];
                                _.ops.push(op);
                                break;
                            }
                            if (t[2])
                                _.ops.pop();
                            _.trys.pop();
                            continue;
                    }
                    op = body.call(thisArg, _);
                }
                catch (e) {
                    op = [6, e];
                    y = 0;
                }
                finally {
                    f = t = 0;
                }
            if (op[0] & 5)
                throw op[1];
            return { value: op[0] ? op[1] : void 0, done: true };
        }
    }
    var __createBinding = Object.create ? (function (o, m, k, k2) {
        if (k2 === undefined)
            k2 = k;
        Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
    }) : (function (o, m, k, k2) {
        if (k2 === undefined)
            k2 = k;
        o[k2] = m[k];
    });
    function __exportStar(m, o) {
        for (var p in m)
            if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p))
                __createBinding(o, m, p);
    }
    function __values(o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m)
            return m.call(o);
        if (o && typeof o.length === "number")
            return {
                next: function () {
                    if (o && i >= o.length)
                        o = void 0;
                    return { value: o && o[i++], done: !o };
                }
            };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    }
    function __read(o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m)
            return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
                ar.push(r.value);
        }
        catch (error) {
            e = { error: error };
        }
        finally {
            try {
                if (r && !r.done && (m = i["return"]))
                    m.call(i);
            }
            finally {
                if (e)
                    throw e.error;
            }
        }
        return ar;
    }
    function __spread() {
        for (var ar = [], i = 0; i < arguments.length; i++)
            ar = ar.concat(__read(arguments[i]));
        return ar;
    }
    function __spreadArrays() {
        for (var s = 0, i = 0, il = arguments.length; i < il; i++)
            s += arguments[i].length;
        for (var r = Array(s), k = 0, i = 0; i < il; i++)
            for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
                r[k] = a[j];
        return r;
    }
    ;
    function __await(v) {
        return this instanceof __await ? (this.v = v, this) : new __await(v);
    }
    function __asyncGenerator(thisArg, _arguments, generator) {
        if (!Symbol.asyncIterator)
            throw new TypeError("Symbol.asyncIterator is not defined.");
        var g = generator.apply(thisArg, _arguments || []), i, q = [];
        return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
        function verb(n) { if (g[n])
            i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
        function resume(n, v) { try {
            step(g[n](v));
        }
        catch (e) {
            settle(q[0][3], e);
        } }
        function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
        function fulfill(value) { resume("next", value); }
        function reject(value) { resume("throw", value); }
        function settle(f, v) { if (f(v), q.shift(), q.length)
            resume(q[0][0], q[0][1]); }
    }
    function __asyncDelegator(o) {
        var i, p;
        return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
        function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
    }
    function __asyncValues(o) {
        if (!Symbol.asyncIterator)
            throw new TypeError("Symbol.asyncIterator is not defined.");
        var m = o[Symbol.asyncIterator], i;
        return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
        function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
        function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
    }
    function __makeTemplateObject(cooked, raw) {
        if (Object.defineProperty) {
            Object.defineProperty(cooked, "raw", { value: raw });
        }
        else {
            cooked.raw = raw;
        }
        return cooked;
    }
    ;
    var __setModuleDefault = Object.create ? (function (o, v) {
        Object.defineProperty(o, "default", { enumerable: true, value: v });
    }) : function (o, v) {
        o["default"] = v;
    };
    function __importStar(mod) {
        if (mod && mod.__esModule)
            return mod;
        var result = {};
        if (mod != null)
            for (var k in mod)
                if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
                    __createBinding(result, mod, k);
        __setModuleDefault(result, mod);
        return result;
    }
    function __importDefault(mod) {
        return (mod && mod.__esModule) ? mod : { default: mod };
    }
    function __classPrivateFieldGet(receiver, privateMap) {
        if (!privateMap.has(receiver)) {
            throw new TypeError("attempted to get private field on non-instance");
        }
        return privateMap.get(receiver);
    }
    function __classPrivateFieldSet(receiver, privateMap, value) {
        if (!privateMap.has(receiver)) {
            throw new TypeError("attempted to set private field on non-instance");
        }
        privateMap.set(receiver, value);
        return value;
    }

    var activeEventOptions = platform.normalizePassiveListenerOptions({ passive: false });
    var pos = (100 * Math.sqrt(2) - 100) / 2 / Math.sqrt(2);
    var ɵ0 = function (_value, _, _b) {
        var __ = _b.classes;
        return function (_b) {
            var after = _b.after;
            return function (className) { return className + "{border-radius:50%;}" + className + " ." + __.resizer + "{" + after + ":" + pos + "%;bottom:" + pos + "%;transform:translate(4px, 4px);}"; };
        };
    };
    /**
     * @dynamic
     */
    var LyCropperArea = /** @class */ (function () {
        function LyCropperArea(sRenderer, _elementRef, _ngZone, _cropper, _document) {
            var _this = this;
            this.sRenderer = sRenderer;
            this._elementRef = _elementRef;
            this._ngZone = _ngZone;
            this._cropper = _cropper;
            this.classes = this.sRenderer.renderSheet(STYLES, 'area');
            this._pointerDown = function (event) {
                // Don't do anything if the
                // user is using anything other than the main mouse button.
                if (_this._isSliding || (!isTouchEvent(event) && event.button !== 0)) {
                    return;
                }
                event.preventDefault();
                _this._ngZone.run(function () {
                    _this._isSliding = true;
                    _this._lastPointerEvent = event;
                    _this._startPointerEvent = getGesturePointFromEvent(event);
                    _this._startAreaRect = _this._cropper._areaCropperRect();
                    _this._startImgRect = _this._cropper._canvasRect();
                    event.preventDefault();
                    _this._bindGlobalEvents(event);
                });
            };
            this._pointerMove = function (event) {
                if (_this._isSliding) {
                    event.preventDefault();
                    _this._lastPointerEvent = event;
                    var element = _this._elementRef.nativeElement;
                    var _b = _this._cropper.config, width = _b.width, height = _b.height, minWidth = _b.minWidth, minHeight = _b.minHeight;
                    var point = getGesturePointFromEvent(event);
                    var deltaX = point.x - _this._startPointerEvent.x;
                    var deltaY = point.y - _this._startPointerEvent.y;
                    var startAreaRect = _this._startAreaRect;
                    var startImgRect = _this._startImgRect;
                    var round = _this.round;
                    var keepAspectRatio = _this._cropper.config.keepAspectRatio || event.shiftKey;
                    var newWidth = 0;
                    var newHeight = 0;
                    var rootRect = _this._cropper._rootRect();
                    if (round) {
                        // The distance from the center of the cropper area to the pointer
                        var originX = ((width / 2 / Math.sqrt(2)) + deltaX);
                        var originY = ((height / 2 / Math.sqrt(2)) + deltaY);
                        // Leg
                        var side = Math.sqrt(Math.pow(originX, 2) + Math.pow(originY, 2));
                        newWidth = newHeight = side * 2;
                    }
                    else if (keepAspectRatio) {
                        newWidth = width + deltaX * 2;
                        newHeight = height + deltaY * 2;
                        if (width !== height) {
                            if (width > height) {
                                newHeight = height / (width / newWidth);
                            }
                            else if (height > width) {
                                newWidth = width / (height / newHeight);
                            }
                        }
                        else {
                            newWidth = newHeight = Math.max(newWidth, newHeight);
                        }
                    }
                    else {
                        newWidth = width + deltaX * 2;
                        newHeight = height + deltaY * 2;
                    }
                    // To min width
                    if (newWidth < minWidth) {
                        newWidth = minWidth;
                    }
                    // To min height
                    if (newHeight < minHeight) {
                        newHeight = minHeight;
                    }
                    // Do not overflow the cropper area
                    var centerX = startAreaRect.x + startAreaRect.width / 2;
                    var centerY = startAreaRect.y + startAreaRect.height / 2;
                    var topOverflow = startImgRect.y > centerY - (newHeight / 2);
                    var bottomOverflow = centerY + (newHeight / 2) > startImgRect.bottom;
                    var minHeightOnOverflow = Math.min((centerY - startImgRect.y) * 2, (startImgRect.bottom - centerY) * 2);
                    var leftOverflow = startImgRect.x > centerX - (newWidth / 2);
                    var rightOverflow = centerX + (newWidth / 2) > startImgRect.right;
                    var minWidthOnOverflow = Math.min((centerX - startImgRect.x) * 2, (startImgRect.right - centerX) * 2);
                    var minOnOverflow = Math.min(minWidthOnOverflow, minHeightOnOverflow);
                    if (round) {
                        if (topOverflow || bottomOverflow || leftOverflow || rightOverflow) {
                            newHeight = newWidth = minOnOverflow;
                        }
                    }
                    else if (keepAspectRatio) {
                        var newNewWidth = [];
                        var newNewHeight = [];
                        if ((topOverflow || bottomOverflow) && Math.min()) {
                            newHeight = minHeightOnOverflow;
                            newNewHeight.push(newHeight);
                            newWidth = width / (height / minHeightOnOverflow);
                            newNewWidth.push(newWidth);
                        }
                        if ((leftOverflow || rightOverflow)) {
                            newWidth = minWidthOnOverflow;
                            newNewWidth.push(newWidth);
                            newHeight = height / (width / minWidthOnOverflow);
                            newNewHeight.push(newHeight);
                        }
                        if (newNewWidth.length === 2) {
                            newWidth = Math.min.apply(Math, __spread(newNewWidth));
                        }
                        if (newNewHeight.length === 2) {
                            newHeight = Math.min.apply(Math, __spread(newNewHeight));
                        }
                    }
                    else {
                        if (topOverflow || bottomOverflow) {
                            newHeight = minHeightOnOverflow;
                        }
                        if (leftOverflow || rightOverflow) {
                            newWidth = minWidthOnOverflow;
                        }
                    }
                    // Do not overflow the container
                    if (round) {
                        var min = Math.min(rootRect.width, rootRect.height);
                        if (newWidth > min) {
                            newWidth = newHeight = min;
                        }
                        else if (newHeight > min) {
                            newWidth = newHeight = min;
                        }
                    }
                    else if (keepAspectRatio) {
                        if (newWidth > rootRect.width) {
                            newWidth = rootRect.width;
                            newHeight = height / (width / rootRect.width);
                        }
                        else if (newHeight > rootRect.height) {
                            newWidth = width / (height / rootRect.height);
                            newHeight = rootRect.height;
                        }
                    }
                    else {
                        if (newWidth > rootRect.width) {
                            newWidth = rootRect.width;
                        }
                        else if (newHeight > rootRect.height) {
                            newHeight = rootRect.height;
                        }
                    }
                    // round values
                    newWidth = Math.round(newWidth);
                    newHeight = Math.round(newHeight);
                    element.style.width = newWidth + "px";
                    element.style.height = newHeight + "px";
                    _this._currentWidth = newWidth;
                    _this._currentHeight = newHeight;
                }
            };
            /** Called when the user has lifted their pointer. */
            this._pointerUp = function (event) {
                if (_this._isSliding) {
                    event.preventDefault();
                    _this._removeGlobalEvents();
                    _this._cropper._primaryAreaWidth = _this._cropper.config.width = _this._currentWidth;
                    _this._cropper._primaryAreaHeight = _this._cropper.config.height = _this._currentHeight;
                    _this._cropper.config = _this._cropper.config;
                    _this._cropper._updateMinScale();
                    _this._isSliding = false;
                    _this._startPointerEvent = null;
                }
            };
            /** Called when the window has lost focus. */
            this._windowBlur = function () {
                // If the window is blurred while dragging we need to stop dragging because the
                // browser won't dispatch the `mouseup` and `touchend` events anymore.
                if (_this._lastPointerEvent) {
                    _this._pointerUp(_this._lastPointerEvent);
                }
            };
            this._document = _document;
        }
        Object.defineProperty(LyCropperArea.prototype, "resizableArea", {
            get: function () {
                return this._resizableArea;
            },
            set: function (val) {
                var _this = this;
                if (val !== this._resizableArea) {
                    this._resizableArea = val;
                    Promise.resolve(null).then(function () {
                        if (val) {
                            _this._removeResizableArea();
                            _this._addResizableArea();
                        }
                        else {
                            _this._removeResizableArea();
                        }
                    });
                }
            },
            enumerable: false,
            configurable: true
        });
        LyCropperArea.prototype.ngOnDestroy = function () {
            this._removeResizableArea();
        };
        LyCropperArea.prototype._addResizableArea = function () {
            var _this = this;
            this._ngZone.runOutsideAngular(function () {
                var element = _this._resizer.nativeElement;
                element.addEventListener('mousedown', _this._pointerDown, activeEventOptions);
                element.addEventListener('touchstart', _this._pointerDown, activeEventOptions);
            });
        };
        LyCropperArea.prototype._removeResizableArea = function () {
            var _a;
            var element = (_a = this._resizer) === null || _a === void 0 ? void 0 : _a.nativeElement;
            if (element) {
                this._lastPointerEvent = null;
                this._removeGlobalEvents();
                element.removeEventListener('mousedown', this._pointerDown, activeEventOptions);
                element.removeEventListener('touchstart', this._pointerDown, activeEventOptions);
            }
        };
        LyCropperArea.prototype._bindGlobalEvents = function (triggerEvent) {
            var element = this._document;
            var isTouch = isTouchEvent(triggerEvent);
            var moveEventName = isTouch ? 'touchmove' : 'mousemove';
            var endEventName = isTouch ? 'touchend' : 'mouseup';
            element.addEventListener(moveEventName, this._pointerMove, activeEventOptions);
            element.addEventListener(endEventName, this._pointerUp, activeEventOptions);
            if (isTouch) {
                element.addEventListener('touchcancel', this._pointerUp, activeEventOptions);
            }
            var window = this._getWindow();
            if (typeof window !== 'undefined' && window) {
                window.addEventListener('blur', this._windowBlur);
            }
        };
        /** Removes any global event listeners that we may have added. */
        LyCropperArea.prototype._removeGlobalEvents = function () {
            var element = this._document;
            element.removeEventListener('mousemove', this._pointerMove, activeEventOptions);
            element.removeEventListener('mouseup', this._pointerUp, activeEventOptions);
            element.removeEventListener('touchmove', this._pointerMove, activeEventOptions);
            element.removeEventListener('touchend', this._pointerUp, activeEventOptions);
            element.removeEventListener('touchcancel', this._pointerUp, activeEventOptions);
            var window = this._getWindow();
            if (typeof window !== 'undefined' && window) {
                window.removeEventListener('blur', this._windowBlur);
            }
        };
        /** Use defaultView of injected document if available or fallback to global window reference */
        LyCropperArea.prototype._getWindow = function () {
            return this._document.defaultView || window;
        };
        return LyCropperArea;
    }());
    LyCropperArea.decorators = [
        { type: core.Component, args: [{
                    selector: 'ly-cropper-area',
                    template: "<div #resizer\n  *ngIf=\"resizableArea\"\n  [class]=\"classes.resizer\"\n></div>",
                    providers: [
                        ui.StyleRenderer
                    ],
                    changeDetection: core.ChangeDetectionStrategy.OnPush,
                    exportAs: 'lyCropperArea'
                },] }
    ];
    LyCropperArea.ctorParameters = function () { return [
        { type: ui.StyleRenderer },
        { type: core.ElementRef },
        { type: core.NgZone },
        { type: LyImageCropper },
        { type: undefined, decorators: [{ type: core.Inject, args: [common.DOCUMENT,] }] }
    ]; };
    LyCropperArea.propDecorators = {
        _resizer: [{ type: core.ViewChild, args: ['resizer',] }],
        resizableArea: [{ type: core.Input }],
        keepAspectRatio: [{ type: core.Input }],
        round: [{ type: core.Input }]
    };
    __decorate([
        ui.Style(ɵ0)
    ], LyCropperArea.prototype, "round", void 0);
    function getGesturePointFromEvent(event) {
        // `touches` will be empty for start/end events so we have to fall back to `changedTouches`.
        var point = isTouchEvent(event)
            ? (event.touches[0] || event.changedTouches[0])
            : event;
        return {
            x: point.clientX,
            y: point.clientY
        };
    }
    /** Returns whether an event is a touch event. */
    function isTouchEvent(event) {
        return event.type[0] === 't';
    }

    var LyImageCropperModule = /** @class */ (function () {
        function LyImageCropperModule() {
        }
        return LyImageCropperModule;
    }());
    LyImageCropperModule.decorators = [
        { type: core.NgModule, args: [{
                    imports: [common.CommonModule],
                    exports: [LyImageCropper],
                    declarations: [LyImageCropper, LyCropperArea]
                },] }
    ];

    /**
     * Generated bundle index. Do not edit.
     */

    exports.ImgCropperConfig = ImgCropperConfig;
    exports.LyImageCropper = LyImageCropper;
    exports.LyImageCropperModule = LyImageCropperModule;
    exports.STYLES = STYLES;
    exports._normalizeDegrees = _normalizeDegrees;
    exports.round = round;
    exports.ɵa = LyCropperArea;

    Object.defineProperty(exports, '__esModule', { value: true });

})));
//# sourceMappingURL=alyle-ui-image-cropper.umd.js.map
