UNPKG

@ngxpert/hot-toast

Version:

Smoking hot Notifications for Angular. Lightweight, customizable and beautiful by default.

1,417 lines 77.2 kB
import { NgStyle, isPlatformServer } from '@angular/common';
import * as i0 from '@angular/core';
import { Input, ChangeDetectionStrategy, Component, EventEmitter, signal, inject, Injector, Renderer2, NgZone, ChangeDetectorRef, ViewChild, Output, ViewChildren, PLATFORM_ID, Injectable, makeEnvironmentProviders } from '@angular/core';
import { DynamicViewDirective, isTemplateRef, isComponent, ViewService } from '@ngneat/overview';
import { Subject, race, defer } from 'rxjs';
import { map, filter, tap } from 'rxjs/operators';

const HOT_TOAST_DEFAULT_TIMEOUTS = {
    blank: 4000,
    error: 4000,
    success: 4000,
    loading: 30000,
    warning: 4000,
    info: 4000,
};
const EXIT_ANIMATION_DURATION = 800;
const ENTER_ANIMATION_DURATION = 350;
const HOT_TOAST_MARGIN = 8;
const HOT_TOAST_DEPTH_SCALE = 0.05;
const HOT_TOAST_DEPTH_SCALE_ADD = 1;

class HotToastRef {
    constructor(toast) {
        this.toast = toast;
        this.groupRefs = [];
        this.groupExpanded = false;
        /** Subject for notifying the user that the toast has been closed. */
        this._onClosed = new Subject();
        /** Subject for notifying the user that the toast has been closed. */
        this._onGroupToggle = new Subject();
    }
    set data(data) {
        this.toast.data = data;
    }
    get data() {
        return this.toast.data;
    }
    set dispose(value) {
        this._dispose = value;
    }
    getToast() {
        return this.toast;
    }
    /**
     * Used for internal purpose
     * Attach ToastRef to container
     */
    appendTo(container, skipAttachToParent) {
        const { dispose, updateMessage, updateToast, afterClosed, afterGroupToggled, afterGroupRefsAttached } = container.addToast(this, skipAttachToParent);
        this.dispose = dispose;
        this.updateMessage = updateMessage;
        this.updateToast = updateToast;
        this.afterClosed = race(this._onClosed.asObservable(), afterClosed);
        this.afterGroupToggled = race(this._onGroupToggle.asObservable(), afterGroupToggled);
        this.afterGroupRefsAttached = afterGroupRefsAttached;
        return this;
    }
    /**
     * Closes the toast
     *
     * @param [closeData={ dismissedByAction: false }] -
     * Make sure to pass { dismissedByAction: true } when closing from template
     * @memberof HotToastRef
     */
    close(closeData = { dismissedByAction: false }) {
        this.groupRefs.forEach((ref) => ref.close());
        this._dispose();
        this._onClosed.next({ dismissedByAction: closeData.dismissedByAction, id: this.toast.id });
        this._onClosed.complete();
    }
    toggleGroup(eventData = { byAction: false }) {
        this.groupExpanded = !this.groupExpanded;
        this._onGroupToggle.next({
            byAction: eventData.byAction,
            id: this.toast.id,
            event: this.groupExpanded ? 'expand' : 'collapse',
        });
    }
    show() {
        this.toast.visible = true;
    }
}

const animate = (renderer, element, animation) => {
    renderer.setStyle(element, 'animation', animation);
};

class LoaderComponent {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: LoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.0", type: LoaderComponent, isStandalone: true, selector: "hot-toast-loader", inputs: { theme: "theme" }, ngImport: i0, template: "<div\n  class=\"hot-toast-loader-icon\"\n  [style.border-color]=\"theme?.primary\"\n  [style.border-right-color]=\"theme?.secondary\"\n></div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: LoaderComponent, decorators: [{
            type: Component,
            args: [{ selector: 'hot-toast-loader', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n  class=\"hot-toast-loader-icon\"\n  [style.border-color]=\"theme?.primary\"\n  [style.border-right-color]=\"theme?.secondary\"\n></div>\n" }]
        }], propDecorators: { theme: [{
                type: Input
            }] } });

class ErrorComponent {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.0", type: ErrorComponent, isStandalone: true, selector: "hot-toast-error", inputs: { theme: "theme" }, ngImport: i0, template: "<div\n  class=\"hot-toast-error-icon\"\n  [style.--error-primary]=\"theme?.primary\"\n  [style.--error-secondary]=\"theme?.secondary\"\n></div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ErrorComponent, decorators: [{
            type: Component,
            args: [{ selector: 'hot-toast-error', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div\n  class=\"hot-toast-error-icon\"\n  [style.--error-primary]=\"theme?.primary\"\n  [style.--error-secondary]=\"theme?.secondary\"\n></div>\n" }]
        }], propDecorators: { theme: [{
                type: Input
            }] } });

class CheckMarkComponent {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: CheckMarkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.0", type: CheckMarkComponent, isStandalone: true, selector: "hot-toast-checkmark", inputs: { theme: "theme" }, ngImport: i0, template: "<div\n  class=\"hot-toast-checkmark-icon\"\n  [style.--check-primary]=\"theme?.primary\"\n  [style.--check-secondary]=\"theme?.secondary\"\n></div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: CheckMarkComponent, decorators: [{
            type: Component,
            args: [{ selector: 'hot-toast-checkmark', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div\n  class=\"hot-toast-checkmark-icon\"\n  [style.--check-primary]=\"theme?.primary\"\n  [style.--check-secondary]=\"theme?.secondary\"\n></div>\n" }]
        }], propDecorators: { theme: [{
                type: Input
            }] } });

class WarningComponent {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: WarningComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.0", type: WarningComponent, isStandalone: true, selector: "hot-toast-warning", inputs: { theme: "theme" }, ngImport: i0, template: "<div\n  class=\"hot-toast-warning-icon\"\n  [style.--warn-primary]=\"theme?.primary\"\n  [style.--warn-secondary]=\"theme?.secondary\"\n></div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: WarningComponent, decorators: [{
            type: Component,
            args: [{ selector: 'hot-toast-warning', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div\n  class=\"hot-toast-warning-icon\"\n  [style.--warn-primary]=\"theme?.primary\"\n  [style.--warn-secondary]=\"theme?.secondary\"\n></div>\n" }]
        }], propDecorators: { theme: [{
                type: Input
            }] } });

class InfoComponent {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: InfoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.0", type: InfoComponent, isStandalone: true, selector: "hot-toast-info", inputs: { theme: "theme" }, ngImport: i0, template: "<div\n  class=\"hot-toast-info-icon\"\n  [style.--info-primary]=\"theme?.primary\"\n  [style.--info-secondary]=\"theme?.secondary\"\n></div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: InfoComponent, decorators: [{
            type: Component,
            args: [{ selector: 'hot-toast-info', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div\n  class=\"hot-toast-info-icon\"\n  [style.--info-primary]=\"theme?.primary\"\n  [style.--info-secondary]=\"theme?.secondary\"\n></div>\n" }]
        }], propDecorators: { theme: [{
                type: Input
            }] } });

class IndicatorComponent {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: IndicatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: IndicatorComponent, isStandalone: true, selector: "hot-toast-indicator", inputs: { theme: "theme", type: "type" }, ngImport: i0, template: "@if (type !== 'blank') {\n<div class=\"hot-toast-indicator-wrapper\">\n  @if (type === 'loading') {\n  <hot-toast-loader [theme]=\"theme\"></hot-toast-loader>\n  } @if (type !== 'loading') {\n  <div class=\"hot-toast-status-wrapper\">\n    <div>\n      @switch (type) { @case ('error') {\n      <div>\n        <hot-toast-error [theme]=\"theme\"></hot-toast-error>\n      </div>\n      } @case ('success') {\n      <div>\n        <hot-toast-checkmark [theme]=\"theme\"></hot-toast-checkmark>\n      </div>\n      } @case ('warning') {\n      <div>\n        <hot-toast-warning [theme]=\"theme\"></hot-toast-warning>\n      </div>\n      } @case ('info') {\n      <div>\n        <hot-toast-info [theme]=\"theme\"></hot-toast-info>\n      </div>\n      } }\n    </div>\n  </div>\n  }\n</div>\n}\n", dependencies: [{ kind: "component", type: LoaderComponent, selector: "hot-toast-loader", inputs: ["theme"] }, { kind: "component", type: ErrorComponent, selector: "hot-toast-error", inputs: ["theme"] }, { kind: "component", type: CheckMarkComponent, selector: "hot-toast-checkmark", inputs: ["theme"] }, { kind: "component", type: WarningComponent, selector: "hot-toast-warning", inputs: ["theme"] }, { kind: "component", type: InfoComponent, selector: "hot-toast-info", inputs: ["theme"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: IndicatorComponent, decorators: [{
            type: Component,
            args: [{ selector: 'hot-toast-indicator', changeDetection: ChangeDetectionStrategy.OnPush, imports: [LoaderComponent, ErrorComponent, CheckMarkComponent, WarningComponent, InfoComponent], template: "@if (type !== 'blank') {\n<div class=\"hot-toast-indicator-wrapper\">\n  @if (type === 'loading') {\n  <hot-toast-loader [theme]=\"theme\"></hot-toast-loader>\n  } @if (type !== 'loading') {\n  <div class=\"hot-toast-status-wrapper\">\n    <div>\n      @switch (type) { @case ('error') {\n      <div>\n        <hot-toast-error [theme]=\"theme\"></hot-toast-error>\n      </div>\n      } @case ('success') {\n      <div>\n        <hot-toast-checkmark [theme]=\"theme\"></hot-toast-checkmark>\n      </div>\n      } @case ('warning') {\n      <div>\n        <hot-toast-warning [theme]=\"theme\"></hot-toast-warning>\n      </div>\n      } @case ('info') {\n      <div>\n        <hot-toast-info [theme]=\"theme\"></hot-toast-info>\n      </div>\n      } }\n    </div>\n  </div>\n  }\n</div>\n}\n" }]
        }], propDecorators: { theme: [{
                type: Input
            }], type: [{
                type: Input
            }] } });

class AnimatedIconComponent {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AnimatedIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.0", type: AnimatedIconComponent, isStandalone: true, selector: "hot-toast-animated-icon", inputs: { iconTheme: "iconTheme", icon: "icon" }, ngImport: i0, template: "<div class=\"hot-toast-animated-icon\" [style.color]=\"iconTheme?.primary\">\n  <ng-container *dynamicView=\"icon\"></ng-container>\n</div>\n", dependencies: [{ kind: "directive", type: DynamicViewDirective, selector: "[dynamicView]", inputs: ["dynamicView", "dynamicViewInjector", "dynamicViewContext", "dynamicViewInputs"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AnimatedIconComponent, decorators: [{
            type: Component,
            args: [{ selector: 'hot-toast-animated-icon', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [DynamicViewDirective], template: "<div class=\"hot-toast-animated-icon\" [style.color]=\"iconTheme?.primary\">\n  <ng-container *dynamicView=\"icon\"></ng-container>\n</div>\n" }]
        }], propDecorators: { iconTheme: [{
                type: Input
            }], icon: [{
                type: Input
            }] } });

class HotToastGroupItemComponent {
    constructor() {
        this.offset = 0;
        this._toastsAfter = 0;
        this.isShowingAllToasts = false;
        this.height = new EventEmitter();
        this.beforeClosed = new EventEmitter();
        this.afterClosed = new EventEmitter();
        this.showAllToasts = new EventEmitter();
        this.toggleGroup = new EventEmitter();
        this.isManualClose = false;
        this.toastBarBaseStylesSignal = signal({});
        this.unlisteners = [];
        this.softClosed = false;
        this.injector = inject(Injector);
        this.renderer = inject(Renderer2);
        this.ngZone = inject(NgZone);
        this.cdr = inject(ChangeDetectorRef);
    }
    set toast(value) {
        this._toast = value;
        const ogStyle = this.toastBarBaseStylesSignal();
        const newStyle = { ...value.style };
        if (ogStyle['animation']?.includes('hotToastExitAnimation')) {
            // if toast is set for exit, we don't need want set the enter animation
            newStyle['animation'] = ogStyle['animation'];
        }
        else {
            const top = value.position.includes('top');
            const enterAnimation = `hotToastEnterAnimation${top ? 'Negative' : 'Positive'} ${ENTER_ANIMATION_DURATION}ms cubic-bezier(0.21, 1.02, 0.73, 1) forwards`;
            newStyle['animation'] = enterAnimation;
        }
        this.toastBarBaseStylesSignal.set(newStyle);
    }
    get toast() {
        return this._toast;
    }
    get toastsAfter() {
        return this._toastsAfter;
    }
    set toastsAfter(value) {
        this._toastsAfter = value;
    }
    get toastBarBaseHeight() {
        return this.toastBarBase.nativeElement.offsetHeight;
    }
    get scale() {
        return this.defaultConfig.stacking !== 'vertical' && !this.isShowingAllToasts
            ? this.toastsAfter * -HOT_TOAST_DEPTH_SCALE + 1
            : 1;
    }
    get translateY() {
        return this.offset * (this.top ? 1 : -1) + 'px';
    }
    get exitAnimationDelay() {
        return this.toast.duration + 'ms';
    }
    get top() {
        return this.toast.position.includes('top');
    }
    get containerPositionStyle() {
        const verticalStyle = this.top ? { top: 0 } : { bottom: 0 };
        const transform = `translateY(var(--hot-toast-translate-y)) scale(var(--hot-toast-scale))`;
        const horizontalStyle = this.toast.position.includes('left')
            ? {
                left: 0,
            }
            : this.toast.position.includes('right')
                ? {
                    right: 0,
                }
                : {
                    left: 0,
                    right: 0,
                    justifyContent: 'center',
                };
        return {
            transform,
            ...verticalStyle,
            ...horizontalStyle,
        };
    }
    get isIconString() {
        return typeof this.toast.icon === 'string';
    }
    get groupChildrenToastRefs() {
        return this.toastRef.groupRefs.filter((ref) => !!ref);
    }
    set groupChildrenToastRefs(value) {
        this.toastRef.groupRefs = value;
    }
    get groupChildrenToasts() {
        return this.groupChildrenToastRefs.map((ref) => ref.getToast());
    }
    get groupHeight() {
        return this.visibleToasts.map((t) => t.height).reduce((prev, curr) => prev + curr, 0);
    }
    get isExpanded() {
        return this.toastRef.groupExpanded;
    }
    ngOnChanges(changes) {
        if (changes.toast && !changes.toast.firstChange && changes.toast.currentValue?.message) {
            requestAnimationFrame(() => {
                this.height.emit(this.toastBarBase.nativeElement.offsetHeight);
            });
        }
    }
    ngOnInit() {
        if (isTemplateRef(this.toast.message)) {
            this.context = { $implicit: this.toastRef };
        }
        if (isComponent(this.toast.message)) {
            this.toastComponentInjector = Injector.create({
                providers: [
                    {
                        provide: HotToastRef,
                        useValue: this.toastRef,
                    },
                ],
                parent: this.toast.injector || this.injector,
            });
        }
        const nativeElement = this.toastBarBase.nativeElement;
        // Caretaker note: `animationstart` and `animationend` events are event tasks that trigger change detection.
        // We'd want to trigger the change detection only if it's an exit animation.
        this.ngZone.runOutsideAngular(() => {
            this.unlisteners.push(
            // Caretaker note: we have to remove these event listeners at the end (even if the element is removed from DOM).
            // zone.js stores its `ZoneTask`s within the `nativeElement[Zone.__symbol__('animationstart') + 'false']` property
            // with callback that capture `this`.
            this.renderer.listen(nativeElement, 'animationstart', (event) => {
                if (this.isExitAnimation(event)) {
                    this.ngZone.run(() => {
                        this.renderer.setStyle(nativeElement, 'pointer-events', 'none');
                        this.renderer.setStyle(nativeElement.parentElement, 'pointer-events', 'none');
                        this.beforeClosed.emit();
                    });
                }
            }), this.renderer.listen(nativeElement, 'animationend', (event) => {
                if (this.isEnterAnimation(event)) {
                    this.ngZone.run(() => {
                        if (this.toast.autoClose) {
                            const exitAnimation = `hotToastExitAnimation${this.top ? 'Negative' : 'Positive'} ${EXIT_ANIMATION_DURATION}ms forwards cubic-bezier(0.06, 0.71, 0.55, 1) var(--hot-toast-exit-animation-delay) var(--hot-toast-exit-animation-state)`;
                            this.toastBarBaseStylesSignal.set({ ...this.toast.style, animation: exitAnimation });
                        }
                    });
                }
                if (this.isExitAnimation(event)) {
                    this.ngZone.run(() => this.afterClosed.emit({ dismissedByAction: this.isManualClose, id: this.toast.id }));
                }
            }));
        });
    }
    ngAfterViewInit() {
        const nativeElement = this.toastBarBase.nativeElement;
        // Caretaker note: accessing `offsetHeight` triggers the whole layout update.
        // Macro tasks (like `setTimeout`) might be executed within the current rendering frame and cause a frame drop.
        requestAnimationFrame(() => {
            this.height.emit(nativeElement.offsetHeight);
        });
        this.setToastAttributes();
    }
    softClose() {
        const exitAnimation = `hotToastExitSoftAnimation${this.top ? 'Negative' : 'Positive'} ${EXIT_ANIMATION_DURATION}ms forwards cubic-bezier(0.06, 0.71, 0.55, 1)`;
        const nativeElement = this.toastBarBase.nativeElement;
        animate(this.renderer, nativeElement, exitAnimation);
        this.softClosed = true;
    }
    softOpen() {
        const softEnterAnimation = `hotToastEnterSoftAnimation${top ? 'Negative' : 'Positive'} ${ENTER_ANIMATION_DURATION}ms cubic-bezier(0.21, 1.02, 0.73, 1) forwards`;
        const nativeElement = this.toastBarBase.nativeElement;
        animate(this.renderer, nativeElement, softEnterAnimation);
        this.softClosed = false;
    }
    close() {
        this.isManualClose = true;
        this.cdr.markForCheck();
        const exitAnimation = `hotToastExitAnimation${this.top ? 'Negative' : 'Positive'} ${EXIT_ANIMATION_DURATION}ms forwards cubic-bezier(0.06, 0.71, 0.55, 1)`;
        this.toastBarBaseStylesSignal.set({ ...this.toast.style, animation: exitAnimation });
    }
    handleMouseEnter() {
        this.showAllToasts.emit(true);
    }
    handleMouseLeave() {
        this.showAllToasts.emit(false);
    }
    ngOnDestroy() {
        this.close();
        while (this.unlisteners.length) {
            this.unlisteners.pop()();
        }
    }
    isExitAnimation(ev) {
        return ev.animationName.includes('hotToastExitAnimation');
    }
    isEnterAnimation(ev) {
        return ev.animationName.includes('hotToastEnterAnimation');
    }
    setToastAttributes() {
        const toastAttributes = this.toast.attributes;
        for (const [key, value] of Object.entries(toastAttributes)) {
            this.renderer.setAttribute(this.toastBarBase.nativeElement, key, value);
        }
    }
    get visibleToasts() {
        return this.groupChildrenToasts.filter((t) => t.visible);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: HotToastGroupItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: HotToastGroupItemComponent, isStandalone: true, selector: "hot-toast-group-item", inputs: { toast: "toast", offset: "offset", defaultConfig: "defaultConfig", toastRef: "toastRef", toastsAfter: "toastsAfter", isShowingAllToasts: "isShowingAllToasts" }, outputs: { height: "height", beforeClosed: "beforeClosed", afterClosed: "afterClosed", showAllToasts: "showAllToasts", toggleGroup: "toggleGroup" }, viewQueries: [{ propertyName: "toastBarBase", first: true, predicate: ["hotToastBarBase"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div\n  class=\"hot-toast-bar-base-container\"\n  [style]=\"containerPositionStyle\"\n  [class]=\"'hot-toast-theme-' + toast.theme\"\n  [style.--hot-toast-scale]=\"scale\"\n  [style.--hot-toast-translate-y]=\"translateY\"\n>\n  <div class=\"hot-toast-bar-base-wrapper\" (mouseenter)=\"handleMouseEnter()\" (mouseleave)=\"handleMouseLeave()\">\n    <div\n      class=\"hot-toast-bar-base\"\n      #hotToastBarBase\n      [style]=\"toastBarBaseStylesSignal()\"\n      [class]=\"toast.className\"\n      [style.--hot-toast-animation-state]=\"isManualClose ? 'running' : 'paused'\"\n      [style.--hot-toast-exit-animation-state]=\"isShowingAllToasts ? 'paused' : 'running'\"\n      [style.--hot-toast-exit-animation-delay]=\"exitAnimationDelay\"\n      [attr.aria-live]=\"toast.ariaLive\"\n      [attr.role]=\"toast.role\"\n    >\n      <div class=\"hot-toast-icon\" aria-hidden=\"true\">\n        @if (toast.icon !== undefined) { @if (isIconString) {\n        <hot-toast-animated-icon [iconTheme]=\"toast.iconTheme\">{{ toast.icon }}</hot-toast-animated-icon>\n        } @else {\n        <div>\n          <ng-container *dynamicView=\"toast.icon\"></ng-container>\n        </div>\n        } } @else {\n        <hot-toast-indicator [theme]=\"toast.iconTheme\" [type]=\"toast.type\"></hot-toast-indicator>\n        }\n      </div>\n      <div class=\"hot-toast-message\">\n        <ng-container *dynamicView=\"toast.message; context: context; injector: toastComponentInjector\"></ng-container>\n      </div>\n      @if (toast.dismissible) {\n      <button\n        (click)=\"close()\"\n        type=\"button\"\n        class=\"hot-toast-close-btn\"\n        aria-label=\"Close\"\n        [style]=\"toast.closeStyle\"\n      ></button>\n      }\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "component", type: AnimatedIconComponent, selector: "hot-toast-animated-icon", inputs: ["iconTheme", "icon"] }, { kind: "component", type: IndicatorComponent, selector: "hot-toast-indicator", inputs: ["theme", "type"] }, { kind: "directive", type: DynamicViewDirective, selector: "[dynamicView]", inputs: ["dynamicView", "dynamicViewInjector", "dynamicViewContext", "dynamicViewInputs"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: HotToastGroupItemComponent, decorators: [{
            type: Component,
            args: [{ selector: 'hot-toast-group-item', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AnimatedIconComponent, IndicatorComponent, DynamicViewDirective], template: "<div\n  class=\"hot-toast-bar-base-container\"\n  [style]=\"containerPositionStyle\"\n  [class]=\"'hot-toast-theme-' + toast.theme\"\n  [style.--hot-toast-scale]=\"scale\"\n  [style.--hot-toast-translate-y]=\"translateY\"\n>\n  <div class=\"hot-toast-bar-base-wrapper\" (mouseenter)=\"handleMouseEnter()\" (mouseleave)=\"handleMouseLeave()\">\n    <div\n      class=\"hot-toast-bar-base\"\n      #hotToastBarBase\n      [style]=\"toastBarBaseStylesSignal()\"\n      [class]=\"toast.className\"\n      [style.--hot-toast-animation-state]=\"isManualClose ? 'running' : 'paused'\"\n      [style.--hot-toast-exit-animation-state]=\"isShowingAllToasts ? 'paused' : 'running'\"\n      [style.--hot-toast-exit-animation-delay]=\"exitAnimationDelay\"\n      [attr.aria-live]=\"toast.ariaLive\"\n      [attr.role]=\"toast.role\"\n    >\n      <div class=\"hot-toast-icon\" aria-hidden=\"true\">\n        @if (toast.icon !== undefined) { @if (isIconString) {\n        <hot-toast-animated-icon [iconTheme]=\"toast.iconTheme\">{{ toast.icon }}</hot-toast-animated-icon>\n        } @else {\n        <div>\n          <ng-container *dynamicView=\"toast.icon\"></ng-container>\n        </div>\n        } } @else {\n        <hot-toast-indicator [theme]=\"toast.iconTheme\" [type]=\"toast.type\"></hot-toast-indicator>\n        }\n      </div>\n      <div class=\"hot-toast-message\">\n        <ng-container *dynamicView=\"toast.message; context: context; injector: toastComponentInjector\"></ng-container>\n      </div>\n      @if (toast.dismissible) {\n      <button\n        (click)=\"close()\"\n        type=\"button\"\n        class=\"hot-toast-close-btn\"\n        aria-label=\"Close\"\n        [style]=\"toast.closeStyle\"\n      ></button>\n      }\n    </div>\n  </div>\n</div>\n" }]
        }], propDecorators: { toast: [{
                type: Input
            }], offset: [{
                type: Input
            }], defaultConfig: [{
                type: Input
            }], toastRef: [{
                type: Input
            }], toastsAfter: [{
                type: Input
            }], isShowingAllToasts: [{
                type: Input
            }], height: [{
                type: Output
            }], beforeClosed: [{
                type: Output
            }], afterClosed: [{
                type: Output
            }], showAllToasts: [{
                type: Output
            }], toggleGroup: [{
                type: Output
            }], toastBarBase: [{
                type: ViewChild,
                args: ['hotToastBarBase', { static: true }]
            }] } });

class HotToastComponent {
    constructor() {
        this.offset = 0;
        this._toastsAfter = 0;
        this.isShowingAllToasts = false;
        this.height = new EventEmitter();
        this.beforeClosed = new EventEmitter();
        this.afterClosed = new EventEmitter();
        this.showAllToasts = new EventEmitter();
        this.toggleGroup = new EventEmitter();
        this.isManualClose = false;
        this.isExpanded = false;
        this.toastBarBaseStylesSignal = signal({});
        this.unlisteners = [];
        this.softClosed = false;
        this.groupRefs = [];
        this.injector = inject(Injector);
        this.renderer = inject(Renderer2);
        this.ngZone = inject(NgZone);
        this.cdr = inject(ChangeDetectorRef);
    }
    set toast(value) {
        this._toast = value;
        const ogStyle = this.toastBarBaseStylesSignal();
        const newStyle = { ...value.style };
        if (ogStyle['animation']?.includes('hotToastExitAnimation')) {
            // if toast is set for exit, we don't need want set the enter animation
            newStyle['animation'] = ogStyle['animation'];
        }
        else {
            const top = value.position.includes('top');
            const enterAnimation = `hotToastEnterAnimation${top ? 'Negative' : 'Positive'} ${ENTER_ANIMATION_DURATION}ms cubic-bezier(0.21, 1.02, 0.73, 1) forwards`;
            newStyle['animation'] = enterAnimation;
        }
        this.toastBarBaseStylesSignal.set(newStyle);
    }
    get toast() {
        return this._toast;
    }
    get toastsAfter() {
        return this._toastsAfter;
    }
    set toastsAfter(value) {
        this._toastsAfter = value;
        if (this.defaultConfig?.visibleToasts > 0) {
            if (this.toast.autoClose) {
                // if (value >= this.defaultConfig?.visibleToasts) {
                //   this.close();
                // }
            }
            else {
                if (value >= this.defaultConfig?.visibleToasts) {
                    this.softClose();
                }
                else if (this.softClosed) {
                    this.softOpen();
                }
            }
        }
    }
    get toastBarBaseHeight() {
        return this.toastBarBase.nativeElement.offsetHeight;
    }
    get scale() {
        return this.defaultConfig.stacking !== 'vertical' && !this.isShowingAllToasts
            ? this.toastsAfter * -HOT_TOAST_DEPTH_SCALE + 1
            : 1;
    }
    get translateY() {
        return this.offset * (this.top ? 1 : -1) + 'px';
    }
    get exitAnimationDelay() {
        return this.toast.duration + 'ms';
    }
    get top() {
        return this.toast.position.includes('top');
    }
    get containerPositionStyle() {
        const verticalStyle = this.top ? { top: 0 } : { bottom: 0 };
        const transform = `translateY(var(--hot-toast-translate-y)) scale(var(--hot-toast-scale))`;
        const horizontalStyle = this.toast.position.includes('left')
            ? {
                left: 0,
            }
            : this.toast.position.includes('right')
                ? {
                    right: 0,
                }
                : {
                    left: 0,
                    right: 0,
                    justifyContent: 'center',
                };
        return {
            transform,
            ...verticalStyle,
            ...horizontalStyle,
        };
    }
    get isIconString() {
        return typeof this.toast.icon === 'string';
    }
    get groupChildrenToastRefs() {
        return this.groupRefs.filter((ref) => !!ref);
    }
    set groupChildrenToastRefs(value) {
        this.groupRefs = value;
        this.toastRef.groupRefs = value;
    }
    get groupChildrenToasts() {
        return this.groupChildrenToastRefs.map((ref) => ref.getToast());
    }
    get groupHeight() {
        return this.visibleToasts
            .slice(-this.defaultConfig.visibleToasts)
            .map((t) => t.height)
            .reduce((prev, curr) => prev + curr, 0);
    }
    get visibleToasts() {
        return this.groupChildrenToasts.filter((t) => t.visible);
    }
    ngDoCheck() {
        if (this.toastRef.groupRefs.length !== this.groupRefs.length) {
            this.groupRefs = this.toastRef.groupRefs.slice();
            this.cdr.markForCheck();
            this.emiHeightWithGroup(this.isExpanded);
        }
        if (this.toastRef.groupExpanded !== this.isExpanded) {
            this.isExpanded = this.toastRef.groupExpanded;
            this.cdr.markForCheck();
            this.emiHeightWithGroup(this.isExpanded);
        }
    }
    ngOnChanges(changes) {
        if (changes.toast && !changes.toast.firstChange && changes.toast.currentValue?.message) {
            this, this.emiHeightWithGroup(this.isExpanded);
        }
    }
    ngOnInit() {
        if (isTemplateRef(this.toast.message)) {
            this.context = { $implicit: this.toastRef };
        }
        if (isComponent(this.toast.message)) {
            this.toastComponentInjector = Injector.create({
                providers: [
                    {
                        provide: HotToastRef,
                        useValue: this.toastRef,
                    },
                ],
                parent: this.toast.injector || this.injector,
            });
        }
        const nativeElement = this.toastBarBase.nativeElement;
        // Caretaker note: `animationstart` and `animationend` events are event tasks that trigger change detection.
        // We'd want to trigger the change detection only if it's an exit animation.
        this.ngZone.runOutsideAngular(() => {
            this.unlisteners.push(
            // Caretaker note: we have to remove these event listeners at the end (even if the element is removed from DOM).
            // zone.js stores its `ZoneTask`s within the `nativeElement[Zone.__symbol__('animationstart') + 'false']` property
            // with callback that capture `this`.
            this.renderer.listen(nativeElement, 'animationstart', (event) => {
                if (this.isExitAnimation(event)) {
                    this.ngZone.run(() => {
                        this.renderer.setStyle(nativeElement, 'pointer-events', 'none');
                        this.renderer.setStyle(nativeElement.parentElement, 'pointer-events', 'none');
                        this.beforeClosed.emit();
                    });
                }
            }), this.renderer.listen(nativeElement, 'animationend', (event) => {
                if (this.isEnterAnimation(event)) {
                    this.ngZone.run(() => {
                        if (this.toast.autoClose) {
                            const exitAnimation = `hotToastExitAnimation${this.top ? 'Negative' : 'Positive'} ${EXIT_ANIMATION_DURATION}ms forwards cubic-bezier(0.06, 0.71, 0.55, 1) var(--hot-toast-exit-animation-delay) var(--hot-toast-exit-animation-state)`;
                            this.toastBarBaseStylesSignal.set({ ...this.toast.style, animation: exitAnimation });
                        }
                    });
                }
                if (this.isExitAnimation(event)) {
                    this.ngZone.run(() => this.afterClosed.emit({ dismissedByAction: this.isManualClose, id: this.toast.id }));
                }
            }));
        });
    }
    ngAfterViewInit() {
        const nativeElement = this.toastBarBase.nativeElement;
        // Caretaker note: accessing `offsetHeight` triggers the whole layout update.
        // Macro tasks (like `setTimeout`) might be executed within the current rendering frame and cause a frame drop.
        requestAnimationFrame(() => {
            this.height.emit(nativeElement.offsetHeight);
        });
        this.setToastAttributes();
    }
    softClose() {
        const exitAnimation = `hotToastExitSoftAnimation${this.top ? 'Negative' : 'Positive'} ${EXIT_ANIMATION_DURATION}ms forwards cubic-bezier(0.06, 0.71, 0.55, 1)`;
        const nativeElement = this.toastBarBase.nativeElement;
        animate(this.renderer, nativeElement, exitAnimation);
        this.softClosed = true;
        if (this.isExpanded) {
            this.toggleToastGroup();
        }
    }
    softOpen() {
        const softEnterAnimation = `hotToastEnterSoftAnimation${top ? 'Negative' : 'Positive'} ${ENTER_ANIMATION_DURATION}ms cubic-bezier(0.21, 1.02, 0.73, 1) forwards`;
        const nativeElement = this.toastBarBase.nativeElement;
        animate(this.renderer, nativeElement, softEnterAnimation);
        this.softClosed = false;
    }
    close() {
        this.isManualClose = true;
        this.cdr.markForCheck();
        const exitAnimation = `hotToastExitAnimation${this.top ? 'Negative' : 'Positive'} ${EXIT_ANIMATION_DURATION}ms forwards cubic-bezier(0.06, 0.71, 0.55, 1)`;
        this.toastBarBaseStylesSignal.set({ ...this.toast.style, animation: exitAnimation });
    }
    handleMouseEnter() {
        this.showAllToasts.emit(true);
    }
    handleMouseLeave() {
        this.showAllToasts.emit(false);
    }
    ngOnDestroy() {
        this.close();
        while (this.unlisteners.length) {
            this.unlisteners.pop()();
        }
    }
    isExitAnimation(ev) {
        return ev.animationName.includes('hotToastExitAnimation');
    }
    isEnterAnimation(ev) {
        return ev.animationName.includes('hotToastEnterAnimation');
    }
    setToastAttributes() {
        const toastAttributes = this.toast.attributes;
        for (const [key, value] of Object.entries(toastAttributes)) {
            this.renderer.setAttribute(this.toastBarBase.nativeElement, key, value);
        }
    }
    calculateOffset(toastId) {
        const visibleToasts = this.visibleToasts;
        const index = visibleToasts.findIndex((toast) => toast.id === toastId);
        const offset = index !== -1
            ? visibleToasts.slice(...(this.defaultConfig.reverseOrder ? [index + 1] : [0, index])).reduce((acc, t, i) => {
                return this.defaultConfig.visibleToasts !== 0 && i < visibleToasts.length - this.defaultConfig.visibleToasts
                    ? 0
                    : acc + (t.height || 0);
            }, 0)
            : 0;
        return offset;
    }
    updateHeight(height, toast) {
        toast.height = height;
        this.cdr.markForCheck();
    }
    beforeClosedGroupItem(toast) {
        toast.visible = false;
        this.cdr.markForCheck();
        if (this.visibleToasts.length === 0 && this.isExpanded) {
            this.toggleToastGroup();
        }
        else {
            this.emiHeightWithGroup(this.isExpanded);
        }
    }
    afterClosedGroupItem(closeToast) {
        const toastIndex = this.groupChildrenToasts.findIndex((t) => t.id === closeToast.id);
        if (toastIndex > -1) {
            this.groupChildrenToastRefs = this.groupChildrenToastRefs.filter((t) => t.getToast().id !== closeToast.id);
            this.cdr.markForCheck();
        }
    }
    toggleToastGroup() {
        const event = this.isExpanded ? 'collapse' : 'expand';
        this.toggleGroup.emit({
            byAction: true,
            event,
            id: this.toast.id,
        });
        this.emiHeightWithGroup(event === 'expand');
    }
    emiHeightWithGroup(isExpanded) {
        if (isExpanded) {
            requestAnimationFrame(() => {
                this.height.emit(this.toastBarBase.nativeElement.offsetHeight + this.groupHeight);
            });
        }
        else {
            requestAnimationFrame(() => {
                this.height.emit(this.toastBarBase.nativeElement.offsetHeight);
            });
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: HotToastComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: HotToastComponent, isStandalone: true, selector: "hot-toast", inputs: { toast: "toast", offset: "offset", defaultConfig: "defaultConfig", toastRef: "toastRef", toastsAfter: "toastsAfter", isShowingAllToasts: "isShowingAllToasts" }, outputs: { height: "height", beforeClosed: "beforeClosed", afterClosed: "afterClosed", showAllToasts: "showAllToasts", toggleGroup: "toggleGroup" }, viewQueries: [{ propertyName: "toastBarBase", first: true, predicate: ["hotToastBarBase"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div\n  class=\"hot-toast-bar-base-container\"\n  [style]=\"containerPositionStyle\"\n  [class]=\"'hot-toast-theme-' + toast.theme\"\n  [style.--hot-toast-scale]=\"scale\"\n  [style.--hot-toast-translate-y]=\"translateY\"\n>\n  <div\n    class=\"hot-toast-bar-base-wrapper\"\n    [class.expanded]=\"isExpanded\"\n    (mouseenter)=\"handleMouseEnter()\"\n    (mouseleave)=\"handleMouseLeave()\"\n  >\n    <div\n      class=\"hot-toast-bar-base\"\n      #hotToastBarBase\n      [style]=\"toastBarBaseStylesSignal()\"\n      [class]=\"toast.className\"\n      [style.--hot-toast-animation-state]=\"isManualClose ? 'running' : 'paused'\"\n      [style.--hot-toast-exit-animation-state]=\"isShowingAllToasts ? 'paused' : 'running'\"\n      [style.--hot-toast-exit-animation-delay]=\"exitAnimationDelay\"\n      [attr.aria-live]=\"toast.ariaLive\"\n      [attr.role]=\"toast.role\"\n    >\n      <div class=\"hot-toast-icon\" aria-hidden=\"true\">\n        @if (toast.icon !== undefined) { @if (isIconString) {\n        <hot-toast-animated-icon [iconTheme]=\"toast.iconTheme\" [icon]=\"toast.icon\"></hot-toast-animated-icon>\n        } @else {\n        <div>\n          <ng-container *dynamicView=\"toast.icon\"></ng-container>\n        </div>\n        } } @else {\n        <hot-toast-indicator [theme]=\"toast.iconTheme\" [type]=\"toast.type\"></hot-toast-indicator>\n        }\n      </div>\n\n      <div class=\"hot-toast-message\">\n        <ng-container *dynamicView=\"toast.message; context: context; injector: toastComponentInjector\"></ng-container>\n      </div>\n\n      @if (toast.group?.expandAndCollapsible && toast.group?.children && visibleToasts.length > 0) {\n      <button\n        (click)=\"toggleToastGroup()\"\n        type=\"button\"\n        class=\"hot-toast-group-btn\"\n        [class.expanded]=\"isExpanded\"\n        [attr.aria-label]=\"isExpanded ? 'Collapse' : 'Expand'\"\n        [style]=\"toast.group.btnStyle\"\n      ></button>\n      } @if (toast.dismissible) {\n      <button\n        (click)=\"close()\"\n        type=\"button\"\n        class=\"hot-toast-close-btn\"\n        aria-label=\"Close\"\n        [style]=\"toast.closeStyle\"\n      ></button>\n      }\n    </div>\n\n    @if (toast.visible) {\n    <div\n      role=\"list\"\n      class=\"hot-toast-bar-base-group\"\n      [class]=\"toast.group?.className\"\n      [style.--hot-toast-group-height]=\"groupHeight + 'px'\"\n    >\n      @for (item of groupChildrenToasts; track item.id) {\n      <hot-toast-group-item\n        [toast]=\"item\"\n        [offset]=\"calculateOffset(item.id)\"\n        [toastRef]=\"toastRef.groupRefs[$index]\"\n        [toastsAfter]=\"(item.autoClose ? groupChildrenToasts.length : visibleToasts.length) - 1 - $index\"\n        [defaultConfig]=\"defaultConfig\"\n        [isShowingAllToasts]=\"isShowingAllToasts\"\n        (height)=\"updateHeight($event, item)\"\n        (beforeClosed)=\"beforeClosedGroupItem(item)\"\n        (afterClosed)=\"afterClosedGroupItem($event)\"\n      ></hot-toast-group-item>\n      }\n    </div>\n    }\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: DynamicViewDirective, selector: "[dynamicView]", inputs: ["dynamicView", "dynamicViewInjector", "dynamicViewContext", "dynamicViewInputs"] }, { kind: "component", type: IndicatorComponent, selector: "hot-toast-indicator", inputs: ["theme", "type"] }, { kind: "component", type: AnimatedIconComponent, selector: "hot-toast-animated-icon", inputs: ["iconTheme", "icon"] }, { kind: "component", type: HotToastGroupItemComponent, selector: "hot-toast-group-item", inputs: ["toast", "offset", "defaultConfig", "toastRef", "toastsAfter", "isShowingAllToasts"], outputs: ["height", "beforeClosed", "afterClosed", "showAllToasts", "toggleGroup"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: HotToastComponent, decorators: [{
            type: Component,
            args: [{ selector: 'hot-toast', changeDetection: ChangeDetectionStrategy.OnPush, imports: [DynamicViewDirective, IndicatorComponent, AnimatedIconComponent, HotToastGroupItemComponent], template: "<div\n  class=\"hot-toast-bar-base-container\"\n  [style]=\"containerPositionStyle\"\n  [class]=\"'hot-toast-theme-' + toast.theme\"\n  [style.--hot-toast-scale]=\"scale\"\n  [style.--hot-toast-translate-y]=\"translateY\"\n>\n  <div\n    class=\"hot-toast-bar-base-wrapper\"\n    [class.expanded]=\"isExpanded\"\n    (mouseenter)=\"handleMouseEnter()\"\n    (mouseleave)=\"handleMouseLeave()\"\n  >\n    <div\n      class=\"hot-toast-bar-base\"\n      #hotToastBarBase\n      [style]=\"toastBarBaseStylesSignal()\"\n      [class]=\"toast.className\"\n      [style.--hot-toast-animation-state]=\"isManualClose ? 'running' : 'paused'\"\n      [style.--hot-toast-exit-animation-state]=\"isShowingAllToasts ? 'paused' : 'running'\"\n      [style.--hot-toast-exit-animation-delay]=\"exitAnimationDelay\"\n      [attr.aria-live]=\"toast.ariaLive\"\n      [attr.role]=\"toast.role\"\n    >\n      <div class=\"hot-toast-icon\" aria-hidden=\"true\">\n        @if (toast.icon !== undefined) { @if (isIconString) {\n        <hot-toast-animated-icon [iconTheme]=\"toast.iconTheme\" [icon]=\"toast.icon\"></hot-toast-animated-icon>\n        } @else {\n        <div>\n          <ng-container *dynamicView=\"toast.icon\"></ng-container>\n        </div>\n        } } @else {\n        <hot-toast-indicator [theme]=\"toast.iconTheme\" [type]=\"toast.type\"></hot-toast-indicator>\n        }\n      </div>\n\n      <div class=\"hot-toast-message\">\n        <ng-container *dynamicView=\"toast.message; context: context; injector: toastComponentInjector\"></ng-container>\n      </div>\n\n      @if (toast.group?.expandAndCollapsible && toast.group?.children && visibleToasts.length > 0) {\n      <button\n        (click)=\"toggleToastGroup()\"\n        type=\"button\"\n        class=\"hot-toast-group-btn\"\n        [class.expanded]=\"isExpanded\"\n        [attr.aria-label]=\"isExpanded ? 'Collapse' : 'Expand'\"\n        [style]=\"toast.group.btnStyle\"\n      ></button>\n      } @if (toast.dismissible) {\n      <button\n        (click)=\"close()\"\n        type=\"button\"\n        class=\"hot-toast-close-btn\"\n        aria-label=\"Close\"\n        [style]=\"toast.closeStyle\"\n      ></button>\n      }\n    </div>\n\n    @if (toast.visible) {\n    <div\n      role=\"list\"\n      class=\"hot-toast-bar-base-group\"\n      [class]=\"toast.group?.className\"\n      [style.--hot-toast-group-height]=\"groupHeight + 'px'\"\n    >\n      @for (item of groupChildrenToasts; track item.id) {\n      <hot-toast-group-item\n        [toast]=\"item\"\n        [offset]=\"calculateOffset(item.id)\"\n        [toastRef]=\"toastRef.groupRefs[$index]\"\n        [toastsAfter]=\"(item.autoClose ? groupChildrenToasts.length : visibleToasts.length) - 1 - $index\"\n        [defaultConfig]=\"defaultConfig\"\n        [isShowingAllToasts]=\"isShowingAllToasts\"\n        (height)=\"updateHeight($event, item)\"\n        (beforeClosed)=\"beforeClosedGroupItem(item)\"\n        (afterClosed)=\"afterClosedGroupItem($event)\"\n      ></hot-toast-group-item>\n      }\n    </div>\n    }\n  </div>\n</div>\n" }]
        }], propDecorators: { toast: [{
                type: Input
            }], offset: [{
                type: Input
            }], defaultConfig: [{
                type: Input
            }], toastRef: [{
                type: Input
            }], toastsAfter: [{
                type: Input
            }], isShowingAllToasts: [{
                type: Input
            }], height: [{
                type: Output
            }], beforeClosed: [{
                type: Output
            }], afterClosed: [{
                type: Output
            }], showAllToasts: [{
                type: Output
            }], toggleGroup: [{
                type: Output
            }], toastBarBase: [{
                type: ViewChild,
                args: ['hotToastBarBase', { static: true }]
            }] } });

class HotToastContainerComponent {
    constructor() {
        this.toasts = [];
        this.toastRefs = [];
        this.isShowingAllToasts = false;
        /** Subject for notifying the user that the toast has been closed. */
        this._onClosed = new Subject();
        /** Subject for notifying the user that the toast has been expanded or collapsed. */
        this._onGroupToggle = new Subject();
        /** Subject for notifying the user that the group refs have been attached to toast. */
        this._onGroupRefAttached = new Subject();
        this.onClosed$ = this._onClosed.asObservable();
        this.onGroupToggle$ = this._onGroupToggle.asObservable();
        this.onGroupRefAttached$ = this._onGroupRefAttached.asObservable();
        this.cdr = inject(ChangeDetectorRef);
        this.toastService = inject(HotToastService);
    }
    trackById(index, toast) {
        return toast.id;
    }
    getVisibleToasts(position) {
        return this.unGroupedToasts.filter((t) => t.visible && t.position === position);
    }
    get unGroupedToasts() {
        return this.toasts.filter((t) => t.group?.parent === undefined || t.group?.children === undefined || t.group?.children.length === 0);
    }
    calculateOffset(toastId, position) {
        const visibleToasts = this.getVisibleToasts(position);
        const index = visibleToasts.findIndex((toast) => toast.id === toastId);
        const offset = index !== -1
            ? visibleToasts.slice(...(this.defaultConfig.reverseOrder ? [index + 1] : [0, index])).reduce((acc, t, i) => {
                const toastsAfter = visibleToasts.length - 1 - i;
                return this.defaultConfig.visibleToasts !== 0 && i < visibleToasts.length - this.defaultConfig.visibleToasts
                    ? 0
                    : acc +
                        (this.defaultConfig.stacking === 'vertical' || this.isShowingAllToasts
                            ? t.height || 0
                            : toastsAfter * HOT_TOAST_DEPTH_SCALE + HOT_TOAST_DEPTH_SCALE_ADD) +
                        HOT_TOAST_MARGIN;
            }, 0)
            : 0;
        return offset;
    }
    updateHeight(height, toast) {
        toast.height = height;
        this.cdr.markForCheck();
    }
    addToast(ref, skipAttachToParent) {
        this.toastRefs.push(ref);
        const toast = ref.getToast();
        this.toasts.push(ref.getToast());
        if (this.defaultConfig.visibleToasts !== 0 && this.unGroupedToasts.length > this.defaultConfig.visibleToasts) {
            const closeToasts = this.toasts.slice(0, this.toasts.length - this.defaultConfig.visibleToasts);
            closeToasts.forEach((t) => {
                if (t.autoClose) {
                    this.closeToast(t.id);
                }
            });
        }
        this.cdr.markForCheck();
        this.attachGroupRefs(toast, ref, skipAttachToParent);
        return {
            dispose: () => {
                this.closeToast(toast.id);
            },
            updateMessage: (message) => {
                toast.message = message;
                this.updateToasts(toast);
                this.cdr.markForCheck();
            },
            updateToast: (options) => {
                this.updateToasts(toast, options);
                this.cdr.markForCheck();
            },
            afterClosed: this.getAfterClosed(toast),
            afterGroupToggled: this.getAfterGroupToggled(toast),
            afterGroupRefsAttached: this.getAfterGroupRefsAttached(toast).pipe(map((v) => v.groupRefs)),
        };
    }
    async attachGroupRefs(toast, ref, skipAttachToParent) {
        let groupRefs = [];
        if (toast.group) {
            if (toast.group.children) {
                groupRefs = await this.createGroupRefs(toast, ref);
                const toastIndex = this.toastRefs.findIndex((t) => t.getToast().id === toast.id);
                if (toastIndex > -1) {
                    this.toastRefs[toastIndex].groupRefs = groupRefs;
                    this.cdr.markForCheck();
                    this._onGroupRefAttached.next({ groupRefs, id: toast.id });
                }
            }
            else if (toast.group.parent && !skipAttachToParent) {
                const parentToastRef = toast.group.parent;
                const parentToast = parentToastRef.getToast();
                const parentToastRefIndex = this.toastRefs.findIndex((t) => t.getToast().id === parentToast.id);
                const parentToastIndex = this.toasts.findIndex((t) => t.id === parentToast.id);
                if (parentToastRefIndex > -1 && parentToastIndex > -1) {
                    this.toastRefs[parentToastRefIndex].groupRefs.push(ref);
                    const existingGroup = this.toasts[parentToastRefIndex].group ?? {};
                    const existingChildren = this.toasts[parentToastRefIndex].group?.children ?? [];
                    existingChildren.push({ options: { ...toast, type: toast.type, message: toast.message } });
                    existingGroup.children = existingChildren;
                    this.toasts[parentToastRefIndex].group = { ...existingGroup };
                    this.cdr.markForCheck();
                    this._onGroupRefAttached.next({ groupRefs, id: parentToast.id });
                }
            }
        }
    }
    createGroupRefs(toast, ref) {
        const skipAttachToParent = true;
        return new Promise((resolve) => {
            const items = toast.group.children;
            const allPromises = items.map((item) => {
                return new Promise((innerResolve) => {
                    item.options.group = { parent: ref };
                    // We need to give a tick's delay so that IDs are generated properly
                    setTimeout(() => {
                        try {
                            const itemRef = this.toastService.show(item.options.message, item.options, skipAttachToParent);
                            innerResolve(itemRef);
                        }
                        catch (error) {
                            console.error('Error creating toast', error);
                            innerResolve(null);
                        }
                    });
                });
            });
            Promise.all(allPromises).then((refs) => resolve(refs));
        });
    }
    closeToast(id) {
        if (id) {
            const comp = this.hotToastComponentList.find((item) => item.toast.id === id);
            if (comp) {
                comp.close();
                this.cdr.markForCheck();
            }
        }
        else {
            this.hotToastComponentList.forEach((comp) => comp.close());
            this.cdr.markForCheck();
        }
    }
    beforeClosed(toast) {
        toast.visible = false;
        this.cdr.markForCheck();
    }
    afterClosed(closeToast) {
        const toastIndex = this.toasts.findIndex((t) => t.id === closeToast.id);
        if (toastIndex > -1) {
            this._onClosed.next(closeToast);
            this.toasts = this.toasts.filter((t) => t.id !== closeToast.id);
            this.toastRefs = this.toastRefs.filter((t) => t.getToast().id !== closeToast.id);
            this.cdr.markForCheck();
        }
    }
    toggleGroup(groupEvent) {
        const toastIndex = this.toastRefs.findIndex((t) => t.getToast().id === groupEvent.id);
        if (toastIndex > -1) {
            this._onGroupToggle.next(groupEvent);
            this.toastRefs[toastIndex].groupExpanded = groupEvent.event === 'expand';
            this.cdr.markForCheck();
        }
    }
    hasToast(id) {
        return this.toasts.findIndex((t) => t.id === id) > -1;
    }
    showAllToasts(show) {
        this.isShowingAllToasts = show;
    }
    getAfterClosed(toast) {
        return this.onClosed$.pipe(filter((v) => v.id === toast.id));
    }
    getAfterGroupToggled(toast) {
        return this.onGroupToggle$.pipe(filter((v) => v.id === toast.id));
    }
    getAfterGroupRefsAttached(toast) {
        return this.onGroupRefAttached$.pipe(filter((v) => v.id === toast.id));
    }
    updateToasts(toast, options) {
        this.toasts = this.toasts.map((t) => ({ ...t, ...(t.id === toast.id && { ...toast, ...options }) }));
        this.cdr.markForCheck();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: HotToastContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: HotToastContainerComponent, isStandalone: true, selector: "hot-toast-container", inputs: { defaultConfig: "defaultConfig" }, viewQueries: [{ propertyName: "hotToastComponentList", predicate: HotToastComponent, descendants: true }], ngImport: i0, template: "<div [ngStyle]=\"{position: 'fixed', zIndex: 9999, top: 0, right: 0, bottom: 0, left: 0, pointerEvents: 'none'}\">\n  <div [ngStyle]=\"{position: 'relative', height: '100%'}\">\n    <div>\n      @for (toast of toasts; track trackById(i, toast); let i = $index) { @if (toast.group?.parent) {} @else {\n      <hot-toast\n        [toast]=\"toast\"\n        [offset]=\"calculateOffset(toast.id, toast.position)\"\n        [toastRef]=\"toastRefs[i]\"\n        [toastsAfter]=\"(toast.autoClose ? toasts.length : getVisibleToasts(toast.position).length) - 1 - i\"\n        [defaultConfig]=\"defaultConfig\"\n        [isShowingAllToasts]=\"isShowingAllToasts\"\n        (showAllToasts)=\"showAllToasts($event)\"\n        (height)=\"updateHeight($event, toast)\"\n        (beforeClosed)=\"beforeClosed(toast)\"\n        (afterClosed)=\"afterClosed($event)\"\n        (toggleGroup)=\"toggleGroup($event)\"\n      ></hot-toast>\n      } }\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "component", type: HotToastComponent, selector: "hot-toast", inputs: ["toast", "offset", "defaultConfig", "toastRef", "toastsAfter", "isShowingAllToasts"], outputs: ["height", "beforeClosed", "afterClosed", "showAllToasts", "toggleGroup"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: HotToastContainerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'hot-toast-container', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HotToastComponent, NgStyle], template: "<div [ngStyle]=\"{position: 'fixed', zIndex: 9999, top: 0, right: 0, bottom: 0, left: 0, pointerEvents: 'none'}\">\n  <div [ngStyle]=\"{position: 'relative', height: '100%'}\">\n    <div>\n      @for (toast of toasts; track trackById(i, toast); let i = $index) { @if (toast.group?.parent) {} @else {\n      <hot-toast\n        [toast]=\"toast\"\n        [offset]=\"calculateOffset(toast.id, toast.position)\"\n        [toastRef]=\"toastRefs[i]\"\n        [toastsAfter]=\"(toast.autoClose ? toasts.length : getVisibleToasts(toast.position).length) - 1 - i\"\n        [defaultConfig]=\"defaultConfig\"\n        [isShowingAllToasts]=\"isShowingAllToasts\"\n        (showAllToasts)=\"showAllToasts($event)\"\n        (height)=\"updateHeight($event, toast)\"\n        (beforeClosed)=\"beforeClosed(toast)\"\n        (afterClosed)=\"afterClosed($event)\"\n        (toggleGroup)=\"toggleGroup($event)\"\n      ></hot-toast>\n      } }\n    </div>\n  </div>\n</div>\n" }]
        }], propDecorators: { defaultConfig: [{
                type: Input
            }], hotToastComponentList: [{
                type: ViewChildren,
                args: [HotToastComponent]
            }] } });

class ToastConfig {
    constructor() {
        /**
         * Sets the reverse order for hot-toast stacking
         *
         * @default false
         */
        this.reverseOrder = false;
        /**
         * Sets the number of toasts visible.
         * 0 will set no limit.
         * @default 5
         * @since 6.1.0
         */
        this.visibleToasts = 5;
        /**
         * Sets the type of stacking
         * @default "vertical"
         * @since 6.1.0
         */
        this.stacking = 'vertical';
        this.ariaLive = 'polite';
        this.role = 'status';
        this.position = 'top-center';
        this.autoClose = true;
        this.theme = 'toast';
        this.attributes = {};
        // key in ToastType
        this.info = { content: '' };
        this.success = { content: '' };
        this.error = { content: '' };
        this.loading = { content: '' };
        this.blank = { content: '' };
        this.warning = { content: '' };
    }
}
const isFunction = (valOrFunction) => typeof valOrFunction === 'function';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isAngularComponent = (arg) => {
    // `ɵcmp` is a component definition set by the Angular compiler.
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    return typeof arg === 'function' && !!arg.ɵcmp;
};
const resolveValueOrFunction = (valOrFunction, arg) => isAngularComponent(valOrFunction)
    ? valOrFunction
    : isFunction(valOrFunction)
        ? valOrFunction(arg)
        : valOrFunction;
class ToastPersistConfig {
    constructor() {
        /**
         *In which storage id vs. counts should be stored
         *
         * @type {('local' | 'session')}
         * @memberof ToastPersistConfig
         * @default 'local'
         */
        this.storage = 'local';
        /**
         *The key pattern to store object in storage. `${id}` in pattern is replaced with actual toast id.
         *
         * @type {('local' | 'session')}
         * @memberof ToastPersistConfig
         * @default 'ngxpert/hottoast-${id}'
         */
        this.key = 'ngxpert/hototast-${id}';
        /**
         *The number of toasts allowed to show.
         *
         * @memberof ToastPersistConfig
         * @default 1
         */
        this.count = 1;
        this.enabled = false;
    }
}

class HotToastService {
    static { this.nextId = 0; }
    constructor() {
        this._isInitialized = false;
        this._defaultGlobalConfig = new ToastConfig();
        this._defaultPersistConfig = new ToastPersistConfig();
        this._viewService = inject(ViewService);
        this._platformId = inject(PLATFORM_ID);
        this._globalConfig = inject(ToastConfig, { optional: true });
        if (this._globalConfig) {
            this._defaultGlobalConfig = {
                ...this._defaultGlobalConfig,
                ...this._globalConfig,
            };
        }
    }
    get defaultConfig() {
        return this._defaultGlobalConfig;
    }
    set defaultConfig(config) {
        this._defaultGlobalConfig = {
            ...this._defaultGlobalConfig,
            ...config,
        };
        if (this._componentRef) {
            this._componentRef.setInput('defaultConfig', this._defaultGlobalConfig);
        }
    }
    /**
     * Opens up an hot-toast without any pre-configurations
     *
     * @param message The message to show in the hot-toast.
     * @param [options] Additional configuration options for the hot-toast.
     * @param skipAttachToParent Only for internal usage. Setting this to true will not attach toast to it's parent.
     * @returns
     * @memberof HotToastService
     */
    show(message, options, skipAttachToParent) {
        const toast = this.createToast({
            message: message || this._defaultGlobalConfig.blank.content,
            type: options?.type ?? 'blank',
            options: {
                ...this._defaultGlobalConfig,
                ...options,
            },
            skipAttachToParent,
        });
        return toast;
    }
    /**
     * Opens up an hot-toast with pre-configurations for error state
     *
     * @param message The message to show in the hot-toast.
     * @param [options] Additional configuration options for the hot-toast.
     * @returns
     * @memberof HotToastService
     */
    error(message, options) {
        const toast = this.createToast({
            message: message || this._defaultGlobalConfig.error.content,
            type: 'error',
            options: {
                ...this._defaultGlobalConfig,
                ...this._defaultGlobalConfig?.error,
                ...options,
            },
        });
        return toast;
    }
    /**
     * Opens up an hot-toast with pre-configurations for success state
     *
     * @param message The message to show in the hot-toast.
     * @param [options] Additional configuration options for the hot-toast.
     * @returns
     * @memberof HotToastService
     */
    success(message, options) {
        const toast = this.createToast({
            message: message || this._defaultGlobalConfig.success.content,
            type: 'success',
            options: {
                ...this._defaultGlobalConfig,
                ...this._defaultGlobalConfig?.success,
                ...options,
            },
        });
        return toast;
    }
    /**
     * Opens up an hot-toast with pre-configurations for loading state
     *
     * @param message The message to show in the hot-toast.
     * @param [options] Additional configuration options for the hot-toast.
     * @returns
     * @memberof HotToastService
     */
    loading(message, options) {
        const toast = this.createToast({
            message: message || this._defaultGlobalConfig.loading.content,
            type: 'loading',
            options: {
                ...this._defaultGlobalConfig,
                ...this._defaultGlobalConfig?.loading,
                ...options,
            },
        });
        return toast;
    }
    /**
     * Opens up an hot-toast with pre-configurations for warning state
     *
     * @param message The message to show in the hot-toast.
     * @param [options] Additional configuration options for the hot-toast.
     * @returns
     * @memberof HotToastService
     */
    warning(message, options) {
        const toast = this.createToast({
            message: message || this._defaultGlobalConfig.warning.content,
            type: 'warning',
            options: {
                ...this._defaultGlobalConfig,
                ...this._defaultGlobalConfig?.warning,
                ...options,
            },
        });
        return toast;
    }
    /**
     * Opens up an hot-toast with pre-configurations for info state
     *
     * @param message The message to show in the hot-toast.
     * @param [options] Additional configuration options for the hot-toast.
     * @returns
     * @memberof HotToastService
     * @since 3.3.0
     */
    info(message, options) {
        const toast = this.createToast({
            message: message || this._defaultGlobalConfig.info.content,
            type: 'info',
            options: {
                ...this._defaultGlobalConfig,
                ...this._defaultGlobalConfig?.info,
                ...options,
            },
        });
        return toast;
    }
    /**
     *
     *  Opens up an hot-toast with pre-configurations for loading initially and then changes state based on messages
     *
     * @template T Type of observable
     * @param messages Messages for each state i.e. loading, success and error
     * @returns
     * @memberof HotToastService
     */
    observe(messages) {
        return (source) => {
            let toastRef;
            let start = 0;
            const loadingContent = messages.loading ?? this._defaultGlobalConfig.loading?.content;
            const successContent = messages.success ?? this._defaultGlobalConfig.success?.content;
            const errorContent = messages.error ?? this._defaultGlobalConfig.error?.content;
            return defer(() => {
                if (loadingContent) {
                    toastRef = this.createLoadingToast(loadingContent);
                    start = Date.now();
                }
                return source.pipe(tap({
                    ...(successContent && {
                        next: (val) => {
                            toastRef = this.createOrUpdateToast(messages, val, toastRef, 'success', start === 0 ? start : Date.now() - start);
                        },
                    }),
                    ...(errorContent && {
                        error: (e) => {
                            toastRef = this.createOrUpdateToast(messages, e, toastRef, 'error', start === 0 ? start : Date.now() - start);
                        },
                    }),
                }));
            });
        };
    }
    /**
     * Closes the hot-toast
     *
     * @param [id] - ID of the toast
     * @since 3.0.1 - If ID is not provided, all toasts will be closed
     */
    close(id) {
        if (this._componentRef) {
            this._componentRef.ref.instance.closeToast(id);
        }
    }
    /**
     * Used for internal purpose only.
     * Creates a container component and attaches it to document.body.
     */
    init() {
        if (isPlatformServer(this._platformId)) {
            return;
        }
        this._componentRef = this._viewService
            .createComponent(HotToastContainerComponent)
            .setInput('defaultConfig', this._defaultGlobalConfig)
            .appendTo(document.body);
    }
    createOrUpdateToast(messages, val, toastRef, type, diff) {
        try {
            let content = null;
            let options = {};
            ({ content, options } = this.getContentAndOptions(type, messages[type] || (this._defaultGlobalConfig[type] ? this._defaultGlobalConfig[type].content : '')));
            content = resolveValueOrFunction(content, val);
            if (toastRef) {
                if (options.data) {
                    toastRef.data = options.data;
                }
                toastRef.updateMessage(content);
                const updatedOptions = {
                    type,
                    duration: diff + HOT_TOAST_DEFAULT_TIMEOUTS[type],
                    ...options,
                    ...(options.duration && { duration: diff + options.duration }),
                };
                toastRef.updateToast(updatedOptions);
            }
            else {
                this.createToast({ message: content, type, options });
            }
            return toastRef;
        }
        catch (error) {
            console.error(error);
        }
    }
    createToast({ message, type, options, observableMessages, skipAttachToParent, }) {
        if (!this._isInitialized) {
            this._isInitialized = true;
            this.init();
        }
        const id = options?.id ?? `toast-${HotToastService.nextId++}`;
        if (!this.isDuplicate(id) &&
            (!options.persist?.enabled || (options.persist?.enabled && this.handleStorageValue(id, options)))) {
            const toast = {
                ariaLive: options?.ariaLive ?? 'polite',
                createdAt: Date.now(),
                duration: options?.duration ?? HOT_TOAST_DEFAULT_TIMEOUTS[type],
                id,
                message,
                role: options?.role ?? 'status',
                type,
                visible: true,
                observableMessages: observableMessages ?? undefined,
                ...options,
            };
            return new HotToastRef(toast).appendTo(this._componentRef.ref.instance, skipAttachToParent);
        }
    }
    /**
     * Checks whether any toast with same id is present.
     *
     * @private
     * @param id - Toast ID
     */
    isDuplicate(id) {
        return this._componentRef.ref.instance.hasToast(id);
    }
    /**
     * Creates an entry in local or session storage with count ${defaultConfig.persist.count}, if not present.
     * If present in storage, reduces the count
     * and returns the count.
     * Count can not be less than 0.
     */
    handleStorageValue(id, options) {
        let count = 1;
        const persist = { ...this._defaultPersistConfig, ...options.persist };
        const storage = persist.storage === 'local' ? localStorage : sessionStorage;
        const key = persist.key.replace(/\${id}/g, id);
        let item = storage.getItem(key);
        if (item) {
            item = parseInt(item, 10);
            if (item > 0) {
                count = item - 1;
            }
            else {
                count = item;
            }
        }
        else {
            count = persist.count;
        }
        storage.setItem(key, count.toString());
        return count;
    }
    getContentAndOptions(toastType, message) {
        let content;
        let options = {
            ...this._defaultGlobalConfig,
            ...this._defaultGlobalConfig[toastType],
        };
        // typeof message === 'object' won't work, cz TemplateRef's type is object
        if (typeof message === 'string' || isTemplateRef(message) || isComponent(message)) {
            content = message;
        }
        else {
            let restOptions;
            ({ content, ...restOptions } = message);
            options = { ...options, ...restOptions };
        }
        return { content, options };
    }
    createLoadingToast(messages) {
        let content = null;
        let options = {};
        ({ content, options } = this.getContentAndOptions('loading', messages));
        return this.loading(content, options);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: HotToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: HotToastService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: HotToastService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [] });

function provideHotToastConfig(config) {
    return makeEnvironmentProviders([{ provide: ToastConfig, useValue: config }]);
}

class HotToastBuilder {
    constructor(message, service) {
        this.message = message;
        this.service = service;
        this.options = {};
        this.groupChildren = [];
    }
    setOptions(options) {
        this.options = { ...this.options, ...options };
        return this;
    }
    addChild(child) {
        this.groupChildren.push(child);
        return this;
    }
    get afterGroupRefsAttached() {
        return this.toastRef?.afterGroupRefsAttached;
    }
    addChildrenToOptions() {
        if (this.groupChildren.length > 0) {
            const children = this.groupChildren.map((child) => ({
                options: {
                    message: child.message,
                    ...child.options,
                },
            }));
            this.options.group = {
                ...this.options.group,
                children,
            };
        }
    }
    // Create method that creates but doesn't show the toast. Call show() to show the toast.
    create(method = 'show') {
        this.addChildrenToOptions();
        this.toastRef = this.service[method](this.message, {
            ...this.options,
            ...{ visible: false },
        });
        return this.toastRef;
    }
    createToast(method) {
        this.addChildrenToOptions();
        this.toastRef = this.service[method](this.message, this.options);
        return this.toastRef;
    }
    show() {
        return this.createToast('show');
    }
    success() {
        return this.createToast('success');
    }
    error() {
        return this.createToast('error');
    }
    warning() {
        return this.createToast('warning');
    }
    info() {
        return this.createToast('info');
    }
    loading() {
        return this.createToast('loading');
    }
}

/*
 * Public API Surface of hot-toast
 */

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

export { HotToastBuilder, HotToastRef, HotToastService, ToastConfig, ToastPersistConfig, provideHotToastConfig, resolveValueOrFunction };
//# sourceMappingURL=ngxpert-hot-toast.mjs.map