UNPKG

@browninglogic/ng-modal

Version:

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

425 lines (392 loc) 21.4 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('rxjs/operators'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('@browninglogic/ng-modal', ['exports', '@angular/core', 'rxjs/operators', '@angular/common'], factory) : (global = global || self, factory((global.browninglogic = global.browninglogic || {}, global.browninglogic['ng-modal'] = {}), global.ng.core, global.rxjs.operators, global.ng.common)); }(this, (function (exports, core, operators, common) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } function __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } function __param(paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } } function __metadata(metadataKey, metadataValue) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); } function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } function __exportStar(m, exports) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; } function __values(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spread() { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; } function __spreadArrays() { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; function __await(v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } function __asyncGenerator(thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var g = generator.apply(thisArg, _arguments || []), i, q = []; return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } } function __asyncDelegator(o) { var i, p; return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; } } function __asyncValues(o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } } function __makeTemplateObject(cooked, raw) { if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } return cooked; }; function __importStar(mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result.default = mod; return result; } function __importDefault(mod) { return (mod && mod.__esModule) ? mod : { default: mod }; } function __classPrivateFieldGet(receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); } function __classPrivateFieldSet(receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; } /** * 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. */ var ModalManagerService = /** @class */ (function () { function ModalManagerService() { /** Informs subscribers when the index of a modal on the stack changes */ this.modalIndexChanged = new core.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 */ ModalManagerService.prototype.push = function (modal) { var 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 */ ModalManagerService.prototype.removeModal = function (modal) { // Find the index of the modal var 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 (var i = modalIndex; i < this.activeModals.length; i++) { this.modalIndexChanged.emit([this.activeModals[i], i]); } } }; __decorate([ core.Output(), __metadata("design:type", Object) ], ModalManagerService.prototype, "modalIndexChanged", void 0); ModalManagerService = __decorate([ core.Injectable() ], ModalManagerService); return ModalManagerService; }()); var ModalWindowComponent = /** @class */ (function () { function ModalWindowComponent(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; } Object.defineProperty(ModalWindowComponent.prototype, "visible", { /** Reports the visibility status of the modal window*/ get: function () { return this._visible; }, enumerable: true, configurable: true }); ModalWindowComponent.prototype.ngOnInit = function () { var _this = this; /* 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. operators.filter(function (indexChange) { return indexChange[0] === _this; })).subscribe(function (indexChange) { return _this.onIndexChanged(indexChange[1]); }); }; ModalWindowComponent.prototype.ngOnDestroy = function () { 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 */ ModalWindowComponent.prototype.onIndexChanged = function (newIndex) { this.modalIndex = newIndex; }; Object.defineProperty(ModalWindowComponent.prototype, "zIndex", { /** Provides the z-index to be used in the template for layering the modal */ get: function () { return this.modalIndex != null ? this.modalManagerService.startingZIndex + this.modalIndex : null; }, enumerable: true, configurable: true }); /** Shows the modal and registers it with the modal manager */ ModalWindowComponent.prototype.show = function () { this.modalIndex = this.modalManagerService.push(this); this._visible = true; }; /** Hides the modal and de-registers it with the modal manager */ ModalWindowComponent.prototype.hide = function () { 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 */ ModalWindowComponent.prototype.onOverlayClicked = function (event) { if (event.target.classList.contains('nm-modal-overlay') && this.closeOnOverlayClick) { this.hide(); } }; ModalWindowComponent.ctorParameters = function () { return [ { type: ModalManagerService } ]; }; __decorate([ core.Input(), __metadata("design:type", Object) ], ModalWindowComponent.prototype, "modalClass", void 0); __decorate([ core.Input(), __metadata("design:type", Object) ], ModalWindowComponent.prototype, "overlayClass", void 0); __decorate([ core.Input(), __metadata("design:type", Object) ], ModalWindowComponent.prototype, "closeOnOverlayClick", void 0); __decorate([ core.Input(), __metadata("design:type", Object) ], ModalWindowComponent.prototype, "showCloseButton", void 0); ModalWindowComponent = __decorate([ core.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); return ModalWindowComponent; }()); var ModalManagerModule = /** @class */ (function () { function ModalManagerModule() { } ModalManagerModule = __decorate([ core.NgModule({ imports: [ common.CommonModule ], providers: [ ModalManagerService ], declarations: [ ModalWindowComponent ], exports: [ ModalWindowComponent ] }) ], ModalManagerModule); return ModalManagerModule; }()); exports.ModalManagerModule = ModalManagerModule; exports.ModalManagerService = ModalManagerService; exports.ModalWindowComponent = ModalWindowComponent; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=browninglogic-ng-modal.umd.js.map