import { EventEmitter, Component, ChangeDetectionStrategy, Renderer2, ElementRef, ChangeDetectorRef, NgZone, Inject, ViewChild, Input, Output, NgModule } from '@angular/core';
import { st2c, StyleCollection, LY_COMMON_STYLES, mergeDeep, StyleRenderer, Style } from '@alyle/ui';
import { Subject, Observable } from 'rxjs';
import { takeUntil, take } from 'rxjs/operators';
import { normalizePassiveListenerOptions } from '@angular/cdk/platform';
import { DOCUMENT, CommonModule } from '@angular/common';
import { ViewportRuler } from '@angular/cdk/scrolling';
import { __decorate } from 'tslib';

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

const activeEventOptions$1 = normalizePassiveListenerOptions({ passive: false });
const STYLE_PRIORITY = -2;
const STYLES = (theme, ref) => {
    const cropper = ref.selectorsOf(STYLES);
    const { after } = theme;
    return {
        $name: LyImageCropper.и,
        $priority: STYLE_PRIORITY,
        root: () => (className) => `${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;}${st2c(((theme.cropper
            && theme.cropper.root
            && (theme.cropper.root instanceof StyleCollection
                ? theme.cropper.root.setTransformer(fn => fn(cropper))
                : theme.cropper.root(cropper)))), `${className}`)}`,
        imgContainer: (className) => `${className}{cursor:move;position:absolute;top:0;left:0;display:flex;touch-action:none;}${className} > canvas{display:block;}`,
        overlay: (className) => `${st2c((LY_COMMON_STYLES.fill), `${className}`)}`,
        area: (className) => `${className}{pointer-events:none;box-shadow:0 0 0 20000px rgba(0, 0, 0, 0.4);margin:auto;}${st2c((LY_COMMON_STYLES.fill), `${className}`)}${st2c((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: (className) => `${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'};}${st2c((LY_COMMON_STYLES.fill), `${className}:before`)}${className}:before{content:'';width:20px;height:20px;transform:translate(-25%, -25%);}`,
        defaultContent: (className) => `${className}{display:flex;align-items:center;justify-content:center;}${st2c((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 */
class ImgCropperConfig {
    constructor() {
        /** 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 = ImgResolution.Default;
    }
}
/** Image output */
var ImgResolution;
(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";
})(ImgResolution || (ImgResolution = {}));
/** Image output */
var ImgCropperError;
(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";
})(ImgCropperError || (ImgCropperError = {}));
class LyImageCropper {
    constructor(sRenderer, _renderer, _elementRef, cd, _ngZone, _document, viewPortRuler) {
        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 EventEmitter();
        /** Emits minimum supported image scale */
        this.minScaleChange = new EventEmitter();
        /** Emits maximum supported image scale */
        this.maxScaleChange = new EventEmitter();
        /** @deprecated Emits when the image is loaded, instead use `ready` */
        this.loaded = new EventEmitter();
        /** Emits when the image is loaded */
        this.imageLoaded = new EventEmitter();
        /** Emits when the cropper is ready to be interacted */
        this.ready = new EventEmitter();
        /** On crop new image */
        this.cropped = new EventEmitter();
        /** Emits when the cropper is cleaned */
        this.cleaned = new EventEmitter();
        /** Emit an error when the loaded image is not valid */
        // tslint:disable-next-line: no-output-native
        this.error = new EventEmitter();
        /** Emits whenever the component is destroyed. */
        this._destroy = new Subject();
        this._pointerDown = (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(() => {
                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 = (event) => {
            if (this._isSliding) {
                event.preventDefault();
                this._lastPointerEvent = event;
                let x, y;
                const canvas = this._imgCanvas.nativeElement;
                const scaleFix = this._scal3Fix;
                const config = this.config;
                const startP = this.offset;
                const point = getGesturePointFromEvent$1(event);
                const deltaX = point.x - this._startPointerEvent.x;
                const deltaY = point.y - this._startPointerEvent.y;
                if (!scaleFix || !startP) {
                    return;
                }
                const isMinScaleY = canvas.height * scaleFix < config.height && config.extraZoomOut;
                const isMinScaleX = canvas.width * scaleFix < config.width && config.extraZoomOut;
                const limitLeft = (config.width / 2 / scaleFix) >= startP.left - (deltaX / scaleFix);
                const limitRight = (config.width / 2 / scaleFix) + (canvas.width) - (startP.left - (deltaX / scaleFix)) <= config.width / scaleFix;
                const limitTop = ((config.height / 2 / scaleFix) >= (startP.top - (deltaY / scaleFix)));
                const 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, y
                });
            }
        };
        /** Called when the user has lifted their pointer. */
        this._pointerUp = (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 = () => {
            // 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(takeUntil(this._destroy))
            .subscribe(() => this._ngZone.run(() => this.updateCropperPosition()));
    }
    get config() {
        return this._config;
    }
    set config(val) {
        this._config = mergeDeep({}, new ImgCropperConfig(), val);
        this._configPrimary = 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\``);
        }
        const maxFileSize = this._config.maxFileSize;
        if (maxFileSize) {
            this.maxFileSize = maxFileSize;
        }
    }
    /** Set scale */
    get scale() {
        return this._scale;
    }
    set scale(val) {
        this.setScale(val);
    }
    /** Get min scale */
    get minScale() {
        return this._minScale;
    }
    ngOnInit() {
        this._ngZone.runOutsideAngular(() => {
            const element = this._imgContainer.nativeElement;
            element.addEventListener('mousedown', this._pointerDown, activeEventOptions$1);
            element.addEventListener('touchstart', this._pointerDown, activeEventOptions$1);
        });
    }
    ngOnDestroy() {
        this._destroy.next();
        this._destroy.complete();
        const 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 */
    _imgLoaded(imgElement) {
        if (imgElement) {
            this._img = imgElement;
            const canvas = this._imgCanvas.nativeElement;
            canvas.width = imgElement.width;
            canvas.height = imgElement.height;
            const 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();
        }
    }
    _setStylesForContImg(values) {
        const newStyles = {};
        if (values.x != null && values.y != null) {
            const rootRect = this._rootRect();
            const x = rootRect.width / 2 - (values.x);
            const 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 (const 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
     */
    updateCropperPosition() {
        if (this.isLoaded) {
            this.updatePosition();
            this._updateAreaIfNeeded();
        }
    }
    /** Load Image from input event */
    selectInputEvent(img) {
        this._currentInputElement = img.target;
        const _img = img.target;
        if (_img.files && _img.files.length !== 1) {
            return;
        }
        const fileSize = _img.files[0].size;
        const fileName = _img.value.replace(/.*(\/|\\)/, '');
        if (this.maxFileSize && fileSize > this.maxFileSize) {
            const cropEvent = {
                name: fileName,
                type: _img.files[0].type,
                size: fileSize,
                error: ImgCropperError.Size
            };
            this.clean();
            this.error.emit(cropEvent);
            return;
        }
        new Observable(observer => {
            const reader = new FileReader();
            reader.onerror = err => observer.error(err);
            reader.onabort = err => observer.error(err);
            reader.onload = (ev) => setTimeout(() => {
                observer.next(ev);
                observer.complete();
            });
            reader.readAsDataURL(_img.files[0]);
        })
            .pipe(take(1), takeUntil(this._destroy))
            .subscribe((loadEvent) => {
            const originalDataURL = loadEvent.target.result;
            this.loadImage({
                name: fileName,
                size: _img.files[0].size,
                type: this.config.type || _img.files[0].type,
                originalDataURL
            });
            this.cd.markForCheck();
        }, () => {
            const cropEvent = {
                name: fileName,
                size: fileSize,
                error: 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 */
    setScale(size, noAutoCrop) {
        // fix min scale
        const newSize = size >= this.minScale && size <= 1 ? size : this.minScale;
        // check
        const 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) {
                const 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();
        }
    }
    _getCenterPoints() {
        const root = this._elementRef.nativeElement;
        const img = this._imgCanvas.nativeElement;
        const x = (root.offsetWidth - (img.width)) / 2;
        const y = (root.offsetHeight - (img.height)) / 2;
        return {
            x,
            y
        };
    }
    /**
     * Fit to screen
     */
    fitToScreen() {
        const container = this._elementRef.nativeElement;
        const min = {
            width: container.offsetWidth,
            height: container.offsetHeight
        };
        const { width, height } = this._img;
        const minScale = {
            width: min.width / width,
            height: min.height / height
        };
        const result = Math.max(minScale.width, minScale.height);
        this.setScale(result);
    }
    fit() {
        this.setScale(this.minScale);
    }
    /**
     * Simulate pointerMove with clientX = 0 and clientY = 0,
     * this is used by `setScale` and `rotate`
     */
    _simulatePointerMove() {
        this._isSliding = true;
        this._startPointerEvent = {
            x: 0,
            y: 0
        };
        this._pointerMove({
            clientX: 0,
            clientY: 0,
            type: 'n',
            preventDefault: () => { }
        });
        this._isSliding = false;
        this._startPointerEvent = null;
    }
    _markForCheck() {
        this.cd.markForCheck();
    }
    updatePosition(xOrigin, yOrigin) {
        const hostRect = this._rootRect();
        const areaRect = this._areaCropperRect();
        const areaWidth = areaRect.width > hostRect.width
            ? hostRect.width
            : areaRect.width;
        const areaHeight = areaRect.height > hostRect.height
            ? hostRect.height
            : areaRect.height;
        let 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, y
        });
    }
    _slideEnd() {
        this._cropIfAutoCrop();
    }
    _cropIfAutoCrop() {
        if (this.config.autoCrop) {
            this.crop();
        }
    }
    /** + */
    zoomIn() {
        const scale = this._scal3Fix + .05;
        if (scale > this.minScale && scale <= this._maxScale) {
            this.setScale(scale);
        }
        else {
            this.setScale(this._maxScale);
        }
    }
    /** Clean the img cropper */
    clean() {
        // 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;
            const canvas = this._imgCanvas.nativeElement;
            canvas.width = 0;
            canvas.height = 0;
            this.cleaned.emit(null);
            this.cd.markForCheck();
        }
    }
    /** - */
    zoomOut() {
        const scale = this._scal3Fix - .05;
        if (scale > this.minScale && scale <= this._maxScale) {
            this.setScale(scale);
        }
        else {
            this.fit();
        }
    }
    center() {
        const 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
     */
    loadImage(config, fn) {
        this.clean();
        const _config = this._currentLoadConfig = typeof config === 'string'
            ? { originalDataURL: config }
            : Object.assign({}, config);
        let 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);
        const img = createHtmlImg(src);
        const cropEvent = Object.assign({}, _config);
        new Observable(observer => {
            img.onerror = err => observer.error(err);
            img.onabort = err => observer.error(err);
            img.onload = () => observer.next(null);
        })
            .pipe(take(1), takeUntil(this._destroy))
            .subscribe(() => {
            this._imgLoaded(img);
            this._isLoadedImg = true;
            this.imageLoaded.emit(cropEvent);
            this.cd.markForCheck();
            this._ngZone.runOutsideAngular(() => {
                this._ngZone
                    .onStable
                    .asObservable()
                    .pipe(take(1), takeUntil(this._destroy))
                    .subscribe(() => setTimeout(() => this._ngZone.run(() => this._positionImg(cropEvent, fn))));
            });
        }, () => {
            const error = {
                name: _config.name,
                error: ImgCropperError.Type,
                type: _config.type,
                size: _config.size
            };
            this.error.emit(error);
        });
    }
    _updateAreaIfNeeded() {
        if (!this._config.responsiveArea) {
            return;
        }
        const rootRect = this._rootRect();
        const areaRect = this._areaCropperRect();
        const minWidth = this.config.minWidth || 1;
        const minHeight = this.config.minHeight || 1;
        if (!(areaRect.width > rootRect.width
            || areaRect.height > rootRect.height
            || areaRect.width < this._primaryAreaWidth
            || areaRect.height < this._primaryAreaHeight)) {
            return;
        }
        const areaWidthConf = Math.max(this.config.width, minWidth);
        const areaWidthMax = Math.max(rootRect.width, minWidth);
        const minHost = Math.min(Math.max(rootRect.width, minWidth), Math.max(rootRect.height, minHeight));
        const currentScale = this._scal3Fix;
        let newScale = 0;
        const 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();
            }
        }
    }
    _updateAbsoluteScale() {
        const 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
     */
    setImageUrl(src, fn) {
        this.loadImage(src, fn);
    }
    _positionImg(cropEvent, fn) {
        const 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(() => {
                this._ngZone
                    .onStable
                    .asObservable()
                    .pipe(take(1), takeUntil(this._destroy))
                    .subscribe(() => {
                    if (loadConfig.xOrigin != null && loadConfig.yOrigin != null) {
                        this.updatePosition(loadConfig.xOrigin, loadConfig.yOrigin);
                    }
                    this._updateAreaIfNeeded();
                    this.isLoaded = true;
                    this._cropIfAutoCrop();
                    this._ngZone.run(() => {
                        this._markForCheck();
                        this.ready.emit(cropEvent);
                        // tslint:disable-next-line: deprecation
                        this.loaded.emit(cropEvent);
                    });
                });
            });
        }
    }
    rotate(degrees) {
        let validDegrees = _normalizeDegrees(degrees);
        // If negative convert to positive
        if (validDegrees < 0) {
            validDegrees += 360;
        }
        const newRotation = _normalizeDegrees((this._rotation || 0) + validDegrees);
        if (newRotation === this._rotation) {
            return;
        }
        const degreesRad = validDegrees * Math.PI / 180;
        const canvas = this._imgCanvas.nativeElement;
        const canvasClon = createCanvasImg(canvas);
        const ctx = canvas.getContext('2d');
        this._rotation = newRotation;
        // clear
        ctx.clearRect(0, 0, canvasClon.width, canvasClon.height);
        // rotate canvas image
        const transform = `rotate(${validDegrees}deg) scale(${1 / this._scal3Fix})`;
        const 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;
        const { left, top } = canvas.getBoundingClientRect();
        // save rect
        const canvasRect = canvas.getBoundingClientRect();
        // remove rotate styles
        canvas.removeAttribute('style');
        // set w & h
        const w = canvasRect.width;
        const 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
        const rootRect = this._rootRect();
        this._setStylesForContImg({
            x: (left - rootRect.left),
            y: (top - rootRect.top)
        });
        // keep image inside the frame
        const 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();
    }
    _updateMinScale(canvas) {
        if (!canvas) {
            canvas = this._imgCanvas.nativeElement;
        }
        const config = this.config;
        const minScale = (config.extraZoomOut ? Math.min : Math.max)(config.width / canvas.width, config.height / canvas.height);
        this._minScale = minScale;
        this.minScaleChange.emit(minScale);
    }
    _updateMaxScale() {
        const maxScale = (this.config.width / this._primaryAreaWidth);
        this._maxScale = maxScale;
        this.maxScaleChange.emit(maxScale);
    }
    /**
     * Resize & crop image
     */
    crop(config) {
        const newConfig = config
            ? mergeDeep({}, this.config || new ImgCropperConfig(), config) : this.config;
        const cropEvent = this._imgCrop(newConfig);
        this.cd.markForCheck();
        return cropEvent;
    }
    /**
     * @docs-private
     */
    _imgCrop(myConfig) {
        const canvasElement = document.createElement('canvas');
        const areaRect = this._areaCropperRect();
        const canvasRect = this._canvasRect();
        const scaleFix = this._scal3Fix;
        const left = (areaRect.left - canvasRect.left) / scaleFix;
        const top = (areaRect.top - canvasRect.top) / scaleFix;
        const { output } = myConfig;
        const currentImageLoadConfig = this._currentLoadConfig;
        const area = {
            width: myConfig.width,
            height: myConfig.height
        };
        canvasElement.width = area.width / scaleFix;
        canvasElement.height = area.height / scaleFix;
        const 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));
        const result = canvasElement;
        if (myConfig.output === 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) {
                const newHeight = area.height * output.width / area.width;
                resizeCanvas(result, output.width, newHeight);
            }
            else if (output.height) {
                const newWidth = area.width * output.height / area.height;
                resizeCanvas(result, newWidth, output.height);
            }
        }
        const type = currentImageLoadConfig.originalDataURL.startsWith('http')
            ? currentImageLoadConfig.type || myConfig.type
            : myConfig.type || currentImageLoadConfig.type;
        const dataURL = result.toDataURL(type);
        const cropEvent = {
            dataURL,
            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;
    }
    _rootRect() {
        return this._elementRef.nativeElement.getBoundingClientRect();
    }
    _areaCropperRect() {
        return this._areaRef.nativeElement.getBoundingClientRect();
    }
    _canvasRect() {
        return this._imgCanvas.nativeElement.getBoundingClientRect();
    }
    _bindGlobalEvents(triggerEvent) {
        const element = this._document;
        const isTouch = isTouchEvent$1(triggerEvent);
        const moveEventName = isTouch ? 'touchmove' : 'mousemove';
        const 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);
        }
        const window = this._getWindow();
        if (typeof window !== 'undefined' && window) {
            window.addEventListener('blur', this._windowBlur);
        }
    }
    /** Removes any global event listeners that we may have added. */
    _removeGlobalEvents() {
        const 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);
        const 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 */
    _getWindow() {
        return this._document.defaultView || window;
    }
}
LyImageCropper.и = 'LyImageCropper';
LyImageCropper.decorators = [
    { type: Component, args: [{
                changeDetection: 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: [
                    StyleRenderer
                ]
            },] }
];
LyImageCropper.ctorParameters = () => [
    { type: StyleRenderer },
    { type: Renderer2 },
    { type: ElementRef },
    { type: ChangeDetectorRef },
    { type: NgZone },
    { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
    { type: ViewportRuler }
];
LyImageCropper.propDecorators = {
    _imgContainer: [{ type: ViewChild, args: ['_imgContainer', { static: true },] }],
    _areaRef: [{ type: ViewChild, args: ['_area', {
                    read: ElementRef
                },] }],
    _imgCanvas: [{ type: ViewChild, args: ['_imgCanvas', { static: true },] }],
    config: [{ type: Input }],
    scale: [{ type: Input }],
    maxFileSize: [{ type: Input }],
    scaleChange: [{ type: Output }],
    minScaleChange: [{ type: Output, args: ['minScale',] }],
    maxScaleChange: [{ type: Output, args: ['maxScale',] }],
    loaded: [{ type: Output }],
    imageLoaded: [{ type: Output }],
    ready: [{ type: Output }],
    cropped: [{ type: Output }],
    cleaned: [{ type: Output }],
    error: [{ type: Output }]
};
/**
 * Normalize degrees for cropper rotation
 * @docs-private
 */
function _normalizeDegrees(n) {
    const 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
    const newCanvas = document.createElement('canvas');
    const 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;
}
const DATA_IMAGE_SVG_PREFIX = 'data:image/svg+xml;base64,';
function normalizeSVG(dataURL) {
    if (window.atob && isSvgImage(dataURL)) {
        const len = dataURL.length / 5;
        const text = window.atob(dataURL.replace(DATA_IMAGE_SVG_PREFIX, ''));
        const span = document.createElement('span');
        span.innerHTML = text;
        const svg = span.querySelector('svg');
        span.setAttribute('style', 'display:none');
        document.body.appendChild(span);
        const width = parseFloat(getComputedStyle(svg).width) || 1;
        const height = parseFloat(getComputedStyle(svg).height) || 1;
        const max = Math.max(width, height);
        svg.setAttribute('width', `${len / (width / max)}px`);
        svg.setAttribute('height', `${len / (height / max)}px`);
        const 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) {
    const 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`.
    const 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);
}

const activeEventOptions = normalizePassiveListenerOptions({ passive: false });
const pos = (100 * Math.sqrt(2) - 100) / 2 / Math.sqrt(2);
const ɵ0 = (_value, _, { classes: __ }) => ({ after }) => (className) => `${className}{border-radius:50%;}${className} .${__.resizer}{${after}:${pos}%;bottom:${pos}%;transform:translate(4px, 4px);}`;
/**
 * @dynamic
 */
class LyCropperArea {
    constructor(sRenderer, _elementRef, _ngZone, _cropper, _document) {
        this.sRenderer = sRenderer;
        this._elementRef = _elementRef;
        this._ngZone = _ngZone;
        this._cropper = _cropper;
        this.classes = this.sRenderer.renderSheet(STYLES, 'area');
        this._pointerDown = (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(() => {
                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 = (event) => {
            if (this._isSliding) {
                event.preventDefault();
                this._lastPointerEvent = event;
                const element = this._elementRef.nativeElement;
                const { width, height, minWidth, minHeight } = this._cropper.config;
                const point = getGesturePointFromEvent(event);
                const deltaX = point.x - this._startPointerEvent.x;
                const deltaY = point.y - this._startPointerEvent.y;
                const startAreaRect = this._startAreaRect;
                const startImgRect = this._startImgRect;
                const round = this.round;
                const keepAspectRatio = this._cropper.config.keepAspectRatio || event.shiftKey;
                let newWidth = 0;
                let newHeight = 0;
                const rootRect = this._cropper._rootRect();
                if (round) {
                    // The distance from the center of the cropper area to the pointer
                    const originX = ((width / 2 / Math.sqrt(2)) + deltaX);
                    const originY = ((height / 2 / Math.sqrt(2)) + deltaY);
                    // Leg
                    const 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
                const centerX = startAreaRect.x + startAreaRect.width / 2;
                const centerY = startAreaRect.y + startAreaRect.height / 2;
                const topOverflow = startImgRect.y > centerY - (newHeight / 2);
                const bottomOverflow = centerY + (newHeight / 2) > startImgRect.bottom;
                const minHeightOnOverflow = Math.min((centerY - startImgRect.y) * 2, (startImgRect.bottom - centerY) * 2);
                const leftOverflow = startImgRect.x > centerX - (newWidth / 2);
                const rightOverflow = centerX + (newWidth / 2) > startImgRect.right;
                const minWidthOnOverflow = Math.min((centerX - startImgRect.x) * 2, (startImgRect.right - centerX) * 2);
                const minOnOverflow = Math.min(minWidthOnOverflow, minHeightOnOverflow);
                if (round) {
                    if (topOverflow || bottomOverflow || leftOverflow || rightOverflow) {
                        newHeight = newWidth = minOnOverflow;
                    }
                }
                else if (keepAspectRatio) {
                    const newNewWidth = [];
                    const 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(...newNewWidth);
                    }
                    if (newNewHeight.length === 2) {
                        newHeight = Math.min(...newNewHeight);
                    }
                }
                else {
                    if (topOverflow || bottomOverflow) {
                        newHeight = minHeightOnOverflow;
                    }
                    if (leftOverflow || rightOverflow) {
                        newWidth = minWidthOnOverflow;
                    }
                }
                // Do not overflow the container
                if (round) {
                    const 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 = (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 = () => {
            // 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;
    }
    set resizableArea(val) {
        if (val !== this._resizableArea) {
            this._resizableArea = val;
            Promise.resolve(null).then(() => {
                if (val) {
                    this._removeResizableArea();
                    this._addResizableArea();
                }
                else {
                    this._removeResizableArea();
                }
            });
        }
    }
    get resizableArea() {
        return this._resizableArea;
    }
    ngOnDestroy() {
        this._removeResizableArea();
    }
    _addResizableArea() {
        this._ngZone.runOutsideAngular(() => {
            const element = this._resizer.nativeElement;
            element.addEventListener('mousedown', this._pointerDown, activeEventOptions);
            element.addEventListener('touchstart', this._pointerDown, activeEventOptions);
        });
    }
    _removeResizableArea() {
        var _a;
        const 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);
        }
    }
    _bindGlobalEvents(triggerEvent) {
        const element = this._document;
        const isTouch = isTouchEvent(triggerEvent);
        const moveEventName = isTouch ? 'touchmove' : 'mousemove';
        const endEventName = isTouch ? 'touchend' : 'mouseup';
        element.addEventListener(moveEventName, this._pointerMove, activeEventOptions);
        element.addEventListener(endEventName, this._pointerUp, activeEventOptions);
        if (isTouch) {
            element.addEventListener('touchcancel', this._pointerUp, activeEventOptions);
        }
        const window = this._getWindow();
        if (typeof window !== 'undefined' && window) {
            window.addEventListener('blur', this._windowBlur);
        }
    }
    /** Removes any global event listeners that we may have added. */
    _removeGlobalEvents() {
        const 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);
        const 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 */
    _getWindow() {
        return this._document.defaultView || window;
    }
}
LyCropperArea.decorators = [
    { type: Component, args: [{
                selector: 'ly-cropper-area',
                template: "<div #resizer\n  *ngIf=\"resizableArea\"\n  [class]=\"classes.resizer\"\n></div>",
                providers: [
                    StyleRenderer
                ],
                changeDetection: ChangeDetectionStrategy.OnPush,
                exportAs: 'lyCropperArea'
            },] }
];
LyCropperArea.ctorParameters = () => [
    { type: StyleRenderer },
    { type: ElementRef },
    { type: NgZone },
    { type: LyImageCropper },
    { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
];
LyCropperArea.propDecorators = {
    _resizer: [{ type: ViewChild, args: ['resizer',] }],
    resizableArea: [{ type: Input }],
    keepAspectRatio: [{ type: Input }],
    round: [{ type: Input }]
};
__decorate([
    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`.
    const 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';
}

class LyImageCropperModule {
}
LyImageCropperModule.decorators = [
    { type: NgModule, args: [{
                imports: [CommonModule],
                exports: [LyImageCropper],
                declarations: [LyImageCropper, LyCropperArea]
            },] }
];

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

export { ImgCropperConfig, ImgCropperError, ImgResolution, LyImageCropper, LyImageCropperModule, STYLES, _normalizeDegrees, round, LyCropperArea as ɵa };
//# sourceMappingURL=alyle-ui-image-cropper.js.map
