import * as i0 from '@angular/core';
import { InjectionToken, EventEmitter, inject, ChangeDetectionStrategy, ViewEncapsulation, Component, Injector, Injectable } from '@angular/core';
import { CdkDialogContainer, Dialog } from '@angular/cdk/dialog';
import { Overlay } from '@angular/cdk/overlay';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { CdkPortalOutlet } from '@angular/cdk/portal';
import { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';
import { Subject } from 'rxjs';
import { filter, take } from 'rxjs/operators';

/** Injection token that can be used to access the data that was passed in to a bottom sheet. */
const BOTTOM_SHEET_DATA = new InjectionToken('EmrBottomSheetData');
/**
 * Configuration used when opening a bottom sheet.
 */
class BottomSheetConfig {
    /** The view container to place the overlay for the bottom sheet into. */
    viewContainerRef;
    /** Extra CSS classes to be added to the bottom sheet container. */
    panelClass;
    /** Text layout direction for the bottom sheet. */
    direction;
    /** Data being injected into the child component. */
    data = null;
    /** Whether the bottom sheet has a backdrop. */
    hasBackdrop = true;
    /** Custom class for the backdrop. */
    backdropClass;
    /** Whether the user can use escape or clicking outside to close the bottom sheet. */
    disableClose = false;
    /** Aria label to assign to the bottom sheet element. */
    ariaLabel = null;
    /**
     * Whether this is a modal dialog. Used to set the `aria-modal` attribute.
     */
    ariaModal = false;
    /**
     * Whether the bottom sheet should close when the user goes backwards/forwards in history.
     */
    closeOnNavigation = true;
    /**
     * Where the bottom sheet should focus on open.
     */
    autoFocus = 'first-tabbable';
    /**
     * Whether the bottom sheet should restore focus to the
     * previously-focused element, after it's closed.
     */
    restoreFocus = true;
    /** Scroll strategy to be used for the bottom sheet. */
    scrollStrategy;
    /** Height for the bottom sheet. */
    height = '';
    /** Minimum height for the bottom sheet. If a number is provided, assumes pixel units. */
    minHeight;
    /** Maximum height for the bottom sheet. If a number is provided, assumes pixel units. */
    maxHeight;
}

/**
 * Internal component that wraps user-provided bottom sheet content.
 * @docs-private
 */
class BottomSheetContainer extends CdkDialogContainer {
    _breakpointSubscription;
    /** The state of the bottom sheet animations. */
    _animationState = 'void';
    /** Emits whenever the state of the animation changes. */
    _animationStateChanged = new EventEmitter();
    /** Whether the component has been destroyed. */
    _destroyed = false;
    constructor() {
        super();
        const breakpointObserver = inject(BreakpointObserver);
        this._breakpointSubscription = breakpointObserver
            .observe([Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge])
            .subscribe(() => {
            const classList = this._elementRef.nativeElement.classList;
            classList.toggle('ngs-bottom-sheet-container-medium', breakpointObserver.isMatched(Breakpoints.Medium));
            classList.toggle('ngs-bottom-sheet-container-large', breakpointObserver.isMatched(Breakpoints.Large));
            classList.toggle('ngs-bottom-sheet-container-xlarge', breakpointObserver.isMatched(Breakpoints.XLarge));
        });
    }
    /** Begin animation of bottom sheet entrance into view. */
    enter() {
        if (!this._destroyed) {
            this._animationState = 'visible';
            this._changeDetectorRef.markForCheck();
        }
    }
    /** Begin animation of the bottom sheet exiting from view. */
    exit() {
        if (!this._destroyed) {
            this._animationState = 'hidden';
            this._changeDetectorRef.markForCheck();
        }
    }
    ngOnDestroy() {
        super.ngOnDestroy();
        this._breakpointSubscription.unsubscribe();
        this._destroyed = true;
    }
    _onTransitionEnd(event) {
        if (event.propertyName === 'transform') {
            this._animationStateChanged.emit({
                fromState: this._animationState === 'visible' ? 'void' : 'visible',
                toState: this._animationState,
                totalTime: 300,
                phaseName: 'done',
            });
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BottomSheetContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: BottomSheetContainer, isStandalone: true, selector: "ngs-bottom-sheet-container", host: { attributes: { "tabindex": "-1" }, listeners: { "transitionend": "_onTransitionEnd($event)" }, properties: { "attr.role": "_config.role", "attr.aria-modal": "_config.ariaModal", "attr.aria-label": "_config.ariaLabel", "class.ngs-bottom-sheet-container-visible": "_animationState === \"visible\"", "class.ngs-bottom-sheet-container-hidden": "_animationState === \"hidden\"" }, classAttribute: "ngs-bottom-sheet-container" }, usesInheritance: true, ngImport: i0, template: '<ng-template cdkPortalOutlet />', isInline: true, styles: [".ngs-bottom-sheet-container{box-shadow:0 8px 10px -5px #0003,0 16px 24px 2px #00000024,0 6px 30px 5px #0000001f;padding:8px 16px;min-width:100vw;box-sizing:border-box;display:block;outline:0;max-height:80vh;overflow:auto;position:relative;background:var(--ngs-bottom-sheet-container-background-color, white);color:var(--ngs-bottom-sheet-container-text-color, black);visibility:hidden;transform:translateY(100%);transition:transform .3s cubic-bezier(.4,0,.2,1),visibility .3s}.ngs-bottom-sheet-container-visible{transform:translateY(0);visibility:visible;transition-timing-function:cubic-bezier(0,0,.2,1)}.ngs-bottom-sheet-container-hidden{transform:translateY(100%);visibility:hidden}@media(forced-colors:active){.ngs-bottom-sheet-container{outline:1px solid}}.ngs-bottom-sheet-container-medium,.ngs-bottom-sheet-container-large,.ngs-bottom-sheet-container-xlarge{border-top-left-radius:var(--ngs-bottom-sheet-container-shape, 28px);border-top-right-radius:var(--ngs-bottom-sheet-container-shape, 28px)}.ngs-bottom-sheet-container-medium{min-width:384px;max-width:calc(100vw - 128px)}.ngs-bottom-sheet-container-large{min-width:512px;max-width:calc(100vw - 256px)}.ngs-bottom-sheet-container-xlarge{min-width:576px;max-width:calc(100vw - 384px)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.Eager, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BottomSheetContainer, decorators: [{
            type: Component,
            args: [{ selector: 'ngs-bottom-sheet-container', template: '<ng-template cdkPortalOutlet />', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.Default, imports: [CdkPortalOutlet], host: {
                        'class': 'ngs-bottom-sheet-container',
                        'tabindex': '-1',
                        '[attr.role]': '_config.role',
                        '[attr.aria-modal]': '_config.ariaModal',
                        '[attr.aria-label]': '_config.ariaLabel',
                        '[class.ngs-bottom-sheet-container-visible]': '_animationState === "visible"',
                        '[class.ngs-bottom-sheet-container-hidden]': '_animationState === "hidden"',
                        '(transitionend)': '_onTransitionEnd($event)',
                    }, styles: [".ngs-bottom-sheet-container{box-shadow:0 8px 10px -5px #0003,0 16px 24px 2px #00000024,0 6px 30px 5px #0000001f;padding:8px 16px;min-width:100vw;box-sizing:border-box;display:block;outline:0;max-height:80vh;overflow:auto;position:relative;background:var(--ngs-bottom-sheet-container-background-color, white);color:var(--ngs-bottom-sheet-container-text-color, black);visibility:hidden;transform:translateY(100%);transition:transform .3s cubic-bezier(.4,0,.2,1),visibility .3s}.ngs-bottom-sheet-container-visible{transform:translateY(0);visibility:visible;transition-timing-function:cubic-bezier(0,0,.2,1)}.ngs-bottom-sheet-container-hidden{transform:translateY(100%);visibility:hidden}@media(forced-colors:active){.ngs-bottom-sheet-container{outline:1px solid}}.ngs-bottom-sheet-container-medium,.ngs-bottom-sheet-container-large,.ngs-bottom-sheet-container-xlarge{border-top-left-radius:var(--ngs-bottom-sheet-container-shape, 28px);border-top-right-radius:var(--ngs-bottom-sheet-container-shape, 28px)}.ngs-bottom-sheet-container-medium{min-width:384px;max-width:calc(100vw - 128px)}.ngs-bottom-sheet-container-large{min-width:512px;max-width:calc(100vw - 256px)}.ngs-bottom-sheet-container-xlarge{min-width:576px;max-width:calc(100vw - 384px)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
        }], ctorParameters: () => [] });

/**
 * Reference to a bottom sheet dispatched from the BottomSheet service.
 */
class BottomSheetRef {
    _ref;
    containerInstance;
    /** @internal */
    _refInstance = null;
    /** @internal */
    _refRef = null;
    /** Instance of the component making up the content of the bottom sheet. */
    get instance() {
        return this._refInstance;
    }
    /**
     * `ComponentRef` of the component opened into the bottom sheet. Will be
     * null when the bottom sheet is opened using a `TemplateRef`.
     */
    get componentRef() {
        return this._refRef;
    }
    /** Whether the user is allowed to close the bottom sheet. */
    disableClose;
    /** Subject for notifying the user that the bottom sheet has opened and appeared. */
    _afterOpened = new Subject();
    /** Result to be passed down to the `afterDismissed` stream. */
    _result;
    /** Handle to the timeout that's running as a fallback in case the exit animation doesn't fire. */
    _closeFallbackTimeout;
    constructor(_ref, config, containerInstance) {
        this._ref = _ref;
        this.containerInstance = containerInstance;
        this.disableClose = config.disableClose;
        // Emit when opening animation completes
        containerInstance._animationStateChanged
            .pipe(filter((event) => event.phase === 'done' && event.toState === 'visible'), take(1))
            .subscribe(() => {
            this._afterOpened.next();
            this._afterOpened.complete();
        });
        // Dispose overlay when closing animation is complete
        containerInstance._animationStateChanged
            .pipe(filter((event) => event.phase === 'done' && (event.toState === 'hidden' || event.toState === 'void')), take(1))
            .subscribe(() => {
            if (this._closeFallbackTimeout) {
                clearTimeout(this._closeFallbackTimeout);
            }
            this._ref.close(this._result);
        });
        _ref.overlayRef.detachments().subscribe(() => {
            this._ref.close(this._result);
        });
        _ref.backdropClick.subscribe(() => {
            if (!this.disableClose) {
                this.dismiss();
            }
        });
        _ref.keydownEvents
            .pipe(filter(event => event.keyCode === ESCAPE))
            .subscribe(event => {
            if (!this.disableClose && !hasModifierKey(event)) {
                event.preventDefault();
                this.dismiss();
            }
        });
    }
    /**
     * Dismisses the bottom sheet.
     * @param result Data to be passed back to the bottom sheet opener.
     */
    dismiss(result) {
        if (!this.containerInstance) {
            return;
        }
        // Transition the backdrop in parallel to the bottom sheet.
        this._ref.overlayRef.detachBackdrop();
        this._result = result;
        this.containerInstance.exit();
        this._closeFallbackTimeout = setTimeout(() => {
            this._ref.close(this._result);
        }, 400);
    }
    /** Gets an observable that is notified when the bottom sheet is finished closing. */
    afterDismissed() {
        return this._ref.closed;
    }
    /** Gets an observable that is notified when the bottom sheet has opened and appeared. */
    afterOpened() {
        return this._afterOpened;
    }
    /**
     * Gets an observable that emits when the overlay's backdrop has been clicked.
     */
    backdropClick() {
        return this._ref.backdropClick;
    }
    /**
     * Gets an observable that emits when keydown events are targeted on the overlay.
     */
    keydownEvents() {
        return this._ref.keydownEvents;
    }
}

/** Injection token that can be used to specify default bottom sheet options. */
const BOTTOM_SHEET_DEFAULT_OPTIONS = new InjectionToken('ngs-bottom-sheet-default-options');
class BottomSheet {
    _injector = inject(Injector);
    _overlay = inject(Overlay);
    _dialog = inject(Dialog);
    _parentBottomSheet = inject(BottomSheet, { optional: true, skipSelf: true });
    _defaultOptions = inject(BOTTOM_SHEET_DEFAULT_OPTIONS, { optional: true });
    _bottomSheetRefAtThisLevel = null;
    /** Reference to the currently opened bottom sheet. */
    get _openedBottomSheetRef() {
        const parent = this._parentBottomSheet;
        return parent ? parent._openedBottomSheetRef : this._bottomSheetRefAtThisLevel;
    }
    set _openedBottomSheetRef(value) {
        if (this._parentBottomSheet) {
            this._parentBottomSheet._openedBottomSheetRef = value;
        }
        else {
            this._bottomSheetRefAtThisLevel = value;
        }
    }
    open(componentOrTemplateRef, config) {
        const _config = { ...(this._defaultOptions || new BottomSheetConfig()), ...config };
        let ref;
        this._dialog.open(componentOrTemplateRef, {
            ..._config,
            // Disable closing since we need to sync it up to the animation ourselves.
            disableClose: true,
            // Disable closing on detachments so that we can sync up the animation.
            closeOnOverlayDetachments: false,
            maxWidth: '100%',
            container: BottomSheetContainer,
            scrollStrategy: _config.scrollStrategy || this._overlay.scrollStrategies.block(),
            positionStrategy: this._overlay.position()
                .global()
                .centerHorizontally()
                .bottom('0'),
            templateContext: () => ({ bottomSheetRef: ref }),
            providers: (cdkRef, _cdkConfig, container) => {
                ref = new BottomSheetRef(cdkRef, _config, container);
                return [
                    { provide: BottomSheetRef, useValue: ref },
                    { provide: BOTTOM_SHEET_DATA, useValue: _config.data },
                ];
            },
        });
        ref.afterDismissed().subscribe(() => {
            // Clear the bottom sheet ref if it hasn't already been replaced by a newer one.
            if (this._openedBottomSheetRef === ref) {
                this._openedBottomSheetRef = null;
            }
        });
        if (this._openedBottomSheetRef) {
            // If a bottom sheet is already in view, dismiss it and enter the
            // new bottom sheet after exit animation is complete.
            this._openedBottomSheetRef.afterDismissed().subscribe(() => ref.containerInstance?.enter());
            this._openedBottomSheetRef.dismiss();
        }
        else {
            // If no bottom sheet is in view, enter the new bottom sheet.
            ref.containerInstance.enter();
        }
        this._openedBottomSheetRef = ref;
        return ref;
    }
    /**
     * Dismisses the currently-visible bottom sheet.
     * @param result Data to pass to the bottom sheet instance.
     */
    dismiss(result) {
        if (this._openedBottomSheetRef) {
            this._openedBottomSheetRef.dismiss(result);
        }
    }
    ngOnDestroy() {
        if (this._bottomSheetRefAtThisLevel) {
            this._bottomSheetRefAtThisLevel.dismiss();
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BottomSheet, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BottomSheet, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: BottomSheet, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

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

export { BOTTOM_SHEET_DATA, BOTTOM_SHEET_DEFAULT_OPTIONS, BottomSheet, BottomSheetConfig, BottomSheetContainer, BottomSheetRef };
//# sourceMappingURL=ngstarter-ui-components-bottom-sheet.mjs.map
