UNPKG

@euro-ombudsman/ngx-modal-dialog

Version:
413 lines (404 loc) 19.7 kB
import * as i0 from '@angular/core'; import { ViewContainerRef, Component, ViewChild, HostListener, Injectable, ComponentFactoryResolver, Inject, InjectionToken, Optional, SkipSelf, NgModule } from '@angular/core'; import { Subject, from } from 'rxjs'; import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; /** * Modal dialog component */ class ModalDialogComponent { /** * CTOR * @param _element * @param componentFactoryResolver */ constructor(_element, componentFactoryResolver) { this._element = _element; this.componentFactoryResolver = componentFactoryResolver; /** Modal dialog style settings */ this.settings = { overlayClass: 'modal-backdrop fade', overlayAnimationTriggerClass: 'show', modalClass: 'modal ngx-modal fade', modalAnimationTriggerClass: 'show', modalDialogClass: 'modal-dialog modal-dialog-centered', contentClass: 'modal-content', headerClass: 'modal-header', headerTitleClass: 'modal-title', closeButtonClass: 'close glyphicon glyphicon-remove', closeButtonTitle: 'CLOSE', bodyClass: 'modal-body', footerClass: 'modal-footer', alertClass: 'ngx-modal-shake', alertDuration: 250, notifyWithAlert: true, buttonClass: 'btn btn-primary' }; this.showAlert = false; this.animateOverlayClass = ''; this.animateModalClass = ''; this.showOverlay = false; this._inProgress = false; } onClick(event) { if (event.target !== this.dialogElement.nativeElement) { return; } this.close(); } /** * Initialize dialog with reference to instance and options * @param reference * @param options */ dialogInit(reference, options = {}) { this.reference = reference; // inject component if (options.childComponent) { let factory = this.componentFactoryResolver.resolveComponentFactory(options.childComponent); let componentRef = this.dynamicComponentTarget.createComponent(factory); this._childInstance = componentRef.instance; this._closeDialog$ = new Subject(); this._closeDialog$.subscribe(() => { this._finalizeAndDestroy(); }); options.closeDialogSubject = this._closeDialog$; this._childInstance['dialogInit'](componentRef, options); document.activeElement != null ? document.activeElement.blur() : document.body.blur(); } // set options this._setOptions(options); } ngOnInit() { // a trick to defer css animations setTimeout(() => { this.animateOverlayClass = this.settings.overlayAnimationTriggerClass; this.animateModalClass = this.settings.modalAnimationTriggerClass; }, 0); } /** * Cleanup on destroy */ ngOnDestroy() { // run animations this.animateOverlayClass = ''; this.animateModalClass = ''; // cleanup listeners if (this._alertTimeout) { clearTimeout(this._alertTimeout); this._alertTimeout = null; } if (this._closeDialog$) { this._closeDialog$.unsubscribe(); } } /** * Run action defined on action button * @param action */ doAction(action) { // disable multi clicks if (this._inProgress) { return; } this._inProgress = true; this._closeIfSuccessful(action); } /** * Method to run on close * if action buttons are defined, it will not close */ close() { if (this._inProgress) { return; } if (this.actionButtons && this.actionButtons.length) { return; } this._inProgress = true; if (this.onClose) { this._closeIfSuccessful(this.onClose); return; } this._finalizeAndDestroy(); } /** * Pass options from dialog setup to component * @param {IModalDialogOptions} options? */ _setOptions(options) { if (options.onClose && options.actionButtons && options.actionButtons.length) { throw new Error(`OnClose callback and ActionButtons are not allowed to be defined on the same dialog.`); } // set references this.title = (options && options.title) || ''; this.onClose = (options && options.onClose) || null; this.actionButtons = (this._childInstance && this._childInstance['actionButtons']) || (options && options.actionButtons) || null; if (options && options.settings) { Object.assign(this.settings, options.settings); } } /** * Close if successful * @param callback */ _closeIfSuccessful(callback) { if (!callback) { return this._finalizeAndDestroy(); } let response = callback(); if (typeof response === 'boolean') { if (response) { return this._finalizeAndDestroy(); } return this._triggerAlert(); } if (this.isPromise(response)) { response = from(response); } if (this.isObservable(response)) { response.subscribe(() => { this._finalizeAndDestroy(); }, () => { this._triggerAlert(); }); } else { this._inProgress = false; } } _finalizeAndDestroy() { this._inProgress = false; this.reference.destroy(); } _triggerAlert() { if (this.settings.notifyWithAlert) { this.showAlert = true; this._alertTimeout = window.setTimeout(() => { this.showAlert = false; this._inProgress = false; clearTimeout(this._alertTimeout); this._alertTimeout = null; }, this.settings.alertDuration); } } isPromise(value) { return value && typeof value.subscribe !== 'function' && typeof value.then === 'function'; } isObservable(value) { return value && typeof value.subscribe === 'function'; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogComponent, deps: [{ token: i0.ElementRef }, { token: i0.ComponentFactoryResolver }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.4", type: ModalDialogComponent, isStandalone: false, selector: "modal-dialog", host: { listeners: { "click": "onClick($event)" } }, viewQueries: [{ propertyName: "dynamicComponentTarget", first: true, predicate: ["modalDialogBody"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "dialogElement", first: true, predicate: ["dialog"], descendants: true }], ngImport: i0, template: ` <div *ngIf="settings.overlayClass && showOverlay" [ngClass]="[settings.overlayClass, animateOverlayClass]"></div> <div [ngClass]="[settings.modalClass, animateModalClass]" #dialog> <div [ngClass]="settings.modalDialogClass"> <div [ngClass]="[ showAlert ? settings.alertClass : '', settings.contentClass]"> <div [ngClass]="settings.headerClass"> <h4 [ngClass]="settings.headerTitleClass">{{title}}</h4> <button (click)="close()" *ngIf="!actionButtons || !actionButtons.length" type="button" [title]="settings.closeButtonTitle" [ngClass]="settings.closeButtonClass"> </button> </div> <div [ngClass]="settings.bodyClass"> <i #modalDialogBody></i> </div> <div [ngClass]="settings.footerClass" *ngIf="actionButtons && actionButtons.length"> <button *ngFor="let button of actionButtons" (click)="doAction(button.onAction)" [ngClass]="button.buttonClass || settings.buttonClass">{{button.text}} </button> </div> </div> </div> </div> `, isInline: true, styles: ["@-moz-keyframes shake{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(-2rem,0,0)}20%,40%,60%,80%{transform:translate3d(2rem,0,0)}}@-webkit-keyframes shake{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(-2rem,0,0)}20%,40%,60%,80%{transform:translate3d(2rem,0,0)}}@keyframes shake{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(-2rem,0,0)}20%,40%,60%,80%{transform:translate3d(2rem,0,0)}}.ngx-modal{display:flex}.ngx-modal-shake{backface-visibility:hidden;-webkit-animation-duration:.5s;-moz-animation-duration:.5s;animation-duration:.5s;-webkit-animation-fill-mode:both;-moz-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:shake;-moz-animation-name:shake;animation-name:shake}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogComponent, decorators: [{ type: Component, args: [{ selector: 'modal-dialog', template: ` <div *ngIf="settings.overlayClass && showOverlay" [ngClass]="[settings.overlayClass, animateOverlayClass]"></div> <div [ngClass]="[settings.modalClass, animateModalClass]" #dialog> <div [ngClass]="settings.modalDialogClass"> <div [ngClass]="[ showAlert ? settings.alertClass : '', settings.contentClass]"> <div [ngClass]="settings.headerClass"> <h4 [ngClass]="settings.headerTitleClass">{{title}}</h4> <button (click)="close()" *ngIf="!actionButtons || !actionButtons.length" type="button" [title]="settings.closeButtonTitle" [ngClass]="settings.closeButtonClass"> </button> </div> <div [ngClass]="settings.bodyClass"> <i #modalDialogBody></i> </div> <div [ngClass]="settings.footerClass" *ngIf="actionButtons && actionButtons.length"> <button *ngFor="let button of actionButtons" (click)="doAction(button.onAction)" [ngClass]="button.buttonClass || settings.buttonClass">{{button.text}} </button> </div> </div> </div> </div> `, standalone: false, styles: ["@-moz-keyframes shake{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(-2rem,0,0)}20%,40%,60%,80%{transform:translate3d(2rem,0,0)}}@-webkit-keyframes shake{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(-2rem,0,0)}20%,40%,60%,80%{transform:translate3d(2rem,0,0)}}@keyframes shake{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(-2rem,0,0)}20%,40%,60%,80%{transform:translate3d(2rem,0,0)}}.ngx-modal{display:flex}.ngx-modal-shake{backface-visibility:hidden;-webkit-animation-duration:.5s;-moz-animation-duration:.5s;animation-duration:.5s;-webkit-animation-fill-mode:both;-moz-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:shake;-moz-animation-name:shake;animation-name:shake}\n"] }] }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ComponentFactoryResolver }], propDecorators: { dynamicComponentTarget: [{ type: ViewChild, args: ['modalDialogBody', { read: ViewContainerRef, static: true }] }], dialogElement: [{ type: ViewChild, args: ['dialog'] }], onClick: [{ type: HostListener, args: ['click', ['$event']] }] } }); class ModalDialogInstanceService { constructor() { /** * Used to make sure there is exactly one instance of Modal Dialog */ this.componentRefs = []; } /** * Closes existing modal dialog */ closeAnyExistingModalDialog() { while (this.componentRefs.length) { this.componentRefs[this.componentRefs.length - 1].destroy(); } } /** * Save component ref for future comparison * @param componentRef */ saveExistingModalDialog(componentRef) { // remove overlay from top element this.setOverlayForTopDialog(false); // add new component this.componentRefs = [...this.componentRefs, componentRef]; componentRef.instance.showOverlay = true; componentRef.onDestroy(() => { this.componentRefs.pop(); this.setOverlayForTopDialog(true); }); } setOverlayForTopDialog(value) { if (this.componentRefs.length) { this.componentRefs[this.componentRefs.length - 1].instance.showOverlay = value; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogInstanceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogInstanceService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogInstanceService, decorators: [{ type: Injectable }] }); class ModalDialogService { /** * CTOR * @param componentFactoryResolver * @param modalDialogInstanceService */ constructor(componentFactoryResolver, modalDialogInstanceService) { this.componentFactoryResolver = componentFactoryResolver; this.modalDialogInstanceService = modalDialogInstanceService; } /** * Open dialog in given target element with given options * @param {ViewContainerRef} target * @param {IModalDialogOptions} options? */ openDialog(target, options = {}) { if (!options.placeOnTop) { this.modalDialogInstanceService.closeAnyExistingModalDialog(); } const factory = this.componentFactoryResolver.resolveComponentFactory(ModalDialogComponent); const componentRef = target.createComponent(factory); componentRef.instance.dialogInit(componentRef, options); this.modalDialogInstanceService.saveExistingModalDialog(componentRef); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogService, deps: [{ token: ComponentFactoryResolver }, { token: ModalDialogInstanceService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i0.ComponentFactoryResolver, decorators: [{ type: Inject, args: [ComponentFactoryResolver] }] }, { type: ModalDialogInstanceService, decorators: [{ type: Inject, args: [ModalDialogInstanceService] }] }] }); class SimpleModalComponent { /** * Initialize dialog with simple HTML content * @param {ComponentRef<IModalDialog>} reference * @param {Partial<IModalDialogOptions>} options */ dialogInit(reference, options) { if (!options.data) { throw new Error(`Data information for simple modal dialog is missing`); } this.text = options.data.text; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: SimpleModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.4", type: SimpleModalComponent, isStandalone: false, selector: "simple-modal-dialog", host: { properties: { "innerHTML": "text" } }, ngImport: i0, template: ``, isInline: true, styles: [":host{display:block}\n"] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: SimpleModalComponent, decorators: [{ type: Component, args: [{ selector: 'simple-modal-dialog', template: ``, host: { '[innerHTML]': 'text' }, standalone: false, styles: [":host{display:block}\n"] }] }] }); // components and directives /** * Guard to make sure we have single initialization of forRoot * @type {InjectionToken<ModalDialogModule>} */ const MODAL_DIALOG_FORROOT_GUARD = new InjectionToken('MODAL_DIALOG_FORROOT_GUARD'); class ModalDialogModule { static forRoot() { return { ngModule: ModalDialogModule, providers: [ { provide: MODAL_DIALOG_FORROOT_GUARD, useFactory: provideForRootGuard, deps: [ModalDialogModule, new Optional(), new SkipSelf()] }, ModalDialogInstanceService ] }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogModule, declarations: [ModalDialogComponent, SimpleModalComponent], imports: [CommonModule], exports: [ModalDialogComponent, SimpleModalComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogModule, providers: [ModalDialogService, ModalDialogInstanceService], imports: [CommonModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: ModalDialogModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule], declarations: [ModalDialogComponent, SimpleModalComponent], exports: [ModalDialogComponent, SimpleModalComponent], providers: [ModalDialogService, ModalDialogInstanceService] }] }] }); /** * @param dialogModule * @returns {string} */ function provideForRootGuard(dialogModule) { if (dialogModule) { throw new Error(`ModalDialogModule.forRoot() called twice.`); } return 'guarded'; } /* * Public API Surface of ngx-modal-dialog */ /** * Generated bundle index. Do not edit. */ export { MODAL_DIALOG_FORROOT_GUARD, ModalDialogComponent, ModalDialogInstanceService, ModalDialogModule, ModalDialogService, SimpleModalComponent, provideForRootGuard }; //# sourceMappingURL=euro-ombudsman-ngx-modal-dialog.mjs.map