import * as i0 from '@angular/core';
import { ViewEncapsulation, Component, Directive, inject, ViewContainerRef, DestroyRef, contentChild, ElementRef, viewChild, signal, effect, untracked } from '@angular/core';
import { fromEvent } from 'rxjs';
import { Overlay } from '@angular/cdk/overlay';
import { TemplatePortal } from '@angular/cdk/portal';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

class ImageZoomViewerStyle {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ImageZoomViewerStyle, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: ImageZoomViewerStyle, isStandalone: true, selector: "ngs-image-zoom-viewer-style", ngImport: i0, template: '', isInline: true, styles: [".ngs-image-zoom-wrapper{position:fixed;top:0;left:0;width:100vw;height:100vh;display:flex;align-items:center;justify-content:center;z-index:1000;cursor:zoom-out}.ngs-image-zoom-cloned{position:absolute;z-index:1001;cursor:zoom-out;pointer-events:auto;transition:transform .25s cubic-bezier(.4,0,.2,1);will-change:transform}.ngs-image-zoom-backdrop{background:var(--ngs-overlay-backdrop-bg);transition:opacity .25s cubic-bezier(.4,0,.2,1);opacity:0}.ngs-image-zoom-backdrop.cdk-overlay-backdrop-showing{opacity:1}.ngs-image-zoom-backdrop.is-closing{opacity:0!important}\n"], encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ImageZoomViewerStyle, decorators: [{
            type: Component,
            args: [{ selector: 'ngs-image-zoom-viewer-style', template: '', encapsulation: ViewEncapsulation.None, styles: [".ngs-image-zoom-wrapper{position:fixed;top:0;left:0;width:100vw;height:100vh;display:flex;align-items:center;justify-content:center;z-index:1000;cursor:zoom-out}.ngs-image-zoom-cloned{position:absolute;z-index:1001;cursor:zoom-out;pointer-events:auto;transition:transform .25s cubic-bezier(.4,0,.2,1);will-change:transform}.ngs-image-zoom-backdrop{background:var(--ngs-overlay-backdrop-bg);transition:opacity .25s cubic-bezier(.4,0,.2,1);opacity:0}.ngs-image-zoom-backdrop.cdk-overlay-backdrop-showing{opacity:1}.ngs-image-zoom-backdrop.is-closing{opacity:0!important}\n"] }]
        }] });

class ImageZoomViewerImage {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ImageZoomViewerImage, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.4", type: ImageZoomViewerImage, isStandalone: true, selector: "[ngsImageZoomViewerImage]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ImageZoomViewerImage, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngsImageZoomViewerImage]',
                }]
        }] });

class ImageZoomViewer {
    overlay = inject(Overlay);
    viewContainerRef = inject(ViewContainerRef);
    destroyRef = inject(DestroyRef);
    contentImageRef = contentChild.required(ImageZoomViewerImage, { read: (ElementRef) });
    zoomedTemplate = viewChild.required('zoomedTemplate');
    isZoomed = signal(false, ...(ngDevMode ? [{ debugName: "isZoomed" }] : /* istanbul ignore next */ []));
    imageSrc = signal('', ...(ngDevMode ? [{ debugName: "imageSrc" }] : /* istanbul ignore next */ []));
    imageAlt = signal('', ...(ngDevMode ? [{ debugName: "imageAlt" }] : /* istanbul ignore next */ []));
    imageRect = signal(undefined, ...(ngDevMode ? [{ debugName: "imageRect" }] : /* istanbul ignore next */ []));
    zoomedTransform = signal('translate(0, 0) scale(1)', ...(ngDevMode ? [{ debugName: "zoomedTransform" }] : /* istanbul ignore next */ []));
    overlayRef = null;
    resizeSubscription;
    constructor() {
        // Update image source when content changes or initial load
        effect(() => {
            const img = this.getImageElement();
            if (img) {
                untracked(() => {
                    this.imageSrc.set(img.src);
                    this.imageAlt.set(img.alt);
                });
            }
        });
    }
    ngOnDestroy() {
        this.closeZoom();
    }
    toggleZoom() {
        if (this.isZoomed()) {
            this.closeZoom();
        }
        else {
            this.openZoom();
        }
    }
    openZoom() {
        const img = this.getImageElement();
        const template = this.zoomedTemplate();
        this.imageSrc.set(img.src);
        this.imageAlt.set(img.alt);
        const rect = img.getBoundingClientRect();
        this.imageRect.set(rect);
        this.isZoomed.set(true);
        this.overlayRef = this.overlay.create({
            hasBackdrop: true,
            backdropClass: 'ngs-image-zoom-backdrop',
            scrollStrategy: this.overlay.scrollStrategies.block(),
            positionStrategy: this.overlay.position().global().centerHorizontally().centerVertically()
        });
        this.overlayRef
            .backdropClick()
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe(() => this.closeZoom());
        this.overlayRef
            .keydownEvents()
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe(event => {
            if (event.key === 'Escape') {
                this.closeZoom();
            }
        });
        const portal = new TemplatePortal(template, this.viewContainerRef);
        this.overlayRef.attach(portal);
        // Use requestAnimationFrame to ensure the cloned image is rendered before animating
        requestAnimationFrame(() => {
            this.calculateZoom();
        });
        this.resizeSubscription = fromEvent(window, 'resize')
            .pipe(takeUntilDestroyed(this.destroyRef))
            .subscribe(() => {
            this.calculateZoom();
        });
    }
    closeZoom() {
        if (!this.overlayRef) {
            return;
        }
        const backdrop = this.overlayRef.backdropElement;
        if (backdrop) {
            backdrop.classList.add('is-closing');
            backdrop.classList.remove('cdk-overlay-backdrop-showing');
        }
        this.zoomedTransform.set('translate(0, 0) scale(1)');
        // Wait for transition to finish before hiding the overlay and cloned image
        setTimeout(() => {
            this.isZoomed.set(false);
            this.cleanupListeners();
            if (this.overlayRef) {
                this.overlayRef.dispose();
                this.overlayRef = null;
            }
        }, 250);
    }
    calculateZoom() {
        const rect = this.imageRect();
        if (!rect) {
            return;
        }
        const vWidth = window.innerWidth;
        const vHeight = window.innerHeight;
        const scaleX = vWidth / rect.width;
        const scaleY = vHeight / rect.height;
        const scale = Math.min(scaleX, scaleY) * 0.9; // 90% of viewport
        const translateX = (vWidth / 2) - (rect.left + rect.width / 2);
        const translateY = (vHeight / 2) - (rect.top + rect.height / 2);
        this.zoomedTransform.set(`translate(${translateX}px, ${translateY}px) scale(${scale})`);
    }
    getImageElement() {
        return this.contentImageRef().nativeElement;
    }
    cleanupListeners() {
        if (this.resizeSubscription) {
            this.resizeSubscription.unsubscribe();
            this.resizeSubscription = undefined;
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ImageZoomViewer, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.4", type: ImageZoomViewer, isStandalone: true, selector: "ngs-image-zoom-viewer", host: { classAttribute: "ngs-image-zoom-viewer" }, queries: [{ propertyName: "contentImageRef", first: true, predicate: ImageZoomViewerImage, descendants: true, read: ElementRef, isSignal: true }], viewQueries: [{ propertyName: "zoomedTemplate", first: true, predicate: ["zoomedTemplate"], descendants: true, isSignal: true }], exportAs: ["ngsImageZoomViewer"], ngImport: i0, template: "<ngs-image-zoom-viewer-style/>\n<div class=\"ngs-image-zoom-container\" [class.is-zoomed]=\"isZoomed()\" (click)=\"toggleZoom()\">\n  <ng-content/>\n</div>\n\n<ng-template #zoomedTemplate>\n  <div class=\"ngs-image-zoom-wrapper\" (click)=\"closeZoom()\">\n    <img\n      #zoomedImage\n      class=\"ngs-image-zoom-cloned\"\n      [src]=\"imageSrc()\"\n      [alt]=\"imageAlt()\"\n      [style.transform]=\"zoomedTransform()\"\n      [style.width.px]=\"imageRect()?.width\"\n      [style.height.px]=\"imageRect()?.height\"\n      [style.top.px]=\"imageRect()?.top\"\n      [style.left.px]=\"imageRect()?.left\"\n    />\n  </div>\n</ng-template>\n", styles: [":host{display:inline-block;cursor:zoom-in}:host .ngs-image-zoom-container{display:block}:host .ngs-image-zoom-container.is-zoomed{visibility:hidden}\n"], dependencies: [{ kind: "component", type: ImageZoomViewerStyle, selector: "ngs-image-zoom-viewer-style" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ImageZoomViewer, decorators: [{
            type: Component,
            args: [{ selector: 'ngs-image-zoom-viewer', exportAs: 'ngsImageZoomViewer', imports: [
                        ImageZoomViewerStyle,
                    ], host: {
                        'class': 'ngs-image-zoom-viewer'
                    }, template: "<ngs-image-zoom-viewer-style/>\n<div class=\"ngs-image-zoom-container\" [class.is-zoomed]=\"isZoomed()\" (click)=\"toggleZoom()\">\n  <ng-content/>\n</div>\n\n<ng-template #zoomedTemplate>\n  <div class=\"ngs-image-zoom-wrapper\" (click)=\"closeZoom()\">\n    <img\n      #zoomedImage\n      class=\"ngs-image-zoom-cloned\"\n      [src]=\"imageSrc()\"\n      [alt]=\"imageAlt()\"\n      [style.transform]=\"zoomedTransform()\"\n      [style.width.px]=\"imageRect()?.width\"\n      [style.height.px]=\"imageRect()?.height\"\n      [style.top.px]=\"imageRect()?.top\"\n      [style.left.px]=\"imageRect()?.left\"\n    />\n  </div>\n</ng-template>\n", styles: [":host{display:inline-block;cursor:zoom-in}:host .ngs-image-zoom-container{display:block}:host .ngs-image-zoom-container.is-zoomed{visibility:hidden}\n"] }]
        }], ctorParameters: () => [], propDecorators: { contentImageRef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ImageZoomViewerImage), { ...{ read: (ElementRef) }, isSignal: true }] }], zoomedTemplate: [{ type: i0.ViewChild, args: ['zoomedTemplate', { isSignal: true }] }] } });

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

export { ImageZoomViewer, ImageZoomViewerImage };
//# sourceMappingURL=ngstarter-ui-components-image-zoom-viewer.mjs.map
