import { coerceCssPixelValue } from '@angular/cdk/coercion';
import { CdkDialogContainer, Dialog } from '@angular/cdk/dialog';
import { SharedResizeObserver } from '@angular/cdk/observers/private';
import { Overlay } from '@angular/cdk/overlay';
import * as i0 from '@angular/core';
import { InjectionToken, EventEmitter, inject, Renderer2, Component, ChangeDetectionStrategy, ViewEncapsulation, Injector, Injectable, NgModule } from '@angular/core';
import { map, of, Subject, filter, take, takeUntil } from 'rxjs';
import { trigger, state, style, transition, group, animate, query, animateChild } from '@angular/animations';
import { CdkPortalOutlet } from '@angular/cdk/portal';
import { toSignal } from '@angular/core/rxjs-interop';
import * as i2 from '@koobiq/components/button';
import { KbqButtonModule } from '@koobiq/components/button';
import { ruRULocaleData, KbqAnimationDurations, KbqAnimationCurves, KBQ_LOCALE_SERVICE } from '@koobiq/components/core';
import * as i1 from '@koobiq/components/divider';
import { KbqDividerModule } from '@koobiq/components/divider';
import * as i3 from '@koobiq/components/icon';
import { KbqIconModule } from '@koobiq/components/icon';
import * as i4 from '@koobiq/components/tooltip';
import { KbqToolTipModule } from '@koobiq/components/tooltip';

/** Injection token that can be used to specify default actions panel config. */
const KBQ_ACTIONS_PANEL_DEFAULT_CONFIG = new InjectionToken('KBQ_ACTIONS_PANEL_DEFAULT_CONFIG', { factory: () => new KbqActionsPanelConfig() });
/**
 * Utility for providing default actions panel config.
 *
 * @see `KBQ_ACTIONS_PANEL_DEFAULT_CONFIG`
 */
const kbqActionsPanelDefaultConfigProvider = (config) => ({
    provide: KBQ_ACTIONS_PANEL_DEFAULT_CONFIG,
    useValue: config
});
/**
 * Configuration for opened actions panel.
 * Based on cdk `DialogConfig`.
 *
 * @see `DialogConfig`
 *
 */
class KbqActionsPanelConfig {
    constructor() {
        /**
         * Data being injected into the child component.
         *
         * @see `KBQ_ACTIONS_PANEL_DATA`
         */
        this.data = null;
        /**
         * Whether the actions panel should be closed of when the user goes backwards/forwards in history.
         * NOTE! This does not apply to router navigation.
         *
         * @default true
         */
        this.closeOnNavigation = true;
        /**
         * Direction of the text in the actions panel.
         *
         * @default 'ltr'
         */
        this.direction = 'ltr';
        /**
         * Scroll strategy to be used for the actions panel.
         *
         * @default `RepositionScrollStrategy`
         */
        this.scrollStrategy = (overlay) => overlay.scrollStrategies.reposition();
        /**
         * Whether the user can use ESC or click on close button to close the actions panel.
         *
         * @default false
         */
        this.disableClose = false;
    }
}

/** Localization configuration provider. */
const KBQ_ACTIONS_PANEL_LOCALE_CONFIGURATION = new InjectionToken('KBQ_ACTIONS_PANEL_LOCALE_CONFIGURATION', { factory: () => ruRULocaleData.actionsPanel });
/** Utility provider for `KBQ_ACTIONS_PANEL_LOCALE_CONFIGURATION`. */
const kbqActionsPanelLocaleConfigurationProvider = (configuration) => ({
    provide: KBQ_ACTIONS_PANEL_LOCALE_CONFIGURATION,
    useValue: configuration
});
/**
 * Animation that shows and hides the actions panel.
 */
const KBQ_ACTIONS_PANEL_CONTAINER_ANIMATION = trigger('state', [
    state('void, hidden', style({ transform: 'translateY(100%)' })),
    state('visible', style({ transform: 'translateY(0%)' })),
    transition('visible => void, visible => hidden', group([
        animate(`${KbqAnimationDurations.Entering} ${KbqAnimationCurves.StandardCurve}`),
        query('@*', animateChild(), { optional: true })
    ])),
    transition('void => visible', group([
        animate(`${KbqAnimationDurations.Exiting} ${KbqAnimationCurves.StandardCurve}`),
        query('@*', animateChild(), { optional: true })
    ]))
]);
/**
 * Internal component that wraps user-provided actions panel content.
 *
 * @docs-private
 */
class KbqActionsPanelContainer extends CdkDialogContainer {
    constructor() {
        super(...arguments);
        /**
         * The state of the actions panel animations.
         *
         * @docs-private
         */
        this.animationState = 'void';
        /**
         * Emits whenever the state of the animation changes.
         *
         * @docs-private
         */
        this.animationStateChanged = new EventEmitter();
        /**
         * Actions panel configuration.
         *
         * @docs-private
         */
        this.config = inject(KbqActionsPanelConfig);
        this.actionsPanel = inject(KbqActionsPanel);
        this.renderer = inject(Renderer2);
        this.localeService = inject(KBQ_LOCALE_SERVICE, { optional: true });
        /**
         * Actions panel locale configuration.
         *
         * @docs-private
         */
        this.localeConfiguration = toSignal(this.localeService
            ? this.localeService.changes.pipe(map(() => this.localeService.getParams('actionsPanel')))
            : of(inject(KBQ_ACTIONS_PANEL_LOCALE_CONFIGURATION)));
    }
    ngOnDestroy() {
        super.ngOnDestroy();
        this.destroyed = true;
    }
    /**
     * Close the actions panel.
     *
     * @docs-private
     */
    close() {
        this.actionsPanel.close();
    }
    /**
     * Start animation of the actions panel entrance into view.
     *
     * @docs-private
     */
    startOpenAnimation() {
        if (!this.destroyed) {
            this.animationState = 'visible';
            // animationState lives in host bindings and `detectChanges` does not refresh host bindings  so we have to
            // call `markForCheck` to ensure the host view is refreshed eventually.
            this._changeDetectorRef.markForCheck();
            this._changeDetectorRef.detectChanges();
        }
    }
    /**
     * Start animation of the actions panel exiting from view.
     *
     * @docs-private
     */
    startCloseAnimation() {
        if (!this.destroyed) {
            this.animationState = 'hidden';
            this._changeDetectorRef.markForCheck();
        }
    }
    /**
     * Handles animation done events.
     *
     * @docs-private
     */
    onAnimationDone(event) {
        if (event.toState === 'visible') {
            this._trapFocus();
        }
        this.animationStateChanged.emit(event);
    }
    /**
     * Handles animation start events.
     *
     * @docs-private
     */
    onAnimationStart(event) {
        this.animationStateChanged.emit(event);
    }
    /**
     * Handles escape key events.
     *
     * @docs-private
     */
    handleEscape(event) {
        if (!this.config.disableClose) {
            event.preventDefault();
            this.close();
        }
    }
    /**
     * @docs-private
     */
    _contentAttached() {
        this.applyContainerClass();
    }
    applyContainerClass() {
        const { containerClass } = this.config;
        if (containerClass) {
            if (Array.isArray(containerClass)) {
                containerClass.forEach((cssClass) => this.renderer.addClass(this._elementRef.nativeElement, cssClass));
            }
            else {
                this.renderer.addClass(this._elementRef.nativeElement, containerClass);
            }
        }
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KbqActionsPanelContainer, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: KbqActionsPanelContainer, isStandalone: true, selector: "kbq-actions-panel-container", host: { listeners: { "@state.start": "onAnimationStart($event)", "@state.done": "onAnimationDone($event)", "keydown.escape": "handleEscape($event)" }, properties: { "class.kbq-actions-panel-container_rtl": "config.direction === \"rtl\"", "@state": "animationState" }, classAttribute: "kbq-actions-panel-container" }, usesInheritance: true, ngImport: i0, template: `
        <div class="kbq-actions-panel-container__content">
            <ng-template cdkPortalOutlet />
        </div>
        @if (!config.disableClose) {
            <kbq-divider class="kbq-actions-panel-container__vertical-divider" [vertical]="true" />
            <button
                class="kbq-actions-panel-container__close-button"
                color="contrast"
                kbq-button
                [kbqTooltip]="localeConfiguration()!.closeTooltip"
                [kbqTooltipOffset]="16"
                (click)="close()"
            >
                <i kbq-icon="kbq-xmark-circle_16"></i>
            </button>
        }
    `, isInline: true, styles: [".kbq-actions-panel-container,.kbq-actions-panel-overlay{--kbq-actions-panel-background-color: var(--kbq-background-contrast);--kbq-actions-panel-text-color: var(--kbq-foreground-on-contrast);--kbq-actions-panel-padding: var(--kbq-size-s);--kbq-actions-panel-margin: var(--kbq-size-s) var(--kbq-size-s) var(--kbq-size-l);--kbq-actions-panel-border-radius: var(--kbq-size-l);--kbq-actions-panel-box-shadow: var(--kbq-shadow-card);--kbq-actions-panel-height: var(--kbq-size-5xl);--kbq-actions-panel-vertical-divider-background-color: var(--kbq-line-contrast-fade);--kbq-actions-panel-vertical-divider-height: var(--kbq-size-m);--kbq-actions-panel-vertical-divider-margin: 0 var(--kbq-size-s)}\n", ".kbq-actions-panel-container{background:var(--kbq-actions-panel-background-color);color:var(--kbq-actions-panel-text-color);box-shadow:var(--kbq-actions-panel-box-shadow);height:var(--kbq-actions-panel-height);padding:var(--kbq-actions-panel-padding);border-radius:var(--kbq-actions-panel-border-radius);display:flex;flex-grow:1;align-items:center;overflow:hidden;box-sizing:border-box}.kbq-actions-panel-container .kbq-actions-panel-container__content{display:flex;align-items:center;flex-grow:1;overflow:hidden}.kbq-actions-panel-container .kbq-actions-panel-container__vertical-divider{background-color:var(--kbq-actions-panel-vertical-divider-background-color);height:var(--kbq-actions-panel-vertical-divider-height)!important;margin:var(--kbq-actions-panel-vertical-divider-margin)}.kbq-actions-panel-overlay{margin:var(--kbq-actions-panel-margin)}\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { kind: "ngmodule", type: KbqDividerModule }, { kind: "component", type: i1.KbqDivider, selector: "kbq-divider", inputs: ["vertical", "inset", "paddings"] }, { kind: "ngmodule", type: KbqButtonModule }, { kind: "component", type: i2.KbqButton, selector: "[kbq-button]", inputs: ["kbqStyle", "disabled", "tabIndex"] }, { kind: "directive", type: i2.KbqButtonCssStyler, selector: "[kbq-button]" }, { kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i3.KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }, { kind: "ngmodule", type: KbqToolTipModule }, { kind: "directive", type: i4.KbqTooltipTrigger, selector: "[kbqTooltip]", inputs: ["hideWithTimeout", "kbqVisible", "kbqPlacement", "kbqRelativeToPointer", "kbqPlacementPriority", "kbqTooltip", "kbqTooltipDisabled", "kbqEnterDelay", "kbqLeaveDelay", "kbqTrigger", "kbqTooltipClass", "kbqTooltipContext", "kbqTooltipColor", "kbqTooltipArrow", "kbqTooltipOffset"], outputs: ["kbqPlacementChange", "kbqVisibleChange"], exportAs: ["kbqTooltip"] }], animations: [KBQ_ACTIONS_PANEL_CONTAINER_ANIMATION], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KbqActionsPanelContainer, decorators: [{
            type: Component,
            args: [{ standalone: true, imports: [
                        CdkPortalOutlet,
                        KbqDividerModule,
                        KbqButtonModule,
                        KbqIconModule,
                        KbqToolTipModule
                    ], selector: 'kbq-actions-panel-container', template: `
        <div class="kbq-actions-panel-container__content">
            <ng-template cdkPortalOutlet />
        </div>
        @if (!config.disableClose) {
            <kbq-divider class="kbq-actions-panel-container__vertical-divider" [vertical]="true" />
            <button
                class="kbq-actions-panel-container__close-button"
                color="contrast"
                kbq-button
                [kbqTooltip]="localeConfiguration()!.closeTooltip"
                [kbqTooltipOffset]="16"
                (click)="close()"
            >
                <i kbq-icon="kbq-xmark-circle_16"></i>
            </button>
        }
    `, animations: [KBQ_ACTIONS_PANEL_CONTAINER_ANIMATION], host: {
                        class: 'kbq-actions-panel-container',
                        '[class.kbq-actions-panel-container_rtl]': 'config.direction === "rtl"',
                        '[@state]': 'animationState',
                        '(@state.start)': 'onAnimationStart($event)',
                        '(@state.done)': 'onAnimationDone($event)',
                        '(keydown.escape)': 'handleEscape($event)'
                    }, changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, styles: [".kbq-actions-panel-container,.kbq-actions-panel-overlay{--kbq-actions-panel-background-color: var(--kbq-background-contrast);--kbq-actions-panel-text-color: var(--kbq-foreground-on-contrast);--kbq-actions-panel-padding: var(--kbq-size-s);--kbq-actions-panel-margin: var(--kbq-size-s) var(--kbq-size-s) var(--kbq-size-l);--kbq-actions-panel-border-radius: var(--kbq-size-l);--kbq-actions-panel-box-shadow: var(--kbq-shadow-card);--kbq-actions-panel-height: var(--kbq-size-5xl);--kbq-actions-panel-vertical-divider-background-color: var(--kbq-line-contrast-fade);--kbq-actions-panel-vertical-divider-height: var(--kbq-size-m);--kbq-actions-panel-vertical-divider-margin: 0 var(--kbq-size-s)}\n", ".kbq-actions-panel-container{background:var(--kbq-actions-panel-background-color);color:var(--kbq-actions-panel-text-color);box-shadow:var(--kbq-actions-panel-box-shadow);height:var(--kbq-actions-panel-height);padding:var(--kbq-actions-panel-padding);border-radius:var(--kbq-actions-panel-border-radius);display:flex;flex-grow:1;align-items:center;overflow:hidden;box-sizing:border-box}.kbq-actions-panel-container .kbq-actions-panel-container__content{display:flex;align-items:center;flex-grow:1;overflow:hidden}.kbq-actions-panel-container .kbq-actions-panel-container__vertical-divider{background-color:var(--kbq-actions-panel-vertical-divider-background-color);height:var(--kbq-actions-panel-vertical-divider-height)!important;margin:var(--kbq-actions-panel-vertical-divider-margin)}.kbq-actions-panel-overlay{margin:var(--kbq-actions-panel-margin)}\n"] }]
        }] });

/**
 * Reference to actions panel opened by `KbqActionsPanel` service.
 */
class KbqActionsPanelRef {
    /** Gets an observable that is notified when the actions panel is finished closing. */
    get afterClosed() {
        return this.dialogRef.closed;
    }
    /** Gets an observable that emits when keydown events are targeted on the overlay. */
    get keydownEvents() {
        return this.dialogRef.keydownEvents;
    }
    /** Gets an observable that is notified when the actions panel has opened and appeared. */
    get afterOpened() {
        return this._afterOpened;
    }
    /**
     * Gets the overlay reference for the actions panel.
     *
     * @docs-private
     */
    get overlayRef() {
        return this.dialogRef.overlayRef;
    }
    /**
     * Gets the ID of the actions panel.
     *
     * @docs-private
     */
    get id() {
        return this.dialogRef.id;
    }
    constructor(dialogRef, containerInstance) {
        this.dialogRef = dialogRef;
        this._afterOpened = new Subject();
        this.containerInstance = containerInstance;
        this.handleAnimation();
        this.handleOverlayDetachments();
    }
    /** Closes the actions panel. */
    close(result) {
        if (!this.containerInstance) {
            return;
        }
        this.containerInstance.animationStateChanged
            .pipe(filter((event) => event.phaseName === 'start'), take(1))
            .subscribe(({ totalTime }) => {
            this.closeAnimationFallbackTimeout = setTimeout(() => this.dialogRef.close(this.result), totalTime + 100);
        });
        this.result = result;
        this.containerInstance.startCloseAnimation();
        this.containerInstance = null;
    }
    handleAnimation() {
        this.containerInstance.animationStateChanged
            .pipe(filter((event) => event.phaseName === 'done' && event.toState === 'visible'), take(1))
            .subscribe(() => {
            this._afterOpened.next();
            this._afterOpened.complete();
        });
        this.containerInstance.animationStateChanged
            .pipe(filter((event) => event.phaseName === 'done' && event.toState === 'hidden'), take(1))
            .subscribe(() => {
            clearTimeout(this.closeAnimationFallbackTimeout);
            this.dialogRef.close(this.result);
        });
    }
    handleOverlayDetachments() {
        this.dialogRef.overlayRef
            .detachments()
            .pipe(take(1))
            .subscribe(() => {
            this.dialogRef.close(this.result);
        });
    }
}

/** Injection token that can be used to access the data that was passed in to actions panel. */
const KBQ_ACTIONS_PANEL_DATA = new InjectionToken('KBQ_ACTIONS_PANEL_DATA');
/**
 * Selector for actions panel overlay.
 *
 * @docs-private
 */
const KBQ_ACTIONS_PANEL_OVERLAY_SELECTOR = 'kbq-actions-panel-overlay';
/**
 * Service for opening actions panel.
 */
class KbqActionsPanel {
    constructor() {
        this.injector = inject(Injector);
        this.overlay = inject(Overlay);
        this.dialog = inject(Dialog);
        this.defaultConfig = inject(KBQ_ACTIONS_PANEL_DEFAULT_CONFIG);
        this.resizeObserver = inject(SharedResizeObserver);
        /** The reference to the currently opened actions panel. */
        this.openedActionsPanelRef = null;
    }
    ngOnDestroy() {
        this.close();
    }
    open(componentOrTemplateRef, config) {
        const _config = {
            ...this.defaultConfig,
            ...config
        };
        const actionsPanelRef = this.openDialog(componentOrTemplateRef, _config);
        actionsPanelRef.afterClosed.subscribe(() => {
            if (this.openedActionsPanelRef === actionsPanelRef) {
                this.openedActionsPanelRef = null;
            }
        });
        if (this.openedActionsPanelRef) {
            this.openedActionsPanelRef.afterClosed.subscribe(() => {
                actionsPanelRef.containerInstance?.startOpenAnimation();
            });
            this.openedActionsPanelRef.close();
        }
        else {
            actionsPanelRef.containerInstance.startOpenAnimation();
        }
        this.openedActionsPanelRef = actionsPanelRef;
        return actionsPanelRef;
    }
    /** Closes the currently opened actions panel. */
    close(result) {
        this.openedActionsPanelRef?.close(result);
    }
    openDialog(componentOrTemplateRef, config = {}) {
        let actionsPanelRef;
        const { overlayContainer, overlayPanelClass } = config;
        this.dialog.open(componentOrTemplateRef, {
            ...config,
            container: KbqActionsPanelContainer,
            restoreFocus: false,
            autoFocus: null,
            hasBackdrop: false,
            // Disable closing since we need to sync it up to the animation ourselves
            closeOnOverlayDetachments: false,
            // Disable closing since we need to sync it up to the animation ourselves
            closeOnDestroy: false,
            // Disable closing since we need to sync it up to the animation ourselves
            disableClose: true,
            scrollStrategy: config.scrollStrategy && config.scrollStrategy(this.overlay),
            positionStrategy: overlayContainer
                ? this.overlay
                    .position()
                    .flexibleConnectedTo(overlayContainer)
                    .withPositions([{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'bottom' }])
                    .withFlexibleDimensions()
                    .withPush(false)
                    .withLockedPosition()
                    .withGrowAfterOpen()
                : this.overlay.position().global().centerHorizontally().bottom(),
            templateContext: () => {
                return {
                    $implicit: config.data,
                    data: config.data,
                    actionsPanelRef
                };
            },
            injector: Injector.create({
                parent: config.injector || this.injector,
                providers: [{ provide: KbqActionsPanelConfig, useValue: config }]
            }),
            providers: (dialogRef, _dialogConfig, container) => {
                actionsPanelRef = new KbqActionsPanelRef(dialogRef, container);
                return [
                    { provide: KbqActionsPanelRef, useValue: actionsPanelRef },
                    { provide: KBQ_ACTIONS_PANEL_DATA, useValue: config.data }
                ];
            }
        });
        const { overlayRef } = actionsPanelRef;
        overlayRef.addPanelClass(KBQ_ACTIONS_PANEL_OVERLAY_SELECTOR);
        if (overlayPanelClass)
            overlayRef.addPanelClass(overlayPanelClass);
        if (overlayContainer) {
            const { afterClosed } = actionsPanelRef;
            this.resizeObserver
                .observe(overlayContainer.nativeElement)
                .pipe(takeUntil(afterClosed))
                .subscribe(() => {
                const { width: maxWidth } = overlayContainer.nativeElement.getBoundingClientRect();
                if (!maxWidth)
                    return;
                overlayRef.overlayElement.style.maxWidth = coerceCssPixelValue(maxWidth);
                overlayRef.updatePosition();
            });
        }
        return actionsPanelRef;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KbqActionsPanel, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KbqActionsPanel, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KbqActionsPanel, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

const COMPONENTS = [
    KbqActionsPanelContainer
];
class KbqActionsPanelModule {
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KbqActionsPanelModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: KbqActionsPanelModule, imports: [KbqActionsPanelContainer], exports: [KbqActionsPanelContainer] }); }
    /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KbqActionsPanelModule, providers: [KbqActionsPanel], imports: [COMPONENTS] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KbqActionsPanelModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: COMPONENTS,
                    exports: COMPONENTS,
                    providers: [KbqActionsPanel]
                }]
        }] });

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

export { KBQ_ACTIONS_PANEL_DATA, KBQ_ACTIONS_PANEL_DEFAULT_CONFIG, KBQ_ACTIONS_PANEL_LOCALE_CONFIGURATION, KBQ_ACTIONS_PANEL_OVERLAY_SELECTOR, KbqActionsPanel, KbqActionsPanelConfig, KbqActionsPanelContainer, KbqActionsPanelModule, KbqActionsPanelRef, kbqActionsPanelDefaultConfigProvider, kbqActionsPanelLocaleConfigurationProvider };
//# sourceMappingURL=koobiq-components-actions-panel.mjs.map
