UNPKG

@browninglogic/ng-modal

Version:

A simple, lightweight interface for creating layered modal dialogs in Angular 6+

198 lines (191 loc) 8.19 kB
import { __decorate, __metadata } from 'tslib'; import { EventEmitter, Output, Injectable, Input, Component, NgModule } from '@angular/core'; import { filter } from 'rxjs/operators'; import { CommonModule } from '@angular/common'; /** * Maintains the indices of all active modal windows and reports index * changes to the relevant modals so that each modal can layer itself * accordingly with the correct z-index. */ let ModalManagerService = class ModalManagerService { constructor() { /** Informs subscribers when the index of a modal on the stack changes */ this.modalIndexChanged = new EventEmitter(); /** Maintains the currently-displayed modal windows in order */ this.activeModals = new Array(); /** Starting point for the z-index of the layered modal windows */ this.startingZIndex = 1000; } /** * Pushes the provided modal to the top of the stack, if it's not already there, and * returns its index so that the component knows where to place itself via z-index * @param modal A reference to the the modal component instance that we want to register */ push(modal) { const modalIndex = this.activeModals.indexOf(modal); // If the modal isn't already on the stack, then push it to the top. if (modalIndex === -1) { this.activeModals.push(modal); return this.activeModals.indexOf(modal); } else if (modalIndex === this.activeModals.length - 1) { // If the modal is already on the top, then don't do anything: simply return the index return modalIndex; } else { /* If the modal is already on the stack, but not on the top, then remove it and add it to the top. */ this.removeModal(modal); this.activeModals.push(modal); return this.activeModals.indexOf(modal); } } /** * Removes the specified modal, if it exists. * @param modal The modal to remove */ removeModal(modal) { // Find the index of the modal const modalIndex = this.activeModals.indexOf(modal); if (modalIndex > -1) { // If the modal exists in the array, then remove it. this.activeModals.splice(modalIndex, 1); /* If we removed a modal which was not at the top of the stack, then inform each modal above the removed modal in the stack so that they can update their index and, by extension, z-index. */ for (let i = modalIndex; i < this.activeModals.length; i++) { this.modalIndexChanged.emit([this.activeModals[i], i]); } } } }; __decorate([ Output(), __metadata("design:type", Object) ], ModalManagerService.prototype, "modalIndexChanged", void 0); ModalManagerService = __decorate([ Injectable() ], ModalManagerService); let ModalWindowComponent = class ModalWindowComponent { constructor(modalManagerService) { this.modalManagerService = modalManagerService; /** Custom CSS class(es) to apply to the modal*/ this.modalClass = ''; /** Custom CSS class(es) to apply to the overlay*/ this.overlayClass = ''; /** Specifies whether the modal will close if the user clicks on the surrounding overlay */ this.closeOnOverlayClick = true; /** Specifies whether to show the built-in close button */ this.showCloseButton = false; /** Visibility flag for internal use*/ this._visible = false; } /** Reports the visibility status of the modal window*/ get visible() { return this._visible; } ngOnInit() { /* Subscribe to changes of this modal's index on the global modal stack so that this modal can accurately maintain its z-index with relation to other layered modal windows */ this.subIndexChanged = this.modalManagerService.modalIndexChanged.pipe( // We only care about changes to the modal's own index. filter(indexChange => indexChange[0] === this)).subscribe(indexChange => this.onIndexChanged(indexChange[1])); } ngOnDestroy() { if (this.subIndexChanged) { this.subIndexChanged.unsubscribe(); } } /** * Updates the local copy of the index when necessary so that the * corresponding z-index will be updated in the template. * @param newIndex new index provided by the modal management service */ onIndexChanged(newIndex) { this.modalIndex = newIndex; } /** Provides the z-index to be used in the template for layering the modal */ get zIndex() { return this.modalIndex != null ? this.modalManagerService.startingZIndex + this.modalIndex : null; } /** Shows the modal and registers it with the modal manager */ show() { this.modalIndex = this.modalManagerService.push(this); this._visible = true; } /** Hides the modal and de-registers it with the modal manager */ hide() { this.modalManagerService.removeModal(this); this._visible = false; this.modalIndex = null; } /** * Handles the click event when a user clicks on the overlay. * If the user clicked on the overlay and closeOnOverlayClick is enabled, * then close the modal. * @param event The mouse event provided by the browser */ onOverlayClicked(event) { if (event.target.classList.contains('nm-modal-overlay') && this.closeOnOverlayClick) { this.hide(); } } }; ModalWindowComponent.ctorParameters = () => [ { type: ModalManagerService } ]; __decorate([ Input(), __metadata("design:type", Object) ], ModalWindowComponent.prototype, "modalClass", void 0); __decorate([ Input(), __metadata("design:type", Object) ], ModalWindowComponent.prototype, "overlayClass", void 0); __decorate([ Input(), __metadata("design:type", Object) ], ModalWindowComponent.prototype, "closeOnOverlayClick", void 0); __decorate([ Input(), __metadata("design:type", Object) ], ModalWindowComponent.prototype, "showCloseButton", void 0); ModalWindowComponent = __decorate([ Component({ selector: 'nm-modal-window', template: "<div [class]=\"'nm-modal-overlay ' + overlayClass\" (click)=\"onOverlayClicked($event)\" [style.display]=\"visible ? 'block' : 'none'\" [style.z-index]=\"zIndex\">\n <div [class]=\"'nm-modal-window ' + modalClass\">\n <div *ngIf=\"showCloseButton\" (click)=\"hide()\" class=\"nm-modal-close-btn\">&times;</div>\n\n <div>\n <ng-content select=\"[header]\"></ng-content>\n </div>\n <div>\n <ng-content select=\"[body]\"></ng-content>\n </div>\n <div>\n <ng-content select=\"[footer]\"></ng-content>\n </div>\n </div>\n</div>", styles: [".nm-modal-overlay{position:fixed;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,.2)}.nm-modal-window{position:fixed;border:2px solid grey;border-radius:15px;text-align:center;background:#fff;padding:10px 23px;display:inline-block;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.nm-modal-close-btn{position:absolute;right:3px;top:5px;color:#888;font-weight:700;font-size:20px;cursor:pointer;width:25px;line-height:23px}.nm-modal-close-btn:hover{color:#000}"] }), __metadata("design:paramtypes", [ModalManagerService]) ], ModalWindowComponent); let ModalManagerModule = class ModalManagerModule { }; ModalManagerModule = __decorate([ NgModule({ imports: [ CommonModule ], providers: [ ModalManagerService ], declarations: [ ModalWindowComponent ], exports: [ ModalWindowComponent ] }) ], ModalManagerModule); /* * Public API Surface of ng-modal */ /** * Generated bundle index. Do not edit. */ export { ModalManagerModule, ModalManagerService, ModalWindowComponent }; //# sourceMappingURL=browninglogic-ng-modal.js.map