UNPKG

ngx-toasta

Version:

Simple and clean Angular Toast component that shows growl-style notifications and messages for your web app

523 lines (513 loc) 21.8 kB
import * as i0 from '@angular/core'; import { Injectable, Pipe, EventEmitter, Component, Input, Output, NgModule } from '@angular/core'; import { Subject } from 'rxjs'; import * as i1$1 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i1 from '@angular/platform-browser'; /** * Check and return true if an object is type of string * @param obj Analyse has to object the string type * @return result of analysis */ function isString(obj) { return typeof obj === 'string'; } /** * Check and return true if an object is type of number * @param obj Analyse has to object the boolean type * @return result of analysis */ function isNumber(obj) { return typeof obj === 'number'; } /** * Check and return true if an object is type of Function * @param obj Analyse has to object the function type * @return result of analysis */ function isFunction(obj) { return typeof obj === 'function'; } /** * Options to configure a new Toast */ class ToastOptions { } ToastOptions.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastOptions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); ToastOptions.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastOptions }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastOptions, decorators: [{ type: Injectable }] }); /** * Structrure of a created Toast */ class ToastData { } ToastData.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastData, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); ToastData.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastData }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastData, decorators: [{ type: Injectable }] }); /** * Default configuration for all toasts and toasta container */ class ToastaConfig { constructor() { // Maximum number of toasties to show at once this.limit = 5; // Whether to show the 'X' icon to close the toast this.showClose = true; // Whether to show a progress bar at the bottom of the notification this.showDuration = true; // The window position where the toast pops up this.position = 'bottom-right'; // How long (in miliseconds) the toasta shows before it's removed. Set to null/0 to turn off. this.timeout = 5000; // What theme to use this.theme = 'default'; } } ToastaConfig.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastaConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); ToastaConfig.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastaConfig }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastaConfig, decorators: [{ type: Injectable }] }); var ToastaEventType; (function (ToastaEventType) { ToastaEventType[ToastaEventType["ADD"] = 0] = "ADD"; ToastaEventType[ToastaEventType["CLEAR"] = 1] = "CLEAR"; ToastaEventType[ToastaEventType["CLEAR_ALL"] = 2] = "CLEAR_ALL"; })(ToastaEventType || (ToastaEventType = {})); class ToastaEvent { constructor(type, value) { this.type = type; this.value = value; } } function toastaServiceFactory(config) { return new ToastaService(config); } /** * Toasta service helps create different kinds of Toasts */ class ToastaService { constructor(config) { this.config = config; // Init the counter this.uniqueCounter = 0; // ToastData event emitter // private toastsEmitter: EventEmitter<ToastData> = new EventEmitter<ToastData>(); // Clear event emitter // private clearEmitter: EventEmitter<number> = new EventEmitter<number>(); this.eventSource = new Subject(); this.events = this.eventSource.asObservable(); } /** * Get list of toats */ // getToasts(): Observable<ToastData> { // return this.toastsEmitter.asObservable(); // } // getClear(): Observable<number> { // return this.clearEmitter.asObservable(); // } /** * Create Toast of a default type */ default(options) { this.add(options, 'default'); } /** * Create Toast of info type * @param options Individual toasta config overrides */ info(options) { this.add(options, 'info'); } /** * Create Toast of success type * @param options Individual toasta config overrides */ success(options) { this.add(options, 'success'); } /** * Create Toast of wait type * @param options Individual toasta config overrides */ wait(options) { this.add(options, 'wait'); } /** * Create Toast of error type * @param options Individual toasta config overrides */ error(options) { this.add(options, 'error'); } /** * Create Toast of warning type * @param options Individual toasta config overrides */ warning(options) { this.add(options, 'warning'); } // Add a new toast item add(options, type) { var _a; let toastaOptions; if (isString(options) && options !== '' || isNumber(options)) { toastaOptions = { title: options.toString() }; } else { toastaOptions = options; } if (!toastaOptions || !toastaOptions.title && !toastaOptions.msg) { throw new Error('ngx-toasta: No toast title or message specified!'); } type = type || 'default'; // Set a unique counter for an id this.uniqueCounter++; // Set the local vs global config items const showClose = this._checkConfigBooleanItem(this.config, toastaOptions, 'showClose'); // Set the local vs global config items const showDuration = this._checkConfigBooleanItem(this.config, toastaOptions, 'showDuration'); // If we have a theme set, make sure it's a valid one let theme; if (toastaOptions.theme) { theme = ToastaService.THEMES.indexOf(toastaOptions.theme) > -1 ? toastaOptions.theme : this.config.theme; } else { theme = this.config.theme; } const toast = { id: this.uniqueCounter, title: toastaOptions.title, msg: toastaOptions.msg, showClose, showDuration, type: 'toasta-type-' + type, theme: 'toasta-theme-' + theme, // If there's a timeout individually or globally, set the toast to timeout // Allows a caller to pass null/0 and override the default. Can also set the default to null/0 to turn off. timeout: toastaOptions.hasOwnProperty('timeout') ? (_a = toastaOptions.timeout) !== null && _a !== void 0 ? _a : 0 : this.config.timeout, onAdd: toastaOptions.onAdd && isFunction(toastaOptions.onAdd) ? toastaOptions.onAdd : undefined, onRemove: toastaOptions.onRemove && isFunction(toastaOptions.onRemove) ? toastaOptions.onRemove : undefined }; // Push up a new toast item // this.toastsSubscriber.next(toast); // this.toastsEmitter.next(toast); this.emitEvent(new ToastaEvent(ToastaEventType.ADD, toast)); // If we have a onAdd function, call it here if (toastaOptions.onAdd && isFunction(toastaOptions.onAdd)) { toastaOptions.onAdd.call(this, toast); } } // Clear all toasts clearAll() { // this.clearEmitter.next(null); this.emitEvent(new ToastaEvent(ToastaEventType.CLEAR_ALL)); } // Clear the specific one clear(id) { // this.clearEmitter.next(id); this.emitEvent(new ToastaEvent(ToastaEventType.CLEAR, id)); } // Checks whether the local option is set, if not, // checks the global config _checkConfigBooleanItem(config, options, property) { if (options[property] === false) { return false; } else if (!options[property]) { return config[property]; } else { return true; } } emitEvent(event) { if (this.eventSource) { // Push up a new event this.eventSource.next(event); } } } // Allowed THEMES ToastaService.THEMES = ['default', 'material', 'bootstrap']; ToastaService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastaService, deps: [{ token: ToastaConfig }], target: i0.ɵɵFactoryTarget.Injectable }); ToastaService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastaService }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastaService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: ToastaConfig }]; } }); class SafeHtmlPipe { constructor(domSanitized) { this.domSanitized = domSanitized; } transform(value, ...args) { return this.domSanitized.bypassSecurityTrustHtml(value); } } SafeHtmlPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: SafeHtmlPipe, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); SafeHtmlPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.2.2", ngImport: i0, type: SafeHtmlPipe, name: "safeHtml" }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: SafeHtmlPipe, decorators: [{ type: Pipe, args: [{ name: 'safeHtml' }] }], ctorParameters: function () { return [{ type: i1.DomSanitizer }]; } }); /** * A Toast component shows message with title and close button. */ class ToastComponent { constructor() { this.progressPercent = 0; this.startTime = performance.now(); this.closeToastEvent = new EventEmitter(); } ngAfterViewInit() { if (this.toast.showDuration && this.toast.timeout > 0) { this.progressInterval = window.setInterval(() => { this.progressPercent = (100 - ((performance.now() - this.startTime) / this.toast.timeout * 100)); // Descending progress if (this.progressPercent <= 0) { clearInterval(this.progressInterval); } }, 16.7); // 60 fps } } /** * Event handler invokes when user clicks on close button. * This method emit new event into ToastaContainer to close it. */ close($event) { $event.preventDefault(); this.closeToastEvent.next(this.toast); if (this.progressInterval) { clearInterval(this.progressInterval); } } } ToastComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); ToastComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ToastComponent, selector: "ngx-toast", inputs: { toast: "toast" }, outputs: { closeToastEvent: "closeToast" }, ngImport: i0, template: ` <div class="toast" [ngClass]="[toast.type, toast.theme]"> <div *ngIf="toast.showClose" class="close-button" (click)="close($event)"></div> <div *ngIf="toast.title || toast.msg" class="toast-text"> <span *ngIf="toast.title" class="toast-title" [innerHTML]="toast.title | safeHtml"></span> <br *ngIf="toast.title && toast.msg" /> <span *ngIf="toast.msg" class="toast-msg" [innerHtml]="toast.msg | safeHtml"></span> </div> <div class="durationbackground" *ngIf="toast.showDuration && toast.timeout > 0"> <div class="durationbar" [style.width.%]="progressPercent"> </div> </div> </div>`, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-toast', template: ` <div class="toast" [ngClass]="[toast.type, toast.theme]"> <div *ngIf="toast.showClose" class="close-button" (click)="close($event)"></div> <div *ngIf="toast.title || toast.msg" class="toast-text"> <span *ngIf="toast.title" class="toast-title" [innerHTML]="toast.title | safeHtml"></span> <br *ngIf="toast.title && toast.msg" /> <span *ngIf="toast.msg" class="toast-msg" [innerHtml]="toast.msg | safeHtml"></span> </div> <div class="durationbackground" *ngIf="toast.showDuration && toast.timeout > 0"> <div class="durationbar" [style.width.%]="progressPercent"> </div> </div> </div>` }] }], propDecorators: { toast: [{ type: Input }], closeToastEvent: [{ type: Output, args: ['closeToast'] }] } }); /** * Toasta is container for Toast components */ class ToastaComponent { // The window position where the toast pops up. Possible values: // - bottom-right (default value from ToastConfig) // - bottom-left // - bottom-center // - bottom-fullwidth // - top-right // - top-left // - top-center // - top-fullwidth // - center-center set position(value) { if (value) { let notFound = true; for (let i = 0; i < ToastaComponent.POSITIONS.length; i++) { if (ToastaComponent.POSITIONS[i] === value) { notFound = false; break; } } if (notFound) { // Position was wrong - clear it here to use the one from config. value = this.config.position; } } else { value = this.config.position; } this._position = 'toasta-position-' + value; } get position() { return this._position; } constructor(config, toastaService) { this.config = config; this.toastaService = toastaService; this._position = ''; // The storage for toasts. this.toasts = []; // Initialise position this.position = ''; } /** * `ngOnInit` is called right after the directive's data-bound properties have been checked for the * first time, and before any of its children have been checked. It is invoked only once when the * directive is instantiated. */ ngOnInit() { // We listen events from our service this.toastaService.events.subscribe((event) => { if (event.type === ToastaEventType.ADD) { // Add the new one const toast = event.value; this.add(toast); } else if (event.type === ToastaEventType.CLEAR) { // Clear the one by number const id = event.value; this.clear(id); } else if (event.type === ToastaEventType.CLEAR_ALL) { // Lets clear all toasts this.clearAll(); } }); } /** * Event listener of 'closeToast' event comes from ToastaComponent. * This method removes ToastComponent assosiated with this Toast. */ closeToast(toast) { this.clear(toast.id); } /** * Add new Toast */ add(toast) { // If we've gone over our limit, remove the earliest // one from the array if (this.config.limit && this.toasts.length >= this.config.limit) { this.toasts.shift(); } // Add toasta to array this.toasts.push(toast); // // If there's a timeout individually or globally, // set the toast to timeout if (+toast.timeout) { this._setTimeout(toast); } } /** * Clear individual toast by id * @param id is unique identifier of Toast */ clear(id) { if (id) { this.toasts.forEach((value, key) => { if (value.id === id) { if (value.onRemove && isFunction(value.onRemove)) { value.onRemove.call(this, value); } this.toasts.splice(key, 1); } }); } else { throw new Error('Please provide id of Toast to close'); } } /** * Clear all toasts */ clearAll() { this.toasts.forEach((value, key) => { if (value.onRemove && isFunction(value.onRemove)) { value.onRemove.call(this, value); } }); this.toasts = []; } /** * Custom setTimeout function for specific setTimeouts on individual toasts. */ _setTimeout(toast) { window.setTimeout(() => { this.clear(toast.id); }, toast.timeout); } } /** * Set of constants defines position of Toasta on the page. */ ToastaComponent.POSITIONS = ['bottom-right', 'bottom-left', 'bottom-center', 'bottom-fullwidth', 'top-right', 'top-left', 'top-center', 'top-fullwidth', 'center-center']; ToastaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastaComponent, deps: [{ token: ToastaConfig }, { token: ToastaService }], target: i0.ɵɵFactoryTarget.Component }); ToastaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ToastaComponent, selector: "ngx-toasta", inputs: { position: "position" }, ngImport: i0, template: ` <div id="toasta" [ngClass]="[position]"> <ngx-toast *ngFor="let toast of toasts" [toast]="toast" (closeToast)="closeToast(toast)"></ngx-toast> </div>`, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: ToastComponent, selector: "ngx-toast", inputs: ["toast"], outputs: ["closeToast"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastaComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-toasta', template: ` <div id="toasta" [ngClass]="[position]"> <ngx-toast *ngFor="let toast of toasts" [toast]="toast" (closeToast)="closeToast(toast)"></ngx-toast> </div>` }] }], ctorParameters: function () { return [{ type: ToastaConfig }, { type: ToastaService }]; }, propDecorators: { position: [{ type: Input }] } }); let providers = [ ToastaConfig, { provide: ToastaService, useFactory: toastaServiceFactory, deps: [ToastaConfig] } ]; class ToastaModule { static forRoot() { return { ngModule: ToastaModule, providers }; } } ToastaModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastaModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); ToastaModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.2", ngImport: i0, type: ToastaModule, declarations: [ToastComponent, ToastaComponent, SafeHtmlPipe], imports: [CommonModule], exports: [ToastComponent, ToastaComponent] }); ToastaModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastaModule, providers: providers, imports: [CommonModule] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ToastaModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule], declarations: [ToastComponent, ToastaComponent, SafeHtmlPipe], exports: [ToastComponent, ToastaComponent], providers }] }] }); /* * Public API Surface of ngx-toasta */ /** * Generated bundle index. Do not edit. */ export { SafeHtmlPipe, ToastComponent, ToastData, ToastOptions, ToastaComponent, ToastaConfig, ToastaEvent, ToastaEventType, ToastaModule, ToastaService, providers, toastaServiceFactory }; //# sourceMappingURL=ngx-toasta.mjs.map