UNPKG

@alyle/ui

Version:

Minimal Design, a set of components for Angular

1,670 lines 84 kB
import { __decorate } from 'tslib';
import * as i0 from '@angular/core';
import { EventEmitter, ElementRef, Output, Input, ViewChild, Inject, Directive, booleanAttribute, inject, ChangeDetectionStrategy, Component, ViewEncapsulation, NgModule } from '@angular/core';
import { st2c, LY_COMMON_STYLES, StyleCollection, StyleRenderer, Style } from '@alyle/ui';
import { DOCUMENT, NgIf, NgStyle } from '@angular/common';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { color } from '@alyle/ui/color';
import { BehaviorSubject, Subject, Observable } from 'rxjs';
import { takeUntil, take } from 'rxjs/operators';
import { normalizePassiveListenerOptions } from '@angular/cdk/platform';
import * as i1 from '@angular/cdk/scrolling';

/*
 * 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 = normalizePassiveListenerOptions({ passive: false });
const DATA_IMAGE_SVG_PREFIX = 'data:image/svg+xml;base64,';
/** 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;
        /**
         * Pinch zoom gestures
         * Default: true
         */
        this.hasTouchEvents = true;
    }
}
/** 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 = {}));
var PointerChange;
(function (PointerChange) {
    PointerChange[PointerChange["Down"] = 0] = "Down";
    PointerChange[PointerChange["Up"] = 1] = "Up";
})(PointerChange || (PointerChange = {}));
/** 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 _LyImageCropperBase {
    static { this.и = 'LyImageCropper'; }
    get config() {
        return this._config;
    }
    set config(val) {
        this._config = { ...{}, ...new ImgCropperConfig(), ...val };
        this._initialConfig = { ...{}, ...this._config };
        this._initialAreaWidth = this.config.width;
        this._initialAreaHeight = this.config.height;
        if (this._config.round
            && this.config.width !== this.config.height) {
            throw new Error(`${_LyImageCropperBase.и}: 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;
    }
    constructor(_renderer, _elementRef, cd, _ngZone, _document, viewPortRuler) {
        this._renderer = _renderer;
        this._elementRef = _elementRef;
        this.cd = cd;
        this._ngZone = _ngZone;
        this._imgRect = {};
        this._rotation = 0;
        this._urlsToRevoke = [];
        this._events = new Map();
        /** @private */
        this._isPointerUp = new BehaviorSubject(true);
        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._pendingRotation = 0;
        this.areaGridActiveCssClass = '';
        this._pointerDown = (event) => {
            this._isPointerUp.next(false);
            if (isTouchEvent(event)) {
                if (event.touches.length === 2) {
                    this._isMultiTouching = isTouchEvent(event);
                    // Calculate where the fingers have started on the X and Y axis
                    this._startCenter = getCenterFromTouchEvent(event);
                    this._startDistance = calDistanceFromTouchEvent(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;
            }
            this._ngZone.run(() => {
                this._isSliding = true;
                this.startTransform = {
                    x: this._imgRect.x,
                    y: this._imgRect.y,
                    xOrigin: this._imgRect.xc,
                    yOrigin: this._imgRect.yc
                };
                this._lastPointerEvent = event;
                this._startPointerEvent = getGesturePointFromEvent(event);
                event.preventDefault(); // Prevent page scroll
                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;
                let scaleFix = this._scal3Fix;
                const config = this.config;
                const startP = this.startTransform;
                if (!scaleFix || !startP) {
                    return;
                }
                const point = getGesturePointFromEvent(event);
                let deltaX = 0;
                let deltaY = 0;
                const imgContainer = this._imgCanvas.nativeElement;
                /** Main image width */
                const imgWidth = imgContainer.width;
                /** Main image height */
                const imgHeight = imgContainer.height;
                if (this._isMultiTouching) {
                    const newScale = calDistanceFromTouchEvent(event) / this._startDistance * this._scale;
                    scaleFix = this._scal3Fix = Math.max(newScale, this.minScale);
                    const center = getCenterFromTouchEvent(event);
                    deltaX = center.x - this._startCenter.x;
                    deltaY = center.y - this._startCenter.y;
                }
                else {
                    deltaX = point.x - this._startPointerEvent.x;
                    deltaY = point.y - this._startPointerEvent.y;
                }
                if (!scaleFix || !startP) {
                    return;
                }
                const isMinScaleX = imgWidth * scaleFix < config.width && config.extraZoomOut;
                const isMinScaleY = imgHeight * scaleFix < config.height && config.extraZoomOut;
                const limitLeft = (config.width / 2 / scaleFix) >= startP.xOrigin - (deltaX / scaleFix);
                const limitRight = (config.width / 2 / scaleFix) + (imgWidth) - (startP.xOrigin - (deltaX / scaleFix)) <= config.width / scaleFix;
                const limitTop = ((config.height / 2 / scaleFix) >= (startP.yOrigin - (deltaY / scaleFix)));
                const limitBottom = (((config.height / 2 / scaleFix) + (imgHeight) - (startP.yOrigin - (deltaY / scaleFix))) <= (config.height / scaleFix));
                // Limit for left
                if ((limitLeft && !isMinScaleX) || (!limitLeft && isMinScaleX)) {
                    x = startP.x + (startP.xOrigin) - (config.width / 2 / scaleFix);
                }
                // Limit for right
                if ((limitRight && !isMinScaleX) || (!limitRight && isMinScaleX)) {
                    x = startP.x + (startP.xOrigin) + (config.width / 2 / scaleFix) - imgWidth;
                }
                // Limit for top
                if ((limitTop && !isMinScaleY) || (!limitTop && isMinScaleY)) {
                    y = startP.y + (startP.yOrigin) - (config.height / 2 / scaleFix);
                }
                // Limit for bottom
                if ((limitBottom && !isMinScaleY) || (!limitBottom && isMinScaleY)) {
                    y = startP.y + (startP.yOrigin) + (config.height / 2 / scaleFix) - imgHeight;
                }
                // 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,
                });
            }
        };
        // _mainImageRect(): DOMRect {
        //   return this._mainImage.nativeElement.getBoundingClientRect();
        // }
        /** Called when the user has lifted their pointer. */
        this._pointerUp = (event) => {
            this._isPointerUp.next(true);
            if (this._isSliding) {
                event.preventDefault();
                this._removeGlobalEvents();
                this._isSliding = false;
                this._isMultiTouching = false;
                this._startPointerEvent = null;
                this._scale = this._scal3Fix;
                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._onWheel = (event) => {
            if (!this.isLoaded) {
                return;
            }
            event.preventDefault();
            this._ngZone.run(() => {
                if (Math.sign(event.deltaY) < 0) {
                    this.zoomIn();
                }
                else {
                    this.zoomOut();
                }
            });
        };
        this._document = _document;
        viewPortRuler.change()
            .pipe(takeUntil(this._destroy))
            .subscribe(() => this._ngZone.run(() => this.updateCropperPosition()));
        this._isPointerUp.subscribe((UP) => {
            if (!this.areaGridActiveCssClass) {
                return;
            }
            if (UP) {
                this._renderer.removeClass(this._elementRef.nativeElement, this.areaGridActiveCssClass);
            }
            else {
                this._renderer.addClass(this._elementRef.nativeElement, this.areaGridActiveCssClass);
            }
        });
    }
    ngOnInit() {
        this._ngZone.runOutsideAngular(() => {
            const element = this._imgContainer.nativeElement;
            element.addEventListener('mousedown', this._pointerDown, activeEventOptions);
            element.addEventListener('touchstart', this._pointerDown, activeEventOptions);
        });
    }
    ngAfterViewInit() { }
    ngOnDestroy() {
        this._destroy.next();
        this._destroy.complete();
        const element = this._imgContainer.nativeElement;
        this._lastPointerEvent = null;
        this._removeGlobalEvents();
        element.removeEventListener('mousedown', this._pointerDown, activeEventOptions);
        element.removeEventListener('touchstart', this._pointerDown, activeEventOptions);
        this._removeEventsToScaleWithScroll();
    }
    /** Load image with canvas */
    // private _imgLoaded(imgElement: HTMLImageElement) {
    //   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();
    //   }
    // }
    /** Load image with canvas */
    _loadImageToCanvas(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);
        }
    }
    _setStylesForContImg(values) {
        const newStyles = {};
        if (values.x != null && values.y != null) {
            const rootRect = this._cropperContainerRect();
            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.transform += ` rotate(0)`;
        newStyles.transformOrigin = `${this._imgRect.xc}px ${this._imgRect.yc}px 0`;
        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.clean();
        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, // size in bytes
                type: this.config.type || _img.files[0].type,
                originalDataURL,
                file: _img.files[0]
            });
            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;
        const newSize = (size >= this.minScale) ? 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();
        // this._updateMinScale();
        // this._updateMaxScale(); // TODO: check this
        if (this.isLoaded) {
            if (changed) {
                const originPosition = { ...this._imgRect };
                this.startTransform = {
                    x: originPosition.x,
                    y: originPosition.y,
                    xOrigin: originPosition.xc,
                    yOrigin: originPosition.yc
                };
                this._setStylesForContImg({});
                this._simulatePointerMove();
            }
            else {
                return;
            }
        }
        else if (this.minScale) {
            this._setStylesForContImg({
                ...this._getCenterPoints()
            });
        }
        else {
            return;
        }
        this.scaleChange.emit(size);
        if (!noAutoCrop) {
            this._cropIfAutoCrop();
        }
    }
    _getCenterPoints() {
        const root = this._cropperContainer.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._cropperContainer.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._cropperContainerRect();
        const areaRect = this._areaCropperRect();
        const areaWidth = Math.min(areaRect.width, hostRect.width);
        const areaHeight = Math.min(areaRect.height, hostRect.height);
        let x, y;
        if (xOrigin == null && yOrigin == null) {
            xOrigin = this._imgRect.xc;
            yOrigin = this._imgRect.yc;
        }
        x = Math.max((areaRect.left - hostRect.left), 0);
        y = Math.max(0, (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 scalePercent = this._calcScalePercent(this._scal3Fix, this._minScale, this._maxScale);
        const newScale = scalePercent < 20 ? ((this._scal3Fix * this._imgCanvas.nativeElement.width + 50)
            / (this._imgCanvas.nativeElement.width)) : (this._scal3Fix + .05);
        if (newScale > this.minScale && newScale <= this._maxScale) {
            this.setScale(newScale);
        }
        else {
            this.setScale(this._maxScale);
        }
    }
    _calcScalePercent(num, min, max) {
        return ((num - min) / (max - min)) * 100;
    }
    /** 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.startTransform = 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._initialConfig;
            const canvas = this._imgCanvas.nativeElement;
            canvas.width = 0;
            canvas.height = 0;
            this.cleaned.emit(null);
            this.cd.markForCheck();
        }
    }
    /** - */
    zoomOut() {
        const scalePercent = this._calcScalePercent(this._scal3Fix, this._minScale, this._maxScale);
        const newScale = scalePercent < 20 ? ((this._scal3Fix * this._imgCanvas.nativeElement.width - 50)
            / (this._imgCanvas.nativeElement.width)) : (this._scal3Fix - .05);
        if (newScale > this.minScale && newScale <= this._maxScale) {
            this.setScale(newScale);
        }
        else {
            this.fit();
        }
    }
    center() {
        const newStyles = {
            ...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 }
            : { ...config };
        let src = _config.originalDataURL;
        if (!src) {
            const err = {
                name: _config.name,
                error: ImgCropperError.Other,
                type: _config.type,
                size: _config.size
            };
            this.error.emit(err);
            return;
        }
        this._initialAreaWidth = this._initialConfig.width;
        this._initialAreaHeight = this._initialConfig.height;
        if (_config.areaWidth && _config.areaHeight) {
            this.config.width = _config.areaWidth;
            this.config.height = _config.areaHeight;
        }
        if (_config.originalDataURL && isSvgImage(_config.originalDataURL)) {
            src = normalizeSVG(_config.originalDataURL);
        }
        const cropEvent = { ..._config };
        new Promise((resolve, reject) => {
            const img = createHtmlImg(src);
            this._ngZone.runOutsideAngular(() => {
                img.onerror = err => reject(err);
                img.onabort = err => reject(err);
                img.onload = () => resolve(img);
            });
        })
            .then((img) => {
            this._loadImageToCanvas(img);
            this._updateMinScale(img);
            this._updateMaxScale();
            this._isLoadedImg = true;
            this.imageLoaded.emit(cropEvent);
            this.cd.markForCheck();
            Promise.resolve(null).then(() => {
                setTimeout(() => {
                    this._ngZone.run(() => { this._positionImg(cropEvent, fn); });
                });
            });
        }, () => {
            const err = {
                name: _config.name,
                error: ImgCropperError.Type,
                type: _config.type,
                size: _config.size
            };
            this.error.emit(err);
        });
    }
    _updateAreaIfNeeded() {
        if (!this._config.responsiveArea)
            return;
        const rootRect = this._cropperContainerRect();
        const areaRect = this._areaCropperRect();
        const { minWidth = 1, minHeight = 1, round } = this.config;
        // Calculate maximum dimensions allowed for the area
        const maxWidth = Math.max(rootRect.width, minWidth);
        const maxHeight = Math.max(rootRect.height, minHeight);
        let newWidth = areaRect.width;
        let newHeight = areaRect.height;
        if (round) {
            newWidth = newHeight = Math.min(maxWidth, maxHeight); // Área cuadrada si round es true
        }
        else {
            const shouldResizeWidth = (areaRect.width > maxWidth
                || areaRect.width < this._initialAreaWidth
                || this._areaWidthResized);
            const shouldResizeHeight = (areaRect.height > maxHeight
                || areaRect.height < this._initialAreaHeight
                || this._areaHeightResized);
            let posibleWidth_w = 0;
            let posibleWidth_h = 0;
            let posibleHeight_h = 0;
            let posibleHeight_w = 0;
            if (shouldResizeWidth) {
                newWidth = posibleWidth_w = Math.min(maxWidth, this._areaWidthResized || this._initialAreaWidth);
                newHeight = posibleWidth_h = (newWidth * areaRect.height) / areaRect.width;
            }
            if (shouldResizeHeight) {
                newHeight = posibleHeight_h = Math.min(maxHeight, this._areaHeightResized || this._initialAreaHeight);
                newWidth = posibleHeight_w = (newHeight * areaRect.width) / areaRect.height;
            }
            if (shouldResizeHeight && shouldResizeWidth) {
                if (Math.min(posibleWidth_w, posibleWidth_h) < Math.min(posibleHeight_h, posibleHeight_w)) {
                    newWidth = posibleWidth_w;
                    newHeight = posibleWidth_h;
                }
                else {
                    newHeight = posibleHeight_h;
                    newWidth = posibleHeight_w;
                }
            }
        }
        // Apply changes if dimensions have changed
        if (newWidth !== this.config.width || newHeight !== this.config.height) {
            const newScale = (this._scal3Fix * newWidth) / areaRect.width;
            this.config.width = newWidth;
            this.config.height = newHeight;
            this._updateMinScale();
            this._updateMaxScale();
            this.setScale(newScale, true);
            this._markForCheck();
        }
    }
    /**
     * @private
     */
    _updateAbsoluteScale() {
        const scale = this._scal3Fix / (this.config.width / this._initialAreaWidth);
        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(() => {
                Promise.resolve(null).then(() => {
                    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);
                        if (this.config.hasTouchEvents) {
                            this._addEventsToScaleWithScroll();
                        }
                        else {
                            this._removeEventsToScaleWithScroll();
                        }
                        // tslint:disable-next-line: deprecation
                        this.loaded.emit(cropEvent);
                    });
                });
            });
        }
    }
    rotate2(degrees) {
        this._rotation -= degrees;
        const newStyles = {};
        newStyles.transform = `translate(${(this._imgRect.x)}px,${(this._imgRect.y)}px)`;
        newStyles.transform += ` scale(${this._scal3Fix})`;
        newStyles.transform += ` rotate(${this._rotation}deg)`;
        newStyles.transformOrigin = `${this._imgRect.xc}px ${this._imgRect.yc}px 0`;
        for (const key in newStyles) {
            if (newStyles.hasOwnProperty(key)) {
                this._renderer.setStyle(this._imgContainer.nativeElement, key, newStyles[key]);
            }
        }
    }
    rotate(degrees) {
        _normalizeDegrees(degrees);
        const newRotation = this._rotation + degrees;
        clearTimeout(this._rotateTimeOut);
        this._pendingRotation += degrees;
        this._rotation = newRotation;
        this._rotateWithAnimation();
        this._rotateTimeOut = setTimeout(() => {
            this._setStylesForContImg({});
            this._rotateCanvas();
        }, 140);
    }
    _rotateWithAnimation() {
        const newStyles = {};
        // easeOutQuad
        newStyles.transition = `cubic-bezier(0.250, 0.460, 0.450, 0.940) 140ms`;
        newStyles.transform = `translate(${(this._imgRect.x)}px,${(this._imgRect.y)}px)`;
        newStyles.transform += ` scale(${this._scal3Fix})`;
        newStyles.transform += ` rotate(${this._pendingRotation}deg)`;
        newStyles.transformOrigin = `${this._imgRect.xc}px ${this._imgRect.yc}px 0`;
        for (const key in newStyles) {
            if (newStyles.hasOwnProperty(key)) {
                this._renderer.setStyle(this._imgContainer.nativeElement, key, newStyles[key]);
            }
        }
    }
    _rotateCanvas() {
        let validDegrees = this._pendingRotation;
        const degreesRad = validDegrees * Math.PI / 180;
        const canvas = this._imgCanvas.nativeElement;
        canvas.removeAttribute('style');
        this._pendingRotation = 0;
        this._renderer.removeStyle(this._imgContainer.nativeElement, 'transition');
        const canvasClon = createCanvasImg(canvas);
        const ctx = canvas.getContext('2d');
        // 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;
        canvas.style.opacity = '0';
        // 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._cropperContainerRect();
        this._setStylesForContImg({
            x: (left - rootRect.left),
            y: (top - rootRect.top)
        });
        // keep image inside the frame
        const originPosition = { ...this._imgRect };
        this.startTransform = {
            x: originPosition.x,
            y: originPosition.y,
            xOrigin: originPosition.xc,
            yOrigin: 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);
    }
    /**
     * @private
     */
    _updateMaxScale() {
        const maxScale = (this.config.width / this._initialAreaWidth) * 3;
        this._maxScale = maxScale;
        this.maxScaleChange.emit(maxScale);
    }
    /**
     * Resize & crop image
     */
    crop(config) {
        const newConfig = config
            ? { ...{}, ...(this.config || new ImgCropperConfig()), ...config } : this.config;
        // this._loadImageToCanvas(this._mainImage.nativeElement);
        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);
        }
        // crop
        ctx.drawImage(this._imgCanvas.nativeElement, -(left), -(top));
        const result = canvasElement;
        // TODO: check if the image to be sized is smaller than the crop area
        if (myConfig.output === ImgResolution.Default) {
            const areaWidth = this._areaWidthResized ?? this._initialConfig.width;
            const areaHeight = this._areaHeightResized ?? this._initialConfig.height;
            resizeCanvas(result, areaWidth, areaHeight);
        }
        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._initialAreaWidth,
            areaHeight: this._initialAreaHeight,
            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(): DOMRect {
    //   return this._elementRef.nativeElement.getBoundingClientRect() as DOMRect;
    // }
    _cropperContainerRect() {
        return this._cropperContainer.nativeElement.getBoundingClientRect();
    }
    _areaCropperRect() {
        return this._areaRef.nativeElement.getBoundingClientRect();
    }
    _canvasRect() {
        return this._imgCanvas.nativeElement.getBoundingClientRect();
    }
    _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);
        }
    }
    _addEventsToScaleWithScroll() {
        if (!this._events.has('wheel')) {
            this._events.set('wheel', this._onWheel);
            this._ngZone.runOutsideAngular(() => {
                const element = this._elementRef.nativeElement;
                element.addEventListener('wheel', this._onWheel, activeEventOptions);
            });
        }
    }
    _removeEventsToScaleWithScroll() {
        if (this._events.has('wheel')) {
            this._events.delete('wheel');
            const host = this._elementRef.nativeElement;
            host.removeEventListener('wheel', this._onWheel, activeEventOptions);
        }
    }
    /** Use defaultView of injected document if available or fallback to global window reference */
    _getWindow() {
        return this._document.defaultView || window;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: _LyImageCropperBase, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: DOCUMENT }, { token: i1.ViewportRuler }], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: _LyImageCropperBase, isStandalone: true, inputs: { config: "config", scale: "scale", maxFileSize: "maxFileSize" }, outputs: { scaleChange: "scaleChange", minScaleChange: "minScale", maxScaleChange: "maxScale", loaded: "loaded", imageLoaded: "imageLoaded", ready: "ready", cropped: "cropped", cleaned: "cleaned", error: "error" }, viewQueries: [{ propertyName: "_cropperContainer", first: true, predicate: ["_cropperContainer"], descendants: true, static: true }, { propertyName: "_imgContainer", first: true, predicate: ["_imgContainer"], descendants: true, static: true }, { propertyName: "_areaRef", first: true, predicate: ["_area"], descendants: true, read: ElementRef }, { propertyName: "_imgCanvas", first: true, predicate: ["_imgCanvas"], descendants: true, static: true }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: _LyImageCropperBase, decorators: [{
            type: Directive
        }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [DOCUMENT]
                }] }, { type: i1.ViewportRuler }], propDecorators: { _cropperContainer: [{
                type: ViewChild,
                args: ['_cropperContainer', { static: true }]
            }], _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
            }] } });
/**
 * @dynamic
 */
class _LyCropperAreaBase {
    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;
    }
    // @Style<boolean, LyCropperArea>(
    //   (_value, _media) => ({ after }, selectors: SelectorsFn) => {
    //     const $$ = selectors(STYLES);
    //     return (_className: string) => `${_className}{ ;`;
    //   },
    //   coerceBooleanProperty
    // ) round: BooleanInput;
    constructor(_elementRef, _ngZone, _cropper, _document) {
        this._elementRef = _elementRef;
        this._ngZone = _ngZone;
        this._cropper = _cropper;
        this._pointerDown = (event) => {
            this._cropper._isPointerUp.next(false);
            // 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();
                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._cropperContainerRect();
                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(originX ** 2 + 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)) {
                        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);
                    }
                    if (newHeight > rootRect.height) {
                        newWidth = width / (height / rootRect.height);
                        newHeight = rootRect.height;
                    }
                }
                else {
                    if (newWidth > rootRect.width) {
                        newWidth = rootRect.width;
                    }
                    if (newHeight > rootRect.height) {
                        newHeight = rootRect.height;
                    }
                }
                // round values
                const newWidthRounded = Math.round(newWidth);
                const newHeightRounded = Math.round(newHeight);
                element.style.width = `${newWidthRounded}px`;
                element.style.height = `${newHeightRounded}px`;
                this._currentWidth = newWidthRounded;
                this._currentHeight = newHeightRounded;
            }
        };
        /** Called when the user has lifted their pointer. */
        this._pointerUp = (event) => {
            this._cropper._isPointerUp.next(true);
            const hasChange = this._currentWidth !== this._cropper._initialAreaWidth
                || this._currentHeight !== this._cropper._initialAreaHeight;
            if (this._isSliding && (this._currentWidth != null)) {
                event.preventDefault();
                this._removeGlobalEvents();
                this._cropper._areaWidthResized = hasChange ? this._currentWidth : null;
                this._cropper._areaHeightResized = hasChange ? this._currentHeight : null;
                // this._cropper._initialAreaWidth =
                this._cropper.config.width = this._currentWidth;
                // this._cropper._initialAreaHeight =
                this._cropper.config.height = this._currentHeight;
                this._cropper._updateMinScale();
                this._cropper._updateMaxScale();
                this._cropper._updateAbsoluteScale();
                this._isSliding = false;
                this._startPointerEvent = null;
                this._currentWidth = null;
                this._currentHeight = null;
                this._cropper._markForCheck();
            }
        };
        /** 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;
    }
    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() {
        const element = this._resizer?.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;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: _LyCropperAreaBase, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: _LyImageCropperBase }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: _LyCropperAreaBase, isStandalone: true, inputs: { resizableArea: "resizableArea", keepAspectRatio: "keepAspectRatio", round: "round" }, viewQueries: [{ propertyName: "_resizer", first: true, predicate: ["resizer"], descendants: true }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: _LyCropperAreaBase, decorators: [{
            type: Directive
        }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: _LyImageCropperBase }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [DOCUMENT]
                }] }], propDecorators: { _resizer: [{
                type: ViewChild,
                args: ['resizer']
            }], resizableArea: [{
                type: Input
            }], keepAspectRatio: [{
                type: Input
            }], round: [{
                type: Input
            }, {
                type: Input,
                args: [{ transform: booleanAttribute }]
            }] } });
/**
 * 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;
}
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);
        const blob = new Blob([span.innerHTML], { type: 'image/svg+xml' });
        return URL.createObjectURL(blob);
    }
    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(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';
}
// Calculate distance between two fingers
function calDistanceFromTouchEvent(event) {
    return Math.hypot(event.touches[0].clientX - event.touches[1].clientX, event.touches[0].clientY - event.touches[1].clientY);
}
;
function getCenterFromTouchEvent(event) {
    const x = (event.touches[0].pageX + event.touches[1].pageX) / 2;
    const y = (event.touches[0].pageY + event.touches[1].pageY) / 2;
    return { x, y };
}

const STYLE_PRIORITY = -2;
const pos = (100 * Math.sqrt(2) - 100) / 2 / Math.sqrt(2);
const STYLES = (theme, selectors) => {
    const $$ = selectors(STYLES);
    const { after } = theme;
    const transition = `${theme.animations.curves.acceleration} 100ms`;
    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($$))
                : theme.cropper.root($$)))), `${_className}`)}`,
        cropperContainer: (_className) => `${_className}{position:relative;margin:auto;width:80%;height:80%;}`,
        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);}${st2c((LY_COMMON_STYLES.fill), `${_className}`)}${_className}{margin:auto;}${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;}`,
        grid: (_className) => `${_className}{position:absolute;width:100%;height:100%;opacity:0;transition:${transition};}${_className}::before,${_className}::after{content:' ';box-sizing:border-box;position:absolute;border:1px solid ${color(0xffffff, 0.4)};}${_className}::before{top:0;bottom:0;left:33.33%;right:33.33%;border-top:0;border-bottom:0;}${_className}::after{top:33.33%;bottom:33.33%;left:0;right:0;border-left:0;border-right:0;}`,
        showGrid: () => (_className) => `${_className} ${$$.grid}{opacity:1;}`,
        isPointerUp: null,
        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:30px;height:30px;transform:translate(-35%,-35%);}`,
        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%;}`
    };
};
/**
 * @dynamic
 */
class LyCropperArea extends _LyCropperAreaBase {
    constructor() {
        super(...arguments);
        this.sRenderer = inject(StyleRenderer);
        this.classes = this.sRenderer.renderSheet(STYLES, 'area');
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyCropperArea, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "19.2.10", type: LyCropperArea, isStandalone: true, selector: "ly-cropper-area", inputs: { round: ["round", "round", booleanAttribute] }, providers: [
            StyleRenderer
        ], exportAs: ["lyCropperArea"], usesInheritance: true, ngImport: i0, template: "<div #resizer\n  *ngIf=\"resizableArea\"\n  [class]=\"classes.resizer\"\n>\n</div>\n<div [class]=\"classes.grid\"></div>\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
__decorate([
    Style((_value, _media) => ({ after }, selectors) => {
        const $$ = selectors(STYLES);
        return (_className) => `${_className}{border-radius:50%;}${_className} ${$$.resizer}{${after}:${pos}%;bottom:${pos}%;transform:translate(4px,4px);}${_className} ${$$.grid}{border-radius:50%;overflow:hidden;}`;
    }, coerceBooleanProperty)
], LyCropperArea.prototype, "round", void 0);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyCropperArea, decorators: [{
            type: Component,
            args: [{ selector: 'ly-cropper-area', providers: [
                        StyleRenderer
                    ], changeDetection: ChangeDetectionStrategy.OnPush, exportAs: 'lyCropperArea', standalone: true, imports: [NgIf], template: "<div #resizer\n  *ngIf=\"resizableArea\"\n  [class]=\"classes.resizer\"\n>\n</div>\n<div [class]=\"classes.grid\"></div>\n" }]
        }], propDecorators: { round: [{
                type: Input,
                args: [{
                        transform: booleanAttribute
                    }]
            }] } });
class LyImageCropper extends _LyImageCropperBase {
    constructor() {
        super(...arguments);
        this.sRenderer = inject(StyleRenderer);
        this.classes = this.sRenderer.renderSheet(STYLES, 'root');
        this.areaGridActiveCssClass = this.classes.showGrid;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropper, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: LyImageCropper, isStandalone: true, selector: "ly-img-cropper, ly-image-cropper", providers: [
            StyleRenderer,
            { provide: _LyImageCropperBase, useExisting: LyImageCropper },
        ], usesInheritance: true, ngImport: i0, 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 #_cropperContainer class=\"{{classes.cropperContainer}}\">\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</div>\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", dependencies: [{ kind: "component", type: LyCropperArea, selector: "ly-cropper-area", inputs: ["round"], exportAs: ["lyCropperArea"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropper, decorators: [{
            type: Component,
            args: [{ changeDetection: ChangeDetectionStrategy.OnPush, preserveWhitespaces: false, selector: 'ly-img-cropper, ly-image-cropper', providers: [
                        StyleRenderer,
                        { provide: _LyImageCropperBase, useExisting: LyImageCropper },
                    ], standalone: true, imports: [LyCropperArea, NgStyle, NgIf], 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 #_cropperContainer class=\"{{classes.cropperContainer}}\">\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</div>\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" }]
        }] });

/**
 * @dynamic
 */
class LyCropperAreaBase extends _LyCropperAreaBase {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyCropperAreaBase, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: LyCropperAreaBase, isStandalone: true, selector: "ly-cropper-area-base", host: { classAttribute: "ly-cropper-area" }, exportAs: ["lyCropperAreaBase"], usesInheritance: true, ngImport: i0, template: "@if (resizableArea) {\n  <div #resizer\n    class=\"ly-cropper-area-resizer\"\n  >\n  </div>\n}\n<div class=\"ly-cropper-area-grid\"></div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyCropperAreaBase, decorators: [{
            type: Component,
            args: [{ selector: 'ly-cropper-area-base', changeDetection: ChangeDetectionStrategy.OnPush, exportAs: 'lyCropperAreaBase', standalone: true, host: {
                        'class': 'ly-cropper-area'
                    }, template: "@if (resizableArea) {\n  <div #resizer\n    class=\"ly-cropper-area-resizer\"\n  >\n  </div>\n}\n<div class=\"ly-cropper-area-grid\"></div>\n" }]
        }] });
class LyImageCropperBase extends _LyImageCropperBase {
    constructor() {
        super(...arguments);
        this.areaGridActiveCssClass = 'ly-cropper-area-grid-active';
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropperBase, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: LyImageCropperBase, isStandalone: true, selector: "ly-img-cropper-base, ly-image-cropper-base", host: { classAttribute: "ly-cropper-root" }, providers: [
            { provide: _LyImageCropperBase, useExisting: LyImageCropperBase },
        ], exportAs: ["lyImageCropperBase"], usesInheritance: true, ngImport: i0, 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 #_cropperContainer class=\"ly-cropper-container\">\n  <div #_imgContainer\n    class=\"ly-cropper-img-container\"\n    (selectstart)=\"$event.preventDefault()\"\n  >\n    <canvas #_imgCanvas></canvas>\n  </div>\n  @if (_isLoadedImg) {\n    <ly-cropper-area-base #_area\n      [round]=\"!!config.round\"\n      [resizableArea]=\"!!config.resizableArea\"\n      [keepAspectRatio]=\"!!config.keepAspectRatio\"\n      [ngStyle]=\"{\n        width: config.width + 'px',\n        height: config.height + 'px'\n      }\"></ly-cropper-area-base>\n  } @else {\n    <div class=\"ly-cropper-default-content\">\n      <input #_fileInput type=\"file\" (change)=\"selectInputEvent($event)\" accept=\"image/*\">\n      <ng-content></ng-content>\n    </div>\n  }\n</div>\n", styles: [".ly-cropper-root{-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}.ly-cropper-container{position:relative;margin:auto;width:80%;height:80%}.ly-cropper-img-container{cursor:move;position:absolute;top:0;left:0;display:flex;touch-action:none}.ly-cropper-img-container>canvas{display:block}.ly-cropper-area{pointer-events:none;box-shadow:0 0 0 20000px #0006;position:absolute;inset:0;margin:auto}.ly-cropper-area-round{border-radius:50%}.ly-cropper-area-round.ly-cropper-area-resizer{right:14.64%;bottom:14.64%;transform:translate(4px,4px)}.ly-cropper-area-round.ly-cropper-area-grid{border-radius:50%;overflow:hidden}.ly-cropper-area:before,.ly-cropper-area:after{position:absolute;inset:0;content:\"\"}.ly-cropper-area:before{width:0;height:0;margin:auto;border-radius:50%;background:#fff;border:solid 2px rgb(255,255,255)}.ly-cropper-area:after{border:solid 2px rgb(255,255,255);border-radius:inherit}.ly-cropper-area-grid{position:absolute;width:100%;height:100%;opacity:0;transition:cubic-bezier(.4,0,1,1)}.ly-cropper-area-grid:before,.ly-cropper-area-grid:after{content:\" \";box-sizing:border-box;position:absolute;border:1px solid rgba(255,255,255,.4)}.ly-cropper-area-grid:before{inset:0 33.33%;border-top:0;border-bottom:0}.ly-cropper-area-grid:after{inset:33.33% 0;border-left:0;border-right:0}.ly-cropper-area-grid-active .ly-cropper-area-grid{opacity:1}.ly-cropper-area-resizer{width:10px;height:10px;background:#fff;border-radius:3px;position:absolute;touch-action:none;bottom:0;right:0;pointer-events:all;cursor:nwse-resize}.ly-cropper-area-resizer:before{position:absolute;inset:0;content:\"\";width:30px;height:30px;transform:translate(-35%,-35%)}.ly-cropper-default-content{display:flex;align-items:center;justify-content:center}.ly-cropper-default-content,.ly-cropper-default-content>input{position:absolute;inset:0}.ly-cropper-default-content *:not(input){pointer-events:none}.ly-cropper-default-content>input{background:transparent;opacity:0;width:100%;height:100%}\n"], dependencies: [{ kind: "component", type: LyCropperAreaBase, selector: "ly-cropper-area-base", exportAs: ["lyCropperAreaBase"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropperBase, decorators: [{
            type: Component,
            args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ly-img-cropper-base, ly-image-cropper-base', providers: [
                        { provide: _LyImageCropperBase, useExisting: LyImageCropperBase },
                    ], standalone: true, exportAs: 'lyImageCropperBase', imports: [LyCropperAreaBase, NgStyle], host: {
                        'class': 'ly-cropper-root'
                    }, encapsulation: ViewEncapsulation.None, 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 #_cropperContainer class=\"ly-cropper-container\">\n  <div #_imgContainer\n    class=\"ly-cropper-img-container\"\n    (selectstart)=\"$event.preventDefault()\"\n  >\n    <canvas #_imgCanvas></canvas>\n  </div>\n  @if (_isLoadedImg) {\n    <ly-cropper-area-base #_area\n      [round]=\"!!config.round\"\n      [resizableArea]=\"!!config.resizableArea\"\n      [keepAspectRatio]=\"!!config.keepAspectRatio\"\n      [ngStyle]=\"{\n        width: config.width + 'px',\n        height: config.height + 'px'\n      }\"></ly-cropper-area-base>\n  } @else {\n    <div class=\"ly-cropper-default-content\">\n      <input #_fileInput type=\"file\" (change)=\"selectInputEvent($event)\" accept=\"image/*\">\n      <ng-content></ng-content>\n    </div>\n  }\n</div>\n", styles: [".ly-cropper-root{-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}.ly-cropper-container{position:relative;margin:auto;width:80%;height:80%}.ly-cropper-img-container{cursor:move;position:absolute;top:0;left:0;display:flex;touch-action:none}.ly-cropper-img-container>canvas{display:block}.ly-cropper-area{pointer-events:none;box-shadow:0 0 0 20000px #0006;position:absolute;inset:0;margin:auto}.ly-cropper-area-round{border-radius:50%}.ly-cropper-area-round.ly-cropper-area-resizer{right:14.64%;bottom:14.64%;transform:translate(4px,4px)}.ly-cropper-area-round.ly-cropper-area-grid{border-radius:50%;overflow:hidden}.ly-cropper-area:before,.ly-cropper-area:after{position:absolute;inset:0;content:\"\"}.ly-cropper-area:before{width:0;height:0;margin:auto;border-radius:50%;background:#fff;border:solid 2px rgb(255,255,255)}.ly-cropper-area:after{border:solid 2px rgb(255,255,255);border-radius:inherit}.ly-cropper-area-grid{position:absolute;width:100%;height:100%;opacity:0;transition:cubic-bezier(.4,0,1,1)}.ly-cropper-area-grid:before,.ly-cropper-area-grid:after{content:\" \";box-sizing:border-box;position:absolute;border:1px solid rgba(255,255,255,.4)}.ly-cropper-area-grid:before{inset:0 33.33%;border-top:0;border-bottom:0}.ly-cropper-area-grid:after{inset:33.33% 0;border-left:0;border-right:0}.ly-cropper-area-grid-active .ly-cropper-area-grid{opacity:1}.ly-cropper-area-resizer{width:10px;height:10px;background:#fff;border-radius:3px;position:absolute;touch-action:none;bottom:0;right:0;pointer-events:all;cursor:nwse-resize}.ly-cropper-area-resizer:before{position:absolute;inset:0;content:\"\";width:30px;height:30px;transform:translate(-35%,-35%)}.ly-cropper-default-content{display:flex;align-items:center;justify-content:center}.ly-cropper-default-content,.ly-cropper-default-content>input{position:absolute;inset:0}.ly-cropper-default-content *:not(input){pointer-events:none}.ly-cropper-default-content>input{background:transparent;opacity:0;width:100%;height:100%}\n"] }]
        }] });

class LyImageCropperModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropperModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropperModule, imports: [LyImageCropper, LyCropperArea], exports: [LyImageCropper, LyCropperArea] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropperModule }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropperModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [LyImageCropper, LyCropperArea],
                    exports: [LyImageCropper, LyCropperArea]
                }]
        }] });
class LyImageCropperBaseModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropperBaseModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropperBaseModule, imports: [LyImageCropperBase], exports: [LyImageCropperBase] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropperBaseModule }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyImageCropperBaseModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [LyImageCropperBase],
                    exports: [LyImageCropperBase]
                }]
        }] });

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

export { ImgCropperConfig, ImgCropperError, ImgResolution, LyCropperArea, LyCropperAreaBase, LyImageCropper, LyImageCropperBase, LyImageCropperBaseModule, LyImageCropperModule, PointerChange, STYLES, _LyCropperAreaBase, _LyImageCropperBase, _normalizeDegrees };
//# sourceMappingURL=alyle-ui-image-cropper.mjs.map