import * as i0 from '@angular/core';
import { inject, TemplateRef, Directive, InjectionToken, viewChild, contentChild, signal, ChangeDetectionStrategy, Component, ElementRef, ViewContainerRef, Injector, DestroyRef, input, numberAttribute, booleanAttribute, output, EventEmitter } from '@angular/core';
import { NgTemplateOutlet, NgClass } from '@angular/common';
import { Overlay, OverlayConfig } from '@angular/cdk/overlay';
import { takeUntil, fromEvent } from 'rxjs';
import { Directionality } from '@angular/cdk/bidi';
import { TemplatePortal } from '@angular/cdk/portal';
import { _getEventTarget } from '@angular/cdk/platform';
import { PositionManager } from '@ngstarter-ui/components/overlay';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

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

const POPOVER_TRIGGER = new InjectionToken('POPOVER_TRIGGER');

class Popover {
    trigger = inject(POPOVER_TRIGGER, { optional: true });
    templateRef = viewChild.required(TemplateRef);
    content = contentChild(PopoverContent, ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
    _context = signal(undefined, ...(ngDevMode ? [{ debugName: "_context" }] : /* istanbul ignore next */ []));
    _positionClasses = signal([], ...(ngDevMode ? [{ debugName: "_positionClasses" }] : /* istanbul ignore next */ []));
    _setContext(context) {
        this._context.set(context);
    }
    _setPositionClasses(classes) {
        this._positionClasses.set(classes);
    }
    open() {
        this.trigger?.open();
    }
    close() {
        this.trigger?.close();
    }
    isOpen() {
        return this.trigger?.isOpen() ?? false;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: Popover, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: Popover, isStandalone: true, selector: "ngs-popover", host: { classAttribute: "ngs-popover" }, queries: [{ propertyName: "content", first: true, predicate: PopoverContent, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "templateRef", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], exportAs: ["ngsPopover"], ngImport: i0, template: "<ng-template>\n  <div class=\"ngs-popover-panel\" [ngClass]=\"_positionClasses()\">\n    @if (content()) {\n      <ng-container [ngTemplateOutlet]=\"content()!.templateRef\" [ngTemplateOutletContext]=\"_context()\"/>\n    } @else {\n      <ng-content/>\n    }\n  </div>\n</ng-template>\n", styles: [".ngs-popover-panel{--ngs-popover-border: var(--ngs-dropdown-border);--ngs-popover-shadow: var(--ngs-dropdown-shadow);--ngs-popover-border-radius: var(--ngs-dropdown-radius);--ngs-popover-bg: var(--ngs-dropdown-bg);--ngs-popover-margin: .625rem;display:block;position:relative;border-radius:var(--ngs-popover-border-radius);background:var(--ngs-popover-bg);border:var(--ngs-popover-border);box-shadow:var(--ngs-popover-shadow);animation:.15s ngs-popover-animation}.ngs-popover-panel.ngs-overlay-above{margin-bottom:var(--ngs-popover-margin);transform-origin:bottom}.ngs-popover-panel.ngs-overlay-below{margin-top:var(--ngs-popover-margin);transform-origin:top}.ngs-popover-panel.ngs-overlay-before{margin-inline-end:var(--ngs-popover-margin);transform-origin:right}.ngs-popover-panel.ngs-overlay-after{margin-inline-start:var(--ngs-popover-margin);transform-origin:left}@keyframes ngs-popover-animation{0%{transform:scale(.9);opacity:0}to{transform:scale(1);opacity:1}}:host{display:contents}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: Popover, decorators: [{
            type: Component,
            args: [{ selector: 'ngs-popover', exportAs: 'ngsPopover', standalone: true, imports: [
                        NgTemplateOutlet,
                        NgClass
                    ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        'class': 'ngs-popover'
                    }, template: "<ng-template>\n  <div class=\"ngs-popover-panel\" [ngClass]=\"_positionClasses()\">\n    @if (content()) {\n      <ng-container [ngTemplateOutlet]=\"content()!.templateRef\" [ngTemplateOutletContext]=\"_context()\"/>\n    } @else {\n      <ng-content/>\n    }\n  </div>\n</ng-template>\n", styles: [".ngs-popover-panel{--ngs-popover-border: var(--ngs-dropdown-border);--ngs-popover-shadow: var(--ngs-dropdown-shadow);--ngs-popover-border-radius: var(--ngs-dropdown-radius);--ngs-popover-bg: var(--ngs-dropdown-bg);--ngs-popover-margin: .625rem;display:block;position:relative;border-radius:var(--ngs-popover-border-radius);background:var(--ngs-popover-bg);border:var(--ngs-popover-border);box-shadow:var(--ngs-popover-shadow);animation:.15s ngs-popover-animation}.ngs-popover-panel.ngs-overlay-above{margin-bottom:var(--ngs-popover-margin);transform-origin:bottom}.ngs-popover-panel.ngs-overlay-below{margin-top:var(--ngs-popover-margin);transform-origin:top}.ngs-popover-panel.ngs-overlay-before{margin-inline-end:var(--ngs-popover-margin);transform-origin:right}.ngs-popover-panel.ngs-overlay-after{margin-inline-start:var(--ngs-popover-margin);transform-origin:left}@keyframes ngs-popover-animation{0%{transform:scale(.9);opacity:0}to{transform:scale(1);opacity:1}}:host{display:contents}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
        }], propDecorators: { templateRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }], content: [{ type: i0.ContentChild, args: [i0.forwardRef(() => PopoverContent), { isSignal: true }] }] } });

class PopoverTriggerForDirective {
    _overlay = inject(Overlay);
    _elementRef = inject(ElementRef);
    _directionality = inject(Directionality, { optional: true });
    _viewContainerRef = inject(ViewContainerRef);
    _injector = inject(Injector);
    _popoverPortal;
    _overlayRef = null;
    _destroyRef = inject(DestroyRef);
    _openTimeout = null;
    _closeTimeout = null;
    _closeDelay = 500;
    popover = input.required({ ...(ngDevMode ? { debugName: "popover" } : /* istanbul ignore next */ {}), alias: 'ngsPopoverTriggerFor' });
    popoverContext = input(undefined, { ...(ngDevMode ? { debugName: "popoverContext" } : /* istanbul ignore next */ {}), alias: 'ngsPopoverContext' });
    trigger = input('click', ...(ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []));
    position = input('below-center', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
    delay = input(500, { ...(ngDevMode ? { debugName: "delay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
    origin = input(...(ngDevMode ? [undefined, { debugName: "origin" }] : /* istanbul ignore next */ []));
    closeOnOriginClick = input(false, { ...(ngDevMode ? { debugName: "closeOnOriginClick" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    closeOnOriginMouseLeave = input(false, { ...(ngDevMode ? { debugName: "closeOnOriginMouseLeave" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    hasBackdrop = input(false, { ...(ngDevMode ? { debugName: "hasBackdrop" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
    opened = output();
    closed = output();
    _closed = new EventEmitter();
    constructor() {
        this._setType();
    }
    _handleClick() {
        if (this.trigger() !== 'click') {
            if (this.closeOnOriginClick()) {
                this.close();
            }
            return;
        }
        !this.isOpen() ? this.open() : this.close();
    }
    _handleMouseover() {
        if (!this.isOpen() && this.trigger() === 'hover') {
            this._openTimeout = setTimeout(() => {
                this.open();
            }, this.delay());
        }
    }
    _handleMouseout() {
        if (!this.isOpen()) {
            clearTimeout(this._openTimeout);
        }
        else {
            if (this.closeOnOriginMouseLeave()) {
                this.close();
                return;
            }
        }
    }
    ngOnInit() {
        this.closed
            .subscribe(() => {
            this._closed.emit();
        });
    }
    ngOnDestroy() {
        this.close();
        this._destroyOverlay();
    }
    get api() {
        return this;
    }
    isOpen() {
        return !!this._overlayRef?.hasAttached();
    }
    open() {
        if (!this.isOpen() && this.popover() != null) {
            this.opened.emit();
            const popover = this.popover();
            if (popover instanceof Popover) {
                popover._setContext(this.popoverContext());
            }
            this._overlayRef = this._overlay.create(this._getOverlayConfig());
            const strategy = this._overlayRef.getConfig().positionStrategy;
            strategy.positionChanges
                .pipe(takeUntil(this._closed), takeUntilDestroyed(this._destroyRef))
                .subscribe(change => {
                const panelClass = change.connectionPair.panelClass;
                if (panelClass && popover instanceof Popover) {
                    popover._setPositionClasses(Array.isArray(panelClass) ? panelClass : [panelClass]);
                }
            });
            this._overlayRef.attach(this._getPopoverContentPortal());
            this._subscribeToHostMouseleave();
            this._subscribeToOutsideClicks();
        }
    }
    close() {
        clearTimeout(this._closeTimeout);
        clearTimeout(this._openTimeout);
        this.closed.emit();
        this._overlayRef?.detach();
    }
    _destroyOverlay() {
        clearTimeout(this._openTimeout);
        clearTimeout(this._closeTimeout);
        this._overlayRef?.dispose();
        this._overlayRef = null;
    }
    _subscribeToOutsideClicks() {
        if (this._overlayRef) {
            this._overlayRef
                .outsidePointerEvents()
                .pipe(takeUntilDestroyed(this._destroyRef))
                .subscribe(event => {
                const target = _getEventTarget(event);
                const element = this._elementRef.nativeElement;
                if (this.closeOnOriginClick() && ((target === element) || element.contains(target))) {
                    this.close();
                    return;
                }
                if (target !== element && !element.contains(target)) {
                    this.close();
                }
            });
        }
    }
    _getPopoverContentPortal() {
        const injector = Injector.create({
            providers: [
                {
                    provide: POPOVER_TRIGGER,
                    useValue: this
                }
            ],
            parent: this._injector
        });
        const popover = this.popover();
        const templateRef = popover instanceof Popover ? popover.templateRef() : popover;
        const context = popover instanceof Popover ? null : this.popoverContext();
        this._popoverPortal = new TemplatePortal(templateRef, this._viewContainerRef, context, injector);
        return this._popoverPortal;
    }
    _getOverlayConfig() {
        return new OverlayConfig({
            hasBackdrop: this.hasBackdrop(),
            backdropClass: 'ngs-popover-overlay-backdrop',
            positionStrategy: this._getOverlayPositionStrategy(),
            scrollStrategy: this._overlay.scrollStrategies.reposition(),
            direction: this._directionality || undefined,
        });
    }
    _getOverlayPositionStrategy() {
        const origin = (this.origin() ? this.origin() : this._elementRef);
        return this._overlay
            .position()
            .flexibleConnectedTo(origin)
            .setOrigin(origin)
            .withGrowAfterOpen()
            .withPositions(this._getOverlayPositions());
    }
    _getOverlayPositions() {
        return (new PositionManager()).build(this.position());
    }
    _setType() {
        if (this.trigger() === 'hover') {
            return;
        }
        const element = this._elementRef.nativeElement;
        if (element.nodeName === 'BUTTON' && !element.getAttribute('type')) {
            // Prevents form submissions.
            element.setAttribute('type', 'button');
        }
    }
    _subscribeToHostMouseleave() {
        if (this.trigger() === 'hover' && this._overlayRef) {
            fromEvent(this._elementRef.nativeElement, 'mouseleave')
                .pipe(takeUntil(this._closed), takeUntilDestroyed(this._destroyRef))
                .subscribe(event => {
                if (this.closeOnOriginMouseLeave()) {
                    this.close();
                    return;
                }
                this._closeTimeout = setTimeout(() => {
                    this.close();
                }, this._closeDelay);
            });
            const popoverElement = this._overlayRef.overlayElement;
            fromEvent(popoverElement, 'mouseenter')
                .pipe(takeUntil(this._closed), takeUntilDestroyed(this._destroyRef))
                .subscribe(event => {
                clearTimeout(this._closeTimeout);
                this._closeTimeout = null;
            });
            fromEvent(popoverElement, 'mouseleave')
                .pipe(takeUntil(this._closed), takeUntilDestroyed(this._destroyRef))
                .subscribe(event => {
                this._closeTimeout = setTimeout(() => {
                    this.close();
                }, this._closeDelay);
            });
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PopoverTriggerForDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.4", type: PopoverTriggerForDirective, isStandalone: true, selector: "[ngsPopoverTriggerFor]", inputs: { popover: { classPropertyName: "popover", publicName: "ngsPopoverTriggerFor", isSignal: true, isRequired: true, transformFunction: null }, popoverContext: { classPropertyName: "popoverContext", publicName: "ngsPopoverContext", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, origin: { classPropertyName: "origin", publicName: "origin", isSignal: true, isRequired: false, transformFunction: null }, closeOnOriginClick: { classPropertyName: "closeOnOriginClick", publicName: "closeOnOriginClick", isSignal: true, isRequired: false, transformFunction: null }, closeOnOriginMouseLeave: { classPropertyName: "closeOnOriginMouseLeave", publicName: "closeOnOriginMouseLeave", isSignal: true, isRequired: false, transformFunction: null }, hasBackdrop: { classPropertyName: "hasBackdrop", publicName: "hasBackdrop", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed" }, host: { listeners: { "click": "_handleClick()", "mouseenter": "_handleMouseover()", "mouseleave": "_handleMouseout()" }, properties: { "class.ngs-popover-trigger-for--is-open": "api.isOpen()" }, classAttribute: "ngs-popover-trigger-for" }, exportAs: ["ngsPopoverTriggerFor"], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PopoverTriggerForDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngsPopoverTriggerFor]',
                    exportAs: 'ngsPopoverTriggerFor',
                    host: {
                        'class': 'ngs-popover-trigger-for',
                        '[class.ngs-popover-trigger-for--is-open]': 'api.isOpen()',
                        '(click)': '_handleClick()',
                        '(mouseenter)': '_handleMouseover()',
                        '(mouseleave)': '_handleMouseout()'
                    }
                }]
        }], ctorParameters: () => [], propDecorators: { popover: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngsPopoverTriggerFor", required: true }] }], popoverContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngsPopoverContext", required: false }] }], trigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], origin: [{ type: i0.Input, args: [{ isSignal: true, alias: "origin", required: false }] }], closeOnOriginClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOriginClick", required: false }] }], closeOnOriginMouseLeave: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOriginMouseLeave", required: false }] }], hasBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasBackdrop", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });

class PopoverOriginDirective {
    _elementRef = inject(ElementRef);
    get api() {
        return {
            nativeElement: () => {
                return this._elementRef?.nativeElement;
            }
        };
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PopoverOriginDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.4", type: PopoverOriginDirective, isStandalone: true, selector: "[ngsPopoverOrigin]", exportAs: ["ngsPopoverOrigin"], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PopoverOriginDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngsPopoverOrigin]',
                    exportAs: 'ngsPopoverOrigin'
                }]
        }] });

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

export { POPOVER_TRIGGER, Popover, PopoverContent, PopoverOriginDirective, PopoverTriggerForDirective };
//# sourceMappingURL=ngstarter-ui-components-popover.mjs.map
