UNPKG

ngx-ntk-smart-module

Version:

Ntk Cms Modal

1,465 lines 57.3 kB
import * as i1 from '@angular/common';
import { isPlatformBrowser, DOCUMENT, CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { EventEmitter, PLATFORM_ID, ViewContainerRef, HostListener, ViewChildren, Output, Input, Inject, Component, Injectable, Type, TemplateRef, NgModule } from '@angular/core';

const NtkSmartModalConfig = {
    bodyClassOpen: 'dialog-open',
    prefixEvent: 'ntk-smart-modal.'
};

class NtkSmartModalComponent {
    constructor(_renderer, _changeDetectorRef, componentFactoryResolver, _document, _platformId) {
        this._renderer = _renderer;
        this._changeDetectorRef = _changeDetectorRef;
        this.componentFactoryResolver = componentFactoryResolver;
        this._document = _document;
        this._platformId = _platformId;
        this.closable = true;
        this.escapable = true;
        this.dismissable = true;
        this.identifier = '';
        this.customClass = 'nsm-dialog-animation-fade';
        this.visible = false;
        this.backdrop = true;
        this.force = true;
        this.hideDelay = 500;
        this.autostart = false;
        this.target = '';
        this.ariaLabel = null;
        this.ariaLabelledBy = null;
        this.ariaDescribedBy = null;
        this.refocus = true;
        this.visibleChange = new EventEmitter();
        this.onClose = new EventEmitter();
        this.onCloseFinished = new EventEmitter();
        this.onDismiss = new EventEmitter();
        this.onDismissFinished = new EventEmitter();
        this.onAnyCloseEvent = new EventEmitter();
        this.onAnyCloseEventFinished = new EventEmitter();
        this.onOpen = new EventEmitter();
        this.onOpenFinished = new EventEmitter();
        this.onEscape = new EventEmitter();
        this.onDataAdded = new EventEmitter();
        this.onDataRemoved = new EventEmitter();
        this.layerPosition = 1041;
        this.overlayVisible = false;
        this.openedClass = false;
        this.createFrom = 'html';
    }
    ngOnInit() {
        if (!this.identifier || !this.identifier.length) {
            throw new Error('identifier field isn’t set. Please set one before calling <ngx-smart-modal> in a template.');
        }
        this._sendEvent('create');
    }
    ngAfterViewInit() {
        if (this.contentComponent) {
            const factory = this.componentFactoryResolver.resolveComponentFactory(this.contentComponent);
            this.createDynamicContent(this.dynamicContentContainer, factory);
            this.dynamicContentContainer.changes.subscribe((contentViewContainers) => {
                this.createDynamicContent(contentViewContainers, factory);
            });
        }
    }
    ngOnDestroy() {
        this._sendEvent('delete');
    }
    /**
     * Open the modal instance
     *
     * @param top open the modal top of all other
     * @returns the modal component
     */
    open(top) {
        this._sendEvent('open', { top: top });
        return this;
    }
    /**
     * Close the modal instance
     *
     * @returns the modal component
     */
    close() {
        this._sendEvent('close');
        return this;
    }
    /**
     * Dismiss the modal instance
     *
     * @param e the event sent by the browser
     * @returns the modal component
     */
    dismiss(e) {
        if (!this.dismissable || !e.target.classList.contains('overlay')) {
            return this;
        }
        this._sendEvent('dismiss');
        return this;
    }
    /**
     * Toggle visibility of the modal instance
     *
     * @param top open the modal top of all other
     * @returns the modal component
     */
    toggle(top) {
        this._sendEvent('toggle', { top: top });
        return this;
    }
    /**
     * Add a custom class to the modal instance
     *
     * @param className the class to add
     * @returns the modal component
     */
    addCustomClass(className) {
        if (!this.customClass.length) {
            this.customClass = className;
        }
        else {
            this.customClass += ' ' + className;
        }
        return this;
    }
    /**
     * Remove a custom class to the modal instance
     *
     * @param className the class to remove
     * @returns the modal component
     */
    removeCustomClass(className) {
        if (className) {
            this.customClass = this.customClass.replace(className, '').trim();
        }
        else {
            this.customClass = '';
        }
        return this;
    }
    /**
     * Returns the visibility state of the modal instance
     */
    isVisible() {
        return this.visible;
    }
    /**
     * Checks if data is attached to the modal instance
     */
    hasData() {
        return this._data !== undefined;
    }
    /**
     * Attach data to the modal instance
     *
     * @param data the data to attach
     * @param force override potentially attached data
     * @returns the modal component
     */
    setData(data, force) {
        if (!this.hasData() || (this.hasData() && force)) {
            this._data = data;
            this.onDataAdded.emit(this._data);
            this.markForCheck();
        }
        return this;
    }
    /**
     * Retrieve the data attached to the modal instance
     */
    getData() {
        return this._data;
    }
    /**
     * Remove the data attached to the modal instance
     *
     * @returns the modal component
     */
    removeData() {
        this._data = undefined;
        this.onDataRemoved.emit(true);
        this.markForCheck();
        return this;
    }
    /**
     * Add body class modal opened
     *
     * @returns the modal component
     */
    addBodyClass() {
        this._renderer.addClass(this._document.body, NtkSmartModalConfig.bodyClassOpen);
        return this;
    }
    /**
     * Add body class modal opened
     *
     * @returns the modal component
     */
    removeBodyClass() {
        this._renderer.removeClass(this._document.body, NtkSmartModalConfig.bodyClassOpen);
        return this;
    }
    markForCheck() {
        try {
            this._changeDetectorRef.detectChanges();
        }
        catch (e) {
        }
        this._changeDetectorRef.markForCheck();
    }
    /**
     * Listens for window resize event and recalculates modal instance position if it is element-relative
     */
    targetPlacement() {
        if (!this.isBrowser || !this.nsmDialog.length || !this.nsmContent.length || !this.nsmOverlay.length || !this.target) {
            return false;
        }
        const targetElement = this._document.querySelector(this.target);
        if (!targetElement) {
            return false;
        }
        const targetElementRect = targetElement.getBoundingClientRect();
        const bodyRect = this.nsmOverlay.first.nativeElement.getBoundingClientRect();
        const nsmContentRect = this.nsmContent.first.nativeElement.getBoundingClientRect();
        const nsmDialogRect = this.nsmDialog.first.nativeElement.getBoundingClientRect();
        const marginLeft = parseInt(getComputedStyle(this.nsmContent.first.nativeElement).marginLeft, 10);
        const marginTop = parseInt(getComputedStyle(this.nsmContent.first.nativeElement).marginTop, 10);
        let offsetTop = targetElementRect.top - nsmDialogRect.top - ((nsmContentRect.height - targetElementRect.height) / 2);
        let offsetLeft = targetElementRect.left - nsmDialogRect.left - ((nsmContentRect.width - targetElementRect.width) / 2);
        if (offsetLeft + nsmDialogRect.left + nsmContentRect.width + (marginLeft * 2) > bodyRect.width) {
            offsetLeft = bodyRect.width - (nsmDialogRect.left + nsmContentRect.width) - (marginLeft * 2);
        }
        else if (offsetLeft + nsmDialogRect.left < 0) {
            offsetLeft = -nsmDialogRect.left;
        }
        if (offsetTop + nsmDialogRect.top + nsmContentRect.height + marginTop > bodyRect.height) {
            offsetTop = bodyRect.height - (nsmDialogRect.top + nsmContentRect.height) - marginTop;
        }
        this._renderer.setStyle(this.nsmContent.first.nativeElement, 'top', (offsetTop < 0 ? 0 : offsetTop) + 'px');
        this._renderer.setStyle(this.nsmContent.first.nativeElement, 'left', offsetLeft + 'px');
    }
    _sendEvent(name, extraData) {
        if (!this.isBrowser) {
            return false;
        }
        const data = {
            extraData: extraData,
            instance: { id: this.identifier, modal: this }
        };
        const event = new CustomEvent(NtkSmartModalConfig.prefixEvent + name, { detail: data });
        return window.dispatchEvent(event);
    }
    /**
     * Is current platform browser
     */
    get isBrowser() {
        return isPlatformBrowser(this._platformId);
    }
    /**
     * Creates content inside provided ViewContainerRef
     */
    createDynamicContent(changes, factory) {
        changes.forEach((viewContainerRef) => {
            viewContainerRef.clear();
            viewContainerRef.createComponent(factory);
            this.markForCheck();
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i0.ComponentFactoryResolver }, { token: DOCUMENT }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: NtkSmartModalComponent, isStandalone: false, selector: "ntk-smart-modal", inputs: { closable: "closable", escapable: "escapable", dismissable: "dismissable", identifier: "identifier", customClass: "customClass", visible: "visible", backdrop: "backdrop", force: "force", hideDelay: "hideDelay", autostart: "autostart", target: "target", ariaLabel: "ariaLabel", ariaLabelledBy: "ariaLabelledBy", ariaDescribedBy: "ariaDescribedBy", refocus: "refocus" }, outputs: { visibleChange: "visibleChange", onClose: "onClose", onCloseFinished: "onCloseFinished", onDismiss: "onDismiss", onDismissFinished: "onDismissFinished", onAnyCloseEvent: "onAnyCloseEvent", onAnyCloseEventFinished: "onAnyCloseEventFinished", onOpen: "onOpen", onOpenFinished: "onOpenFinished", onEscape: "onEscape", onDataAdded: "onDataAdded", onDataRemoved: "onDataRemoved" }, host: { listeners: { "window:resize": "targetPlacement()" } }, viewQueries: [{ propertyName: "nsmContent", predicate: ["nsmContent"], descendants: true }, { propertyName: "nsmDialog", predicate: ["nsmDialog"], descendants: true }, { propertyName: "nsmOverlay", predicate: ["nsmOverlay"], descendants: true }, { propertyName: "dynamicContentContainer", predicate: ["dynamicContent"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: `
    <div *ngIf="overlayVisible"
         [style.z-index]="visible ? layerPosition-1 : -1"
         [ngClass]="{'transparent':!backdrop, 'overlay':true, 'nsm-overlay-open':openedClass}"
         (click)="dismiss($event)" #nsmOverlay>
      <div [style.z-index]="visible ? layerPosition : -1"
           [ngClass]="['nsm-dialog', customClass, openedClass ? 'nsm-dialog-open': 'nsm-dialog-close']" #nsmDialog
           [attr.aria-hidden]="openedClass ? false : true"
           [attr.aria-label]="ariaLabel"
           [attr.aria-labelledby]="ariaLabelledBy"
           [attr.aria-describedby]="ariaDescribedBy">
        <div class="nsm-content" #nsmContent>
          <div class="nsm-body">
            <ng-template #dynamicContent></ng-template>
            <ng-content></ng-content>

          </div>
          <button type="button" *ngIf="closable" (click)="close()" aria-label="Close" class="nsm-dialog-btn-close">
            <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 512 512"
                 xml:space="preserve" width="16px" height="16px" role="img" aria-labelledby="closeIconTitle closeIconDesc">
              <title id="closeIconTitle">Close Icon</title>
              <desc id="closeIconDesc">A light-gray close icon used to close the modal</desc>
              <g>
                <path d="M505.943,6.058c-8.077-8.077-21.172-8.077-29.249,0L6.058,476.693c-8.077,8.077-8.077,21.172,0,29.249    C10.096,509.982,15.39,512,20.683,512c5.293,0,10.586-2.019,14.625-6.059L505.943,35.306    C514.019,27.23,514.019,14.135,505.943,6.058z"
                      fill="currentColor"/>
              </g>
              <g>
                <path d="M505.942,476.694L35.306,6.059c-8.076-8.077-21.172-8.077-29.248,0c-8.077,8.076-8.077,21.171,0,29.248l470.636,470.636    c4.038,4.039,9.332,6.058,14.625,6.058c5.293,0,10.587-2.019,14.624-6.057C514.018,497.866,514.018,484.771,505.942,476.694z"
                      fill="currentColor"/>
              </g>
            </svg>
          </button>
        </div>
      </div>
    </div>
  `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'ntk-smart-modal',
                    standalone: false,
                    template: `
    <div *ngIf="overlayVisible"
         [style.z-index]="visible ? layerPosition-1 : -1"
         [ngClass]="{'transparent':!backdrop, 'overlay':true, 'nsm-overlay-open':openedClass}"
         (click)="dismiss($event)" #nsmOverlay>
      <div [style.z-index]="visible ? layerPosition : -1"
           [ngClass]="['nsm-dialog', customClass, openedClass ? 'nsm-dialog-open': 'nsm-dialog-close']" #nsmDialog
           [attr.aria-hidden]="openedClass ? false : true"
           [attr.aria-label]="ariaLabel"
           [attr.aria-labelledby]="ariaLabelledBy"
           [attr.aria-describedby]="ariaDescribedBy">
        <div class="nsm-content" #nsmContent>
          <div class="nsm-body">
            <ng-template #dynamicContent></ng-template>
            <ng-content></ng-content>

          </div>
          <button type="button" *ngIf="closable" (click)="close()" aria-label="Close" class="nsm-dialog-btn-close">
            <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 512 512"
                 xml:space="preserve" width="16px" height="16px" role="img" aria-labelledby="closeIconTitle closeIconDesc">
              <title id="closeIconTitle">Close Icon</title>
              <desc id="closeIconDesc">A light-gray close icon used to close the modal</desc>
              <g>
                <path d="M505.943,6.058c-8.077-8.077-21.172-8.077-29.249,0L6.058,476.693c-8.077,8.077-8.077,21.172,0,29.249    C10.096,509.982,15.39,512,20.683,512c5.293,0,10.586-2.019,14.625-6.059L505.943,35.306    C514.019,27.23,514.019,14.135,505.943,6.058z"
                      fill="currentColor"/>
              </g>
              <g>
                <path d="M505.942,476.694L35.306,6.059c-8.076-8.077-21.172-8.077-29.248,0c-8.077,8.076-8.077,21.171,0,29.248l470.636,470.636    c4.038,4.039,9.332,6.058,14.625,6.058c5.293,0,10.587-2.019,14.624-6.057C514.018,497.866,514.018,484.771,505.942,476.694z"
                      fill="currentColor"/>
              </g>
            </svg>
          </button>
        </div>
      </div>
    </div>
  `
                }]
        }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i0.ComponentFactoryResolver }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [DOCUMENT]
                }] }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [PLATFORM_ID]
                }] }], propDecorators: { closable: [{
                type: Input
            }], escapable: [{
                type: Input
            }], dismissable: [{
                type: Input
            }], identifier: [{
                type: Input
            }], customClass: [{
                type: Input
            }], visible: [{
                type: Input
            }], backdrop: [{
                type: Input
            }], force: [{
                type: Input
            }], hideDelay: [{
                type: Input
            }], autostart: [{
                type: Input
            }], target: [{
                type: Input
            }], ariaLabel: [{
                type: Input
            }], ariaLabelledBy: [{
                type: Input
            }], ariaDescribedBy: [{
                type: Input
            }], refocus: [{
                type: Input
            }], visibleChange: [{
                type: Output
            }], onClose: [{
                type: Output
            }], onCloseFinished: [{
                type: Output
            }], onDismiss: [{
                type: Output
            }], onDismissFinished: [{
                type: Output
            }], onAnyCloseEvent: [{
                type: Output
            }], onAnyCloseEventFinished: [{
                type: Output
            }], onOpen: [{
                type: Output
            }], onOpenFinished: [{
                type: Output
            }], onEscape: [{
                type: Output
            }], onDataAdded: [{
                type: Output
            }], onDataRemoved: [{
                type: Output
            }], nsmContent: [{
                type: ViewChildren,
                args: ['nsmContent']
            }], nsmDialog: [{
                type: ViewChildren,
                args: ['nsmDialog']
            }], nsmOverlay: [{
                type: ViewChildren,
                args: ['nsmOverlay']
            }], dynamicContentContainer: [{
                type: ViewChildren,
                args: ['dynamicContent', { read: ViewContainerRef }]
            }], targetPlacement: [{
                type: HostListener,
                args: ['window:resize']
            }] } });

class NtkSmartModalStackService {
    constructor() {
        this.modalStack = [];
    }
    /**
     * Add a new modal instance. This step is essential and allows to retrieve any modal at any time.
     * It stores an object that contains the given modal identifier and the modal itself directly in the `modalStack`.
     *
     * @param modalInstance The object that contains the given modal identifier and the modal itself.
     * @param force Optional parameter that forces the overriding of modal instance if it already exists.
     * @returns nothing special.
     */
    addModal(modalInstance, force) {
        if (force) {
            const i = this.modalStack.findIndex((o) => o.id === modalInstance.id);
            if (i > -1) {
                this.modalStack[i].modal = modalInstance.modal;
            }
            else {
                this.modalStack.push(modalInstance);
            }
            return;
        }
        this.modalStack.push(modalInstance);
    }
    /**
     * Retrieve a modal instance by its identifier.
     *
     * @param id The modal identifier used at creation time.
     */
    getModal(id) {
        const i = this.modalStack.find((o) => o.id === id);
        if (i !== undefined) {
            return i.modal;
        }
        else {
            throw new Error(`Cannot find modal with identifier ${id}`);
        }
    }
    /**
     * Retrieve all the created modals.
     *
     * @returns an array that contains all modal instances.
     */
    getModalStack() {
        return this.modalStack;
    }
    /**
     * Retrieve all the opened modals. It looks for all modal instances with their `visible` property set to `true`.
     *
     * @returns an array that contains all the opened modals.
     */
    getOpenedModals() {
        return this.modalStack.filter((o) => o.modal.visible);
    }
    /**
     * Retrieve the opened modal with highest z-index.
     *
     * @returns the opened modal with highest z-index.
     */
    getTopOpenedModal() {
        if (!this.getOpenedModals().length) {
            throw new Error('No modal is opened');
        }
        return this.getOpenedModals()
            .map((o) => o.modal)
            .reduce((highest, item) => item.layerPosition > highest.layerPosition ? item : highest, this.getOpenedModals()[0].modal);
    }
    /**
     * Get the higher `z-index` value between all the modal instances. It iterates over the `ModalStack` array and
     * calculates a higher value (it takes the highest index value between all the modal instances and adds 1).
     * Use it to make a modal appear foreground.
     *
     * @returns a higher index from all the existing modal instances.
     */
    getHigherIndex() {
        return Math.max(...this.modalStack.map((o) => o.modal.layerPosition), 1041) + 1;
    }
    /**
     * It gives the number of modal instances. It's helpful to know if the modal stack is empty or not.
     *
     * @returns the number of modal instances.
     */
    getModalStackCount() {
        return this.modalStack.length;
    }
    /**
     * Remove a modal instance from the modal stack.
     *
     * @param id The modal identifier.
     * @returns the removed modal instance.
     */
    removeModal(id) {
        const i = this.modalStack.findIndex((o) => o.id === id);
        if (i > -1) {
            this.modalStack.splice(i, 1);
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalStackService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalStackService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalStackService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [] });

class NtkSmartModalService {
    constructor(_componentFactoryResolver, _appRef, _injector, _modalStack, applicationRef, _document, _platformId) {
        this._componentFactoryResolver = _componentFactoryResolver;
        this._appRef = _appRef;
        this._injector = _injector;
        this._modalStack = _modalStack;
        this.applicationRef = applicationRef;
        this._document = _document;
        this._platformId = _platformId;
        /**
         * Close the latest opened modal if escape key event is emitted
         * @param event The Keyboard Event
         */
        this._escapeKeyboardEvent = (event) => {
            if (event.key === 'Escape') {
                try {
                    const modal = this.getTopOpenedModal();
                    if (!modal.escapable) {
                        return false;
                    }
                    modal.onEscape.emit(modal);
                    this.closeLatestModal();
                    return true;
                }
                catch (e) {
                    return false;
                }
            }
            return false;
        };
        /**
         * While modal is open, the focus stay on it
         * @param event The Keyboar dEvent
         */
        this._trapFocusModal = (event) => {
            if (event.key === 'Tab') {
                try {
                    const modal = this.getTopOpenedModal();
                    if (!modal.nsmDialog.first.nativeElement.contains(document.activeElement)) {
                        event.preventDefault();
                        event.stopPropagation();
                        modal.nsmDialog.first.nativeElement.focus();
                    }
                    return true;
                }
                catch (e) {
                    return false;
                }
            }
            return false;
        };
        this._addEvents();
    }
    /**
     * Add a new modal instance. This step is essential and allows to retrieve any modal at any time.
     * It stores an object that contains the given modal identifier and the modal itself directly in the `modalStack`.
     *
     * @param modalInstance The object that contains the given modal identifier and the modal itself.
     * @param force Optional parameter that forces the overriding of modal instance if it already exists.
     * @returns nothing special.
     */
    addModal(modalInstance, force) {
        this._modalStack.addModal(modalInstance, force);
    }
    /**
     * Retrieve a modal instance by its identifier.
     *
     * @param id The modal identifier used at creation time.
     */
    getModal(id) {
        return this._modalStack.getModal(id);
    }
    /**
     * Alias of `getModal` to retrieve a modal instance by its identifier.
     *
     * @param id The modal identifier used at creation time.
     */
    get(id) {
        return this.getModal(id);
    }
    /**
     * Open a given modal
     *
     * @param id The modal identifier used at creation time.
     * @param force Tell the modal to open top of all other opened modals
     */
    open(id, force = false) {
        return this._openModal(this.get(id), force);
    }
    /**
     * Close a given modal
     *
     * @param id The modal identifier used at creation time.
     */
    close(id) {
        return this._closeModal(this.get(id));
    }
    /**
     * Close all opened modals
     */
    closeAll() {
        this.getOpenedModals().forEach((instance) => {
            this._closeModal(instance.modal);
        });
    }
    /**
     * Toggles a given modal
     * If the retrieved modal is opened it closes it, else it opens it.
     *
     * @param id The modal identifier used at creation time.
     * @param force Tell the modal to open top of all other opened modals
     */
    toggle(id, force = false) {
        return this._toggleModal(this.get(id), force);
    }
    /**
     * Retrieve all the created modals.
     *
     * @returns an array that contains all modal instances.
     */
    getModalStack() {
        return this._modalStack.getModalStack();
    }
    /**
     * Retrieve all the opened modals. It looks for all modal instances with their `visible` property set to `true`.
     *
     * @returns an array that contains all the opened modals.
     */
    getOpenedModals() {
        return this._modalStack.getOpenedModals();
    }
    /**
     * Retrieve the opened modal with highest z-index.
     *
     * @returns the opened modal with highest z-index.
     */
    getTopOpenedModal() {
        return this._modalStack.getTopOpenedModal();
    }
    /**
     * Get the higher `z-index` value between all the modal instances. It iterates over the `ModalStack` array and
     * calculates a higher value (it takes the highest index value between all the modal instances and adds 1).
     * Use it to make a modal appear foreground.
     *
     * @returns a higher index from all the existing modal instances.
     */
    getHigherIndex() {
        return this._modalStack.getHigherIndex();
    }
    /**
     * It gives the number of modal instances. It's helpful to know if the modal stack is empty or not.
     *
     * @returns the number of modal instances.
     */
    getModalStackCount() {
        return this._modalStack.getModalStackCount();
    }
    /**
     * Remove a modal instance from the modal stack.
     *
     * @param id The modal identifier.
     * @returns the removed modal instance.
     */
    removeModal(id) {
        this._modalStack.removeModal(id);
    }
    /**
     * Associate data to an identified modal. If the modal isn't already associated to some data, it creates a new
     * entry in the `modalData` array with its `id` and the given `data`. If the modal already has data, it rewrites
     * them with the new ones. Finally if no modal found it returns an error message in the console and false value
     * as method output.
     *
     * @param data The data you want to associate to the modal.
     * @param id The modal identifier.
     * @param force If true, overrides the previous stored data if there was.
     * @returns true if the given modal exists and the process has been tried, either false.
     */
    setModalData(data, id, force) {
        let i;
        if (i = this.get(id)) {
            i.setData(data, force);
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * Retrieve modal data by its identifier.
     *
     * @param id The modal identifier used at creation time.
     * @returns the associated modal data.
     */
    getModalData(id) {
        let i;
        if (i = this.get(id)) {
            return i.getData();
        }
        return null;
    }
    /**
     * Reset the data attached to a given modal.
     *
     * @param id The modal identifier used at creation time.
     * @returns the removed data or false if modal doesn't exist.
     */
    resetModalData(id) {
        if (!!this._modalStack.getModalStack().find((o) => o.id === id)) {
            const removed = this.getModal(id).getData();
            this.getModal(id).removeData();
            return removed;
        }
        else {
            return false;
        }
    }
    /**
     * Close the latest opened modal if it has been declared as escapable
     * Using a debounce system because one or more modals could be listening
     * escape key press event.
     */
    closeLatestModal() {
        this.getTopOpenedModal().close();
    }
    /**
     * Create dynamic NtkSmartModalComponent
     * @param id The modal identifier used at creation time.
     * @param content The modal content ( string, templateRef or Component )
     */
    create(id, content, options = {}) {
        try {
            return this.getModal(id);
        }
        catch (e) {
            const componentFactory = this._componentFactoryResolver.resolveComponentFactory(NtkSmartModalComponent);
            const ngContent = this._resolveNgContent(content);
            const componentRef = componentFactory.create(this._injector, ngContent);
            if (content instanceof Type) {
                componentRef.instance.contentComponent = content;
            }
            componentRef.instance.identifier = id;
            componentRef.instance.createFrom = 'service';
            if (typeof options.closable === 'boolean') {
                componentRef.instance.closable = options.closable;
            }
            if (typeof options.escapable === 'boolean') {
                componentRef.instance.escapable = options.escapable;
            }
            if (typeof options.dismissable === 'boolean') {
                componentRef.instance.dismissable = options.dismissable;
            }
            if (typeof options.customClass === 'string') {
                componentRef.instance.customClass = options.customClass;
            }
            if (typeof options.backdrop === 'boolean') {
                componentRef.instance.backdrop = options.backdrop;
            }
            if (typeof options.force === 'boolean') {
                componentRef.instance.force = options.force;
            }
            if (typeof options.hideDelay === 'number') {
                componentRef.instance.hideDelay = options.hideDelay;
            }
            if (typeof options.autostart === 'boolean') {
                componentRef.instance.autostart = options.autostart;
            }
            if (typeof options.target === 'string') {
                componentRef.instance.target = options.target;
            }
            if (typeof options.ariaLabel === 'string') {
                componentRef.instance.ariaLabel = options.ariaLabel;
            }
            if (typeof options.ariaLabelledBy === 'string') {
                componentRef.instance.ariaLabelledBy = options.ariaLabelledBy;
            }
            if (typeof options.ariaDescribedBy === 'string') {
                componentRef.instance.ariaDescribedBy = options.ariaDescribedBy;
            }
            if (typeof options.refocus === 'boolean') {
                componentRef.instance.refocus = options.refocus;
            }
            this._appRef.attachView(componentRef.hostView);
            const domElem = componentRef.hostView.rootNodes[0];
            this._document.body.appendChild(domElem);
            return componentRef.instance;
        }
    }
    _addEvents() {
        if (!this.isBrowser) {
            return false;
        }
        window.addEventListener(NtkSmartModalConfig.prefixEvent + 'create', ((e) => {
            this._initModal(e.detail.instance);
        }));
        window.addEventListener(NtkSmartModalConfig.prefixEvent + 'delete', ((e) => {
            this._deleteModal(e.detail.instance);
        }));
        window.addEventListener(NtkSmartModalConfig.prefixEvent + 'open', ((e) => {
            this._openModal(e.detail.instance.modal, e.detail.top);
        }));
        window.addEventListener(NtkSmartModalConfig.prefixEvent + 'toggle', ((e) => {
            this._toggleModal(e.detail.instance.modal, e.detail.top);
        }));
        window.addEventListener(NtkSmartModalConfig.prefixEvent + 'close', ((e) => {
            this._closeModal(e.detail.instance.modal);
        }));
        window.addEventListener(NtkSmartModalConfig.prefixEvent + 'dismiss', ((e) => {
            this._dismissModal(e.detail.instance.modal);
        }));
        window.addEventListener('keyup', this._escapeKeyboardEvent);
        return true;
    }
    _initModal(modalInstance) {
        modalInstance.modal.layerPosition += this.getModalStackCount();
        this.addModal(modalInstance, modalInstance.modal.force);
        if (modalInstance.modal.autostart) {
            this.open(modalInstance.id);
        }
    }
    _openModal(modal, top) {
        if (modal.visible) {
            return false;
        }
        this.lastElementFocused = document.activeElement;
        if (modal.escapable) {
            window.addEventListener('keyup', this._escapeKeyboardEvent);
        }
        if (modal.backdrop) {
            window.addEventListener('keydown', this._trapFocusModal);
        }
        if (top) {
            modal.layerPosition = this.getHigherIndex();
        }
        modal.addBodyClass();
        modal.overlayVisible = true;
        modal.visible = true;
        modal.onOpen.emit(modal);
        modal.markForCheck();
        setTimeout(() => {
            modal.openedClass = true;
            if (modal.target) {
                modal.targetPlacement();
            }
            modal.nsmDialog.first.nativeElement.setAttribute('role', 'dialog');
            modal.nsmDialog.first.nativeElement.setAttribute('tabIndex', '-1');
            modal.nsmDialog.first.nativeElement.setAttribute('aria-modal', 'true');
            modal.nsmDialog.first.nativeElement.focus();
            modal.markForCheck();
            modal.onOpenFinished.emit(modal);
        });
        return true;
    }
    _toggleModal(modal, top) {
        if (modal.visible) {
            return this._closeModal(modal);
        }
        else {
            return this._openModal(modal, top);
        }
    }
    _closeModal(modal) {
        if (!modal.openedClass) {
            return false;
        }
        modal.openedClass = false;
        modal.onClose.emit(modal);
        modal.onAnyCloseEvent.emit(modal);
        if (this.getOpenedModals().length < 2) {
            modal.removeBodyClass();
            window.removeEventListener('keyup', this._escapeKeyboardEvent);
            window.removeEventListener('keydown', this._trapFocusModal);
        }
        setTimeout(() => {
            modal.visibleChange.emit(modal.visible);
            modal.visible = false;
            modal.overlayVisible = false;
            modal.nsmDialog.first.nativeElement.removeAttribute('tabIndex');
            modal.markForCheck();
            modal.onCloseFinished.emit(modal);
            modal.onAnyCloseEventFinished.emit(modal);
            if (modal.refocus) {
                this.lastElementFocused.focus();
            }
        }, modal.hideDelay);
        return true;
    }
    _dismissModal(modal) {
        if (!modal.openedClass) {
            return false;
        }
        modal.openedClass = false;
        modal.onDismiss.emit(modal);
        modal.onAnyCloseEvent.emit(modal);
        if (this.getOpenedModals().length < 2) {
            modal.removeBodyClass();
        }
        setTimeout(() => {
            modal.visible = false;
            modal.visibleChange.emit(modal.visible);
            modal.overlayVisible = false;
            modal.markForCheck();
            modal.onDismissFinished.emit(modal);
            modal.onAnyCloseEventFinished.emit(modal);
        }, modal.hideDelay);
        return true;
    }
    _deleteModal(modalInstance) {
        this.removeModal(modalInstance.id);
        if (!this.getModalStack().length) {
            modalInstance.modal.removeBodyClass();
        }
    }
    /**
     * Resolve content according to the types
     * @param content The modal content ( string, templateRef or Component )
     */
    _resolveNgContent(content) {
        if (typeof content === 'string') {
            const element = this._document.createTextNode(content);
            return [[element]];
        }
        if (content instanceof TemplateRef) {
            const viewRef = content.createEmbeddedView(null);
            this.applicationRef.attachView(viewRef);
            return [viewRef.rootNodes];
        }
        return [];
    }
    /**
     * Is current platform browser
     */
    get isBrowser() {
        return isPlatformBrowser(this._platformId);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalService, deps: [{ token: i0.ComponentFactoryResolver }, { token: i0.ApplicationRef }, { token: i0.Injector }, { token: NtkSmartModalStackService }, { token: i0.ApplicationRef }, { token: DOCUMENT }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i0.ComponentFactoryResolver }, { type: i0.ApplicationRef }, { type: i0.Injector }, { type: NtkSmartModalStackService }, { type: i0.ApplicationRef }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [DOCUMENT]
                }] }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [PLATFORM_ID]
                }] }] });

class NtkSmartModalModule {
    /**
     * Use in AppModule: new instance of NtkSmartModal.
     */
    static forRoot() {
        return {
            ngModule: NtkSmartModalModule,
            providers: [
                NtkSmartModalService,
                NtkSmartModalStackService
            ],
        };
    }
    /**
     * Use in features modules with lazy loading: new instance of NtkSmartModal.
     */
    static forChild() {
        return {
            ngModule: NtkSmartModalModule,
            providers: [
                NtkSmartModalService,
                NtkSmartModalStackService
            ],
        };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalModule, declarations: [NtkSmartModalComponent], imports: [CommonModule], exports: [NtkSmartModalComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalModule, imports: [CommonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartModalModule, decorators: [{
            type: NgModule,
            args: [{
                    declarations: [NtkSmartModalComponent],
                    exports: [NtkSmartModalComponent],
                    imports: [CommonModule],
                }]
        }] });

class NtkSmartLoaderService {
    constructor() {
        this.privateloaderStack = [];
        this.privateActions = [];
    }
    /**
     * Add a new loader instance. This step is essential and allows to retrieve any loader at any time.
     * It stores an object that contains the given loader identifier and the loader itself directly in the `loaderStack`.
     *
     * @param loaderInstance The object that contains the given loader identifier and the loader itself.
     * @param force Optional parameter that forces the overriding of loader instance if it already exists.
     * @returns Returns nothing special.
     */
    addLoader(loaderInstance, force) {
        if (force) {
            const i = this.privateloaderStack.findIndex((o) => {
                return o.id === loaderInstance.id;
            });
            if (i > -1) {
                this.privateloaderStack[i].component = loaderInstance.component;
            }
            else {
                this.privateloaderStack.push(loaderInstance);
            }
            return;
        }
        let loader;
        // tslint:disable-next-line: no-conditional-assignment
        if (loader = this._getLoader(loaderInstance.id)) {
            throw (new Error('Loader with ' + loaderInstance.id + ' identifier already exist'));
        }
        else {
            this.privateloaderStack.push(loaderInstance);
        }
    }
    /**
     * Remove a loader instance from the loader stack.
     *
     * @param id The loader identifier.
     */
    removeLoader(id) {
        this.privateloaderStack = this.privateloaderStack.filter((loader) => loader.id !== id);
        this._removeAction(id, '*');
    }
    /**
     * Retrieve all the created loaders.
     *
     * @returns Returns an array that contains all loader instances.
     */
    getLoaderStack() {
        return this.privateloaderStack;
    }
    /**
     * It gives the number of loader instances. It's helpful to know if the loader stack is empty or not.
     *
     * @returns Returns the number of loader instances.
     */
    getLoaderStackCount() {
        return this.privateloaderStack.length;
    }
    /**
     * Retrieve all the opened loaders. It looks for all loader instances with their `visible` property set to `true`.
     *
     * @returns Returns an array that contains all the opened loaders.
     */
    getOpenedLoaders() {
        return this.privateloaderStack.filter((loader) => loader.component.visible);
    }
    /**
     * Retrieve all the active loaders. It looks for all loader instances with their `loading` property set to `true`.
     *
     * @returns Returns an array that contains all the active loaders.
     */
    getActiveLoaders() {
        return this.privateloaderStack.filter((loader) => loader.component.loading);
    }
    /**
     * Get the higher `z-index` value between all the loader instances. It iterates over the `LoaderStack` array and
     * calculates a higher value (it takes the highest index value between all the loader instances and adds 1).
     * Use it to make a loader appear foreground.
     *
     * @returns Returns a higher index from all the existing loader instances.
     */
    getHigherIndex() {
        const index = this.getOpenedLoaders().map((loader) => loader.component.layerPosition);
        return Math.max(...index) + 1;
    }
    /**
     * Enable loading state to one or several loaders.
     *
     * @param id The loader identifier.
     */
    start(id) {
        let loader;
        if (Array.isArray(id)) {
            id.forEach((i) => {
                this.start(i);
            });
        }
        else if (loader = this._getLoader(id)) {
            loader.component.start();
            this._removeAction(id, 'start');
        }
        else {
            this._addAction(id, 'start');
        }
    }
    /**
     * Enable loading state to all loaders.
     */
    startAll() {
        this.privateloaderStack.forEach((loader) => this.start(loader.id));
    }
    /**
     * Disable loading state to one or several loaders.
     *
     * @param id The loader identifier.
     */
    stop(id) {
        let loader;
        if (Array.isArray(id)) {
            id.forEach((i) => {
                this.stop(i);
            });
        }
        else if (loader = this._getLoader(id)) {
            loader.component.stop();
            this._removeAction(id, 'stop');
        }
        else {
            this._addAction(id, 'stop');
        }
    }
    /**
     * Disable loading state to all loaders.
     */
    stopAll() {
        this.privateloaderStack.forEach((loader) => this.stop(loader.id));
    }
    isLoading(id) {
        let loader;
        if (Array.isArray(id)) {
            const tmp = [];
            id.forEach((i) => {
                this.privateloaderStack.forEach((load) => {
                    if (load.id === i) {
                        tmp.push(load.component.loading);
                    }
                });
            });
            return tmp.indexOf(false) === -1;
        }
        else if (loader = this._getLoader(id)) {
            return loader.component.loading;
        }
        else {
            return false;
        }
    }
    /**
     * Execute an action on loaders
     *
     * @param id The loader identifier.
     * @param action Name of the action.
     */
    executeAction(id, action) {
        // First check if the action exists in privateActions
        if (this.privateActions.find((act) => act.identifier === id && act.action === action)) {
            switch (action) {
                case 'start':
                    this.start(id);
                    break;
                case 'stop':
                    this.stop(id);
                    break;
            }
        }
        else {
            // If no action exists, execute it directly if the loader exists
            let loader;
            if (loader = this._getLoader(id)) {
                switch (action) {
                    case 'start':
                        loader.component.start();
                        break;
                    case 'stop':
                        loader.component.stop();
                        break;
                }
            }
            else {
                // If loader doesn't exist, add the action to be executed later
                this._addAction(id, action);
            }
        }
    }
    /**
     * Retrieve a loader instance by its identifier.
     * If there's several loaders with same identifier, the first is returned.
     *
     * @param id The loader identifier used at creation time.
     */
    _getLoader(id) {
        return this.privateloaderStack.find((load) => load.id === id) || null;
    }
    /**
     * Adds an action on one or more loaders
     *
     * @param id The loader identifier.
     * @param action Name of the action.
     */
    _addAction(id, action) {
        if (Array.isArray(id)) {
            id.forEach((i) => {
                this._addAction(i, action);
            });
        }
        else {
            this.privateActions.push({ identifier: id, action: action });
        }
    }
    /**
     * Remove an action on one or more loaders
     *
     * @param id The loader identifier.
     * @param action Name of the action.
     */
    _removeAction(id, action) {
        if (Array.isArray(id)) {
            id.forEach((i) => {
                this._removeAction(i, action);
            });
        }
        else {
            this.privateActions = this.privateActions.filter((act) => act.identifier !== id || (act.action !== action && action !== '*'));
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartLoaderService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartLoaderService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root',
                }]
        }] });

class LoaderInstance {
    constructor(component) {
        this.id = component.identifier;
        this.component = component;
    }
}

class NtkSmartLoaderComponent {
    constructor(ntkSmartLoaderService, changeDetectorRef) {
        this.ntkSmartLoaderService = ntkSmartLoaderService;
        this.changeDetectorRef = changeDetectorRef;
        this.identifier = '';
        this.customClass = '';
        this.force = false;
        this.delayIn = 0;
        this.delayOut = 0;
        this.autostart = false;
        this.onStart = new EventEmitter();
        this.onStop = new EventEmitter();
        this.onVisibleChange = new EventEmitter();
        this.loading = false;
        this.visible = false;
        this.layerPosition = 999;
        this.privateIsProcessing = false;
        this.privateLoaderBodyClass = 'loader-open';
        this.privateEnterClass = 'enter';
        this.privateLeaveClass = 'leave';
    }
    ngOnInit() {
        try {
            console.log('SmartLoader Component initialized with identifier:', this.identifier);
            const loader = new LoaderInstance(this);
            this.ntkSmartLoaderService.addLoader(loader, this.force);
            console.log('Loader added to service. Stack count:', this.ntkSmartLoaderService.getLoaderStackCount());
            this.layerPosition += this.ntkSmartLoaderService.getLoaderStackCount();
            this.addCustomClass(this.identifier.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase());
            if (this.autostart) {
                console.log('Autostart enabled, starting loader');
                this.ntkSmartLoaderService.start(this.identifier);
            }
            // Don't auto-start if autostart is false - let user control it manually
        }
        catch (error) {
            console.error('Error in smart loader initialization:', error);
            throw error;
        }
    }
    ngOnDestroy() {
        this.ntkSmartLoaderService.removeLoader(this.identifier);
    }
    start(top) {
        console.log('SmartLoader start called for identifier:', this.identifier);
        this.privateIsProcessing = true;
        clearInterval(this.privateDebouncer);
        this.visible = true;
        console.log('Loader visible set to true');
        setTimeout(() => {
            this.addCustomClass(this.privateEnterClass);
        });
        this.privateDebouncer = setTimeout(() => {
            if (top) {
                this.layerPosition = this.ntkSmartLoaderService.getHigherIndex();
            }
            if (!document.body.classList.contains(this.privateLoaderBodyClass)) {
                document.body.classList.add(this.privateLoaderBodyClass);
            }
            this.loading = true;
            console.log('Loader loading set to true');
            this.onStart.emit(this);
            this.onVisibleChange.emit(this);
            this.removeCustomClass(this.privateEnterClass);
            this.privateIsProcessing = false;
        }, this.delayIn);
    }
    stop() {
        if (this.privateIsProcessing) {
            this.visible = false;
            this.loading = false;
        }
        clearInterval(this.privateDebouncer);
        this.addCustomClass(this.privateLeaveClass);
        this.loading = false;
        this.privateDebouncer = setTimeout(() => {
            if (document.body.classList.contains(this.privateLoaderBodyClass)) {
                document.body.classList.remove(this.privateLoaderBodyClass);
            }
            this.visible = false;
            this.onStop.emit(this);
            this.onVisibleChange.emit(this);
            this.removeCustomClass(this.privateLeaveClass);
            setTimeout(() => {
                this.changeDetectorRef.markForCheck();
            });
        }, this.delayOut);
    }
    addCustomClass(className) {
        if (!this.customClass.length) {
            this.customClass = className;
        }
        else {
            if (this.customClass.indexOf(className) === -1) {
                this.customClass += ' ' + className;
            }
        }
    }
    removeCustomClass(className) {
        if (className) {
            this.customClass = this.customClass.replace(className, '').trim();
        }
        else {
            this.customClass = '';
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartLoaderComponent, deps: [{ token: NtkSmartLoaderService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: NtkSmartLoaderComponent, isStandalone: false, selector: "ntk-smart-loader", inputs: { identifier: "identifier", customClass: "customClass", force: "force", delayIn: "delayIn", delayOut: "delayOut", autostart: "autostart" }, outputs: { onStart: "onStart", onStop: "onStop", onVisibleChange: "onVisibleChange" }, ngImport: i0, template: `
    <div
      class="loader-container {{ customClass }}"
      [ngClass]="{ active: loading }"
      [style.z-index]="layerPosition - 1"
      *ngIf="visible"
    >
      <ng-content></ng-content>
    </div>
  `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartLoaderComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'ntk-smart-loader',
                    standalone: false,
                    template: `
    <div
      class="loader-container {{ customClass }}"
      [ngClass]="{ active: loading }"
      [style.z-index]="layerPosition - 1"
      *ngIf="visible"
    >
      <ng-content></ng-content>
    </div>
  `,
                }]
        }], ctorParameters: () => [{ type: NtkSmartLoaderService }, { type: i0.ChangeDetectorRef }], propDecorators: { identifier: [{
                type: Input
            }], customClass: [{
                type: Input
            }], force: [{
                type: Input
            }], delayIn: [{
                type: Input
            }], delayOut: [{
                type: Input
            }], autostart: [{
                type: Input
            }], onStart: [{
                type: Output
            }], onStop: [{
                type: Output
            }], onVisibleChange: [{
                type: Output
            }] } });

class NtkSmartLoaderModule {
    /**
     * Use in AppModule: new instance of NtkSmartLoader.
     */
    static forRoot() {
        return {
            ngModule: NtkSmartLoaderModule,
            providers: [NtkSmartLoaderService],
        };
    }
    /**
     * Use in features modules with lazy loading: new instance of NtkSmartLoader.
     */
    static forChild() {
        return {
            ngModule: NtkSmartLoaderModule,
            providers: [NtkSmartLoaderService],
        };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartLoaderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartLoaderModule, declarations: [NtkSmartLoaderComponent], imports: [CommonModule], exports: [NtkSmartLoaderComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartLoaderModule, imports: [CommonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NtkSmartLoaderModule, decorators: [{
            type: NgModule,
            args: [{
                    declarations: [NtkSmartLoaderComponent],
                    exports: [NtkSmartLoaderComponent],
                    imports: [CommonModule],
                }]
        }] });

/*
 * Public API Surface of ntk-cms-module
 */

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

export { NtkSmartLoaderComponent, NtkSmartLoaderModule, NtkSmartLoaderService, NtkSmartModalComponent, NtkSmartModalModule, NtkSmartModalService, NtkSmartModalStackService };
//# sourceMappingURL=ngx-ntk-smart-module.mjs.map