import * as i0 from '@angular/core';
import { inject, ElementRef, DOCUMENT, DestroyRef, Renderer2, input, numberAttribute, Directive, viewChild, Component } from '@angular/core';
import { Slider, SliderThumb } from '@ngstarter-ui/components/slider';
import * as i1 from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { fromEvent } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Icon } from '@ngstarter-ui/components/icon';
import { Button } from '@ngstarter-ui/components/button';

class DragImageDirective {
    _elementRef = inject(ElementRef);
    _document = inject(DOCUMENT);
    _destroyRef = inject(DestroyRef);
    _renderer = inject(Renderer2);
    _dragging = false;
    _startClientY = 0;
    _startClientX = 0;
    _offsetY = 0;
    _offsetX = 0;
    _tmpOffsetY = 0;
    _tmpOffsetX = 0;
    _imageLoaded = false;
    scale = input.required({ ...(ngDevMode ? { debugName: "scale" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    content = input.required(...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
    onLoad() {
        this._imageLoaded = true;
    }
    ngOnInit() {
        const image = this._elementRef.nativeElement;
        fromEvent(image, 'mousedown')
            .pipe(takeUntilDestroyed(this._destroyRef))
            .subscribe((event) => {
            this._dragging = true;
            this._startClientY = event.clientY;
            this._startClientX = event.clientX;
        });
        fromEvent(this._document, 'mousemove')
            .pipe(takeUntilDestroyed(this._destroyRef))
            .subscribe((event) => {
            if (this._dragging) {
                const scaleFactor = (1 / this.scale());
                let offsetY = (event.clientY - this._startClientY) * scaleFactor;
                let offsetX = (event.clientX - this._startClientX) * scaleFactor;
                this._transform(offsetY, offsetX);
            }
        });
        fromEvent(this._document, 'mouseup')
            .pipe(takeUntilDestroyed(this._destroyRef))
            .subscribe((event) => {
            if (this._dragging) {
                this._dragging = false;
                this._offsetY = this._tmpOffsetY;
                this._offsetX = this._tmpOffsetX;
            }
        });
    }
    ngOnChanges(changes) {
        if (!changes['scale'].firstChange) {
            if (!this._imageLoaded) {
                return;
            }
            this._transform(0, 0);
            this._offsetY = this._tmpOffsetY;
            this._offsetX = this._tmpOffsetX;
        }
    }
    onImageLoad(event) {
        this._imageLoaded = true;
    }
    getDataUrl() {
        return this._getCanvas().toDataURL('png', 100);
    }
    toBlob(callback) {
        return this.getCanvas().toBlob(callback, 'png', 100);
    }
    getCanvas() {
        return this._getCanvas();
    }
    _getCanvas() {
        const image = this._elementRef.nativeElement;
        const canvas = this._document.createElement('canvas');
        canvas.width = 300;
        canvas.height = 300;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(image, -((image.width * this.scale() - 300) / 2) + this._offsetX * this.scale(), -((image.height * this.scale() - 300) / 2) + this._offsetY * this.scale(), image.width * this.scale(), image.height * this.scale());
        return canvas;
    }
    _transform(offsetY, offsetX) {
        const image = this._elementRef.nativeElement;
        const scaleFactor = (1 / this.scale());
        let translateX = this._offsetX + offsetX;
        let offsetStartX = ((image.width / 2) - translateX) / scaleFactor;
        let offsetEndX = ((image.width / 2) + translateX) / scaleFactor;
        let translateY = this._offsetY + offsetY;
        let offsetStartY = ((image.height / 2) - translateY) / scaleFactor;
        let offsetEndY = ((image.height / 2) + translateY) / scaleFactor;
        let thumbHalfWidth = 150;
        if (offsetStartX <= thumbHalfWidth && translateX > 0) {
            translateX = (image.width / 2) - (thumbHalfWidth * scaleFactor);
        }
        else if (offsetEndX <= thumbHalfWidth && translateX < 0) {
            translateX = -((image.width / 2) - (thumbHalfWidth * scaleFactor));
        }
        if (offsetStartY <= thumbHalfWidth && translateY > 0) {
            translateY = (image.height / 2) - (thumbHalfWidth * scaleFactor);
        }
        else if (offsetEndY <= thumbHalfWidth && translateY < 0) {
            translateY = -((image.height / 2) - (thumbHalfWidth * scaleFactor));
        }
        this._tmpOffsetY = translateY;
        this._tmpOffsetX = translateX;
        this._renderer.setStyle(image, 'transform', `translate(${translateX}px,${translateY}px)`);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: DragImageDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.4", type: DragImageDirective, isStandalone: true, selector: "[ngsDragImage]", inputs: { scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: true, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "load": "onLoad()" } }, usesOnChanges: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: DragImageDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngsDragImage]',
                    standalone: true,
                    host: {
                        '(load)': 'onLoad()'
                    }
                }]
        }], propDecorators: { scale: [{ type: i0.Input, args: [{ isSignal: true, alias: "scale", required: true }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: true }] }] } });

class ThumbnailMaker {
    _content = viewChild.required('content');
    _dragImage = viewChild.required(DragImageDirective);
    _thumbnailSize = 300;
    src = input.required(...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
    helperText = input('', ...(ngDevMode ? [{ debugName: "helperText" }] : /* istanbul ignore next */ []));
    get api() {
        return {
            getDataUrl: () => this._dragImage().getDataUrl(),
            toBlob: (callback) => this._dragImage().toBlob(callback),
            getCanvas: () => this._dragImage().getCanvas(),
            increase: () => this.increase(),
            decrease: () => this.decrease()
        };
    }
    scale = 0;
    min = 1;
    max = 100;
    loading = true;
    alreadyDragged = false;
    get isEqualsToMinScale() {
        return this.scale <= this.min / 100;
    }
    get isEqualsToMaxScale() {
        return this.scale >= this.max / 100;
    }
    onLoad(event) {
        const contentEl = this._content().nativeElement;
        const target = event.target;
        const heightScale = this._thumbnailSize / target.height;
        const widthScale = this._thumbnailSize / target.width;
        const minScale = Math.max(heightScale, widthScale);
        this.scale = minScale;
        this.min = minScale * 100;
        this.loading = false;
    }
    onDragStart(event) {
        event.stopPropagation();
        event.preventDefault();
        this.alreadyDragged = true;
    }
    onScaleChange($event) {
        this.scale = $event / 100;
    }
    increase() {
        if ((this.scale + .1) * 100 <= this.max) {
            this.scale += .1;
        }
        else {
            this.scale = this.max / 100;
        }
    }
    decrease() {
        if ((this.scale - .1) * 100 >= this.min) {
            this.scale -= .1;
        }
        else {
            this.scale = this.min / 100;
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ThumbnailMaker, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: ThumbnailMaker, isStandalone: true, selector: "ngs-thumbnail-maker", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: true, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.loading": "loading" }, classAttribute: "ngs-thumbnail-maker" }, viewQueries: [{ propertyName: "_content", first: true, predicate: ["content"], descendants: true, isSignal: true }, { propertyName: "_dragImage", first: true, predicate: DragImageDirective, descendants: true, isSignal: true }], exportAs: ["ngsThumbnailMaker"], ngImport: i0, template: "@if (helperText() && !alreadyDragged) {\n  <div class=\"helper-text\">\n    <ngs-icon name=\"fluent:hand-draw-24-regular\" class=\"-ms-0.5\"/>\n    {{ helperText() }}\n  </div>\n}\n\n<div #content class=\"content\" (dragstart)=\"onDragStart($event)\">\n  <img [src]=\"src()\" alt=\"\" class=\"image\"\n       (load)=\"onLoad($event)\" [style.scale]=\"scale\"\n       ngsDragImage [scale]=\"scale\" [content]=\"content\">\n</div>\n<div class=\"controls mx-auto w-max flex items-center gap-3\">\n  <button ngsIconButton (click)=\"decrease()\" [disabled]=\"isEqualsToMinScale\">\n    <ngs-icon name=\"fluent:subtract-24-regular\"/>\n  </button>\n  <div class=\"w-[300px] range-slider -ms-3\">\n    <ngs-slider class=\"!w-full\" [min]=\"min\" [max]=\"max\">\n      <input ngsSliderThumb [ngModel]=\"scale * 100\" (ngModelChange)=\"onScaleChange($event)\">\n    </ngs-slider>\n  </div>\n  <button ngsIconButton (click)=\"increase()\" [disabled]=\"isEqualsToMaxScale\">\n    <ngs-icon name=\"fluent:add-24-regular\"/>\n  </button>\n</div>\n", styles: [":host{--ngs-thumbnail-width: 720px;--ngs-thumbnail-height: 460px;display:block;width:max-content;overflow:hidden;position:relative}:host .content{display:flex;width:var(--ngs-thumbnail-width);height:var(--ngs-thumbnail-height);-webkit-mask-image:radial-gradient(circle,#000 150px,#00000080 150px);mask-image:radial-gradient(circle,#000 150px,#00000080 150px);align-items:center;justify-content:center;overflow:hidden;line-height:1;position:relative;-webkit-user-select:none;user-select:none}:host .image{object-fit:fill;max-width:none;max-height:none;line-height:1;-webkit-user-select:none;user-select:none;cursor:move}:host .helper-text{position:absolute;z-index:1;top:calc(var(--spacing, .25rem) * 5);inset-inline-start:50%;background:var(--ngs-color-neutral-950);color:#fff;border-radius:var(--ngs-radius-lg);padding:calc(var(--spacing, .25rem) * 2) calc(var(--spacing, .25rem) * 3);font-size:var(--ngs-font-size-xs);opacity:90%;width:max-content;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);transform:translate(-50%)}:host .controls{margin-top:calc(var(--spacing, .25rem) * 3);margin-bottom:calc(var(--spacing, .25rem) * 3)}:host.loading .image{visibility:hidden;position:relative;z-index:-1}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: Slider, selector: "ngs-slider", inputs: ["disabled", "discrete", "showTickMarks", "min", "max", "step", "displayWith"], exportAs: ["ngsSlider"] }, { kind: "directive", type: SliderThumb, selector: "input[ngsSliderThumb]", inputs: ["value"], outputs: ["valueChange"], exportAs: ["ngsSliderThumb"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: DragImageDirective, selector: "[ngsDragImage]", inputs: ["scale", "content"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: Button, selector: "    button[ngsButton], button[ngsIconButton],    a[ngsButton], a[ngsIconButton]  ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ThumbnailMaker, decorators: [{
            type: Component,
            args: [{ selector: 'ngs-thumbnail-maker', exportAs: 'ngsThumbnailMaker', imports: [
                        Slider,
                        SliderThumb,
                        FormsModule,
                        DragImageDirective,
                        Icon,
                        Button
                    ], host: {
                        'class': 'ngs-thumbnail-maker',
                        '[class.loading]': 'loading'
                    }, template: "@if (helperText() && !alreadyDragged) {\n  <div class=\"helper-text\">\n    <ngs-icon name=\"fluent:hand-draw-24-regular\" class=\"-ms-0.5\"/>\n    {{ helperText() }}\n  </div>\n}\n\n<div #content class=\"content\" (dragstart)=\"onDragStart($event)\">\n  <img [src]=\"src()\" alt=\"\" class=\"image\"\n       (load)=\"onLoad($event)\" [style.scale]=\"scale\"\n       ngsDragImage [scale]=\"scale\" [content]=\"content\">\n</div>\n<div class=\"controls mx-auto w-max flex items-center gap-3\">\n  <button ngsIconButton (click)=\"decrease()\" [disabled]=\"isEqualsToMinScale\">\n    <ngs-icon name=\"fluent:subtract-24-regular\"/>\n  </button>\n  <div class=\"w-[300px] range-slider -ms-3\">\n    <ngs-slider class=\"!w-full\" [min]=\"min\" [max]=\"max\">\n      <input ngsSliderThumb [ngModel]=\"scale * 100\" (ngModelChange)=\"onScaleChange($event)\">\n    </ngs-slider>\n  </div>\n  <button ngsIconButton (click)=\"increase()\" [disabled]=\"isEqualsToMaxScale\">\n    <ngs-icon name=\"fluent:add-24-regular\"/>\n  </button>\n</div>\n", styles: [":host{--ngs-thumbnail-width: 720px;--ngs-thumbnail-height: 460px;display:block;width:max-content;overflow:hidden;position:relative}:host .content{display:flex;width:var(--ngs-thumbnail-width);height:var(--ngs-thumbnail-height);-webkit-mask-image:radial-gradient(circle,#000 150px,#00000080 150px);mask-image:radial-gradient(circle,#000 150px,#00000080 150px);align-items:center;justify-content:center;overflow:hidden;line-height:1;position:relative;-webkit-user-select:none;user-select:none}:host .image{object-fit:fill;max-width:none;max-height:none;line-height:1;-webkit-user-select:none;user-select:none;cursor:move}:host .helper-text{position:absolute;z-index:1;top:calc(var(--spacing, .25rem) * 5);inset-inline-start:50%;background:var(--ngs-color-neutral-950);color:#fff;border-radius:var(--ngs-radius-lg);padding:calc(var(--spacing, .25rem) * 2) calc(var(--spacing, .25rem) * 3);font-size:var(--ngs-font-size-xs);opacity:90%;width:max-content;display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 2);transform:translate(-50%)}:host .controls{margin-top:calc(var(--spacing, .25rem) * 3);margin-bottom:calc(var(--spacing, .25rem) * 3)}:host.loading .image{visibility:hidden;position:relative;z-index:-1}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
        }], propDecorators: { _content: [{ type: i0.ViewChild, args: ['content', { isSignal: true }] }], _dragImage: [{ type: i0.ViewChild, args: [i0.forwardRef(() => DragImageDirective), { isSignal: true }] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: true }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }] } });

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

export { ThumbnailMaker };
//# sourceMappingURL=ngstarter-ui-components-thumbnail-maker.mjs.map
