UNPKG

ngx-toastr

Version:

<div align="center"> <img src="https://raw.githubusercontent.com/scttcper/ngx-toastr/master/misc/documentation-assets/ngx-toastr-example.png" width="300" alt="Angular Toastr"> <br> <h1>ngx-toastr</h1> <br> <a href="https://www.npmjs.org/package/

958 lines (939 loc) 42.2 kB
import * as i0 from '@angular/core'; import { inject, ElementRef, Directive, InjectionToken, createComponent, Injectable, ApplicationRef, Injector, NgZone, SecurityContext, signal, computed, linkedSignal, ChangeDetectionStrategy, Component, makeEnvironmentProviders, NgModule } from '@angular/core'; import { Subject } from 'rxjs'; import { DomSanitizer } from '@angular/platform-browser'; import { DOCUMENT } from '@angular/common'; class ToastContainerDirective { el = inject(ElementRef); getContainerElement() { return this.el.nativeElement; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastContainerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: ToastContainerDirective, isStandalone: true, selector: "[toastContainer]", exportAs: ["toastContainer"], ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastContainerDirective, decorators: [{ type: Directive, args: [{ selector: '[toastContainer]', exportAs: 'toastContainer', standalone: true, }] }] }); /** * Everything a toast needs to launch */ class ToastPackage { toastId; config; message; title; toastType; toastRef; _onTap = new Subject(); _onAction = new Subject(); constructor(toastId, config, message, title, toastType, toastRef) { this.toastId = toastId; this.config = config; this.message = message; this.title = title; this.toastType = toastType; this.toastRef = toastRef; this.toastRef.afterClosed().subscribe(() => { this._onAction.complete(); this._onTap.complete(); }); } /** Fired on click */ triggerTap() { this._onTap.next(); if (this.config.tapToDismiss) { this._onTap.complete(); } } onTap() { return this._onTap.asObservable(); } /** available for use in custom toast */ triggerAction(action) { this._onAction.next(action); } onAction() { return this._onAction.asObservable(); } } const DefaultNoComponentGlobalConfig = { maxOpened: 0, autoDismiss: false, newestOnTop: true, preventDuplicates: false, countDuplicates: false, resetTimeoutOnDuplicate: false, includeTitleDuplicates: false, iconClasses: { error: 'toast-error', info: 'toast-info', success: 'toast-success', warning: 'toast-warning', }, // Individual closeButton: false, disableTimeOut: false, timeOut: 5000, extendedTimeOut: 1000, enableHtml: false, progressBar: false, toastClass: 'ngx-toastr', positionClass: 'toast-top-right', titleClass: 'toast-title', messageClass: 'toast-message', easing: 'ease-in', easeTime: 300, tapToDismiss: true, onActivateTick: false, progressAnimation: 'decreasing', }; const TOAST_CONFIG = new InjectionToken('ToastConfig'); /** * A `ComponentPortal` is a portal that instantiates some Component upon attachment. */ class ComponentPortal { _attachedHost; /** The type of the component that will be instantiated for attachment. */ component; /** * [Optional] Where the attached component should live in Angular's *logical* component tree. * This is different from where the component *renders*, which is determined by the PortalHost. * The origin necessary when the host is outside of the Angular application context. */ viewContainerRef; /** Injector used for the instantiation of the component. */ injector; constructor(component, injector) { this.component = component; this.injector = injector; } /** Attach this portal to a host. */ attach(host, newestOnTop) { this._attachedHost = host; return host.attach(this, newestOnTop); } /** Detach this portal from its host */ detach() { const host = this._attachedHost; if (host) { this._attachedHost = undefined; return host.detach(); } } /** Whether this portal is attached to a host. */ get isAttached() { return this._attachedHost != null; } /** * Sets the PortalHost reference without performing `attach()`. This is used directly by * the PortalHost when it is performing an `attach()` or `detach()`. */ setAttachedHost(host) { this._attachedHost = host; } } /** * Partial implementation of PortalHost that only deals with attaching a * ComponentPortal */ class BasePortalHost { /** The portal currently attached to the host. */ _attachedPortal; /** A function that will permanently dispose this host. */ _disposeFn; attach(portal, newestOnTop) { this._attachedPortal = portal; return this.attachComponentPortal(portal, newestOnTop); } detach() { if (this._attachedPortal) { this._attachedPortal.setAttachedHost(); } this._attachedPortal = undefined; if (this._disposeFn) { this._disposeFn(); this._disposeFn = undefined; } } setDisposeFn(fn) { this._disposeFn = fn; } } /** * A PortalHost for attaching portals to an arbitrary DOM element outside of the Angular * application context. * * This is the only part of the portal core that directly touches the DOM. */ class DomPortalHost extends BasePortalHost { _hostDomElement; _appRef; constructor(_hostDomElement, _appRef) { super(); this._hostDomElement = _hostDomElement; this._appRef = _appRef; } /** * Attach the given ComponentPortal to DOM element using the ComponentFactoryResolver. * @param portal Portal to be attached */ attachComponentPortal(portal, newestOnTop) { // If the portal specifies a ViewContainerRef, we will use that as the attachment point // for the component (in terms of Angular's component tree, not rendering). // When the ViewContainerRef is missing, we use the factory to create the component directly // and then manually attach the ChangeDetector for that component to the application (which // happens automatically when using a ViewContainer). const componentRef = createComponent(portal.component, { environmentInjector: this._appRef.injector, elementInjector: portal.injector, }); // When creating a component outside of a ViewContainer, we need to manually register // its ChangeDetector with the application. This API is unfortunately not yet published // in Angular core. The change detector must also be deregistered when the component // is destroyed to prevent memory leaks. this._appRef.attachView(componentRef.hostView); this.setDisposeFn(() => { this._appRef.detachView(componentRef.hostView); componentRef.destroy(); }); // At this point the component has been instantiated, so we move it to the location in the DOM // where we want it to be rendered. if (newestOnTop) { this._hostDomElement.insertBefore(this._getComponentRootNode(componentRef), this._hostDomElement.firstChild); } else { this._hostDomElement.appendChild(this._getComponentRootNode(componentRef)); } return componentRef; } /** Gets the root HTMLElement for an instantiated component. */ _getComponentRootNode(componentRef) { return componentRef.hostView.rootNodes[0]; } } /** Container inside which all toasts will render. */ class OverlayContainer { _document = inject(DOCUMENT); _containerElement; ngOnDestroy() { if (this._containerElement && this._containerElement.parentNode) { this._containerElement.parentNode.removeChild(this._containerElement); } } /** * This method returns the overlay container element. It will lazily * create the element the first time it is called to facilitate using * the container in non-browser environments. * @returns the container element */ getContainerElement() { if (!this._containerElement) { this._createContainer(); } return this._containerElement; } /** * Create the overlay container element, which is simply a div * with the 'cdk-overlay-container' class on the document body * and 'aria-live="polite"' */ _createContainer() { const container = this._document.createElement('div'); container.classList.add('overlay-container'); container.setAttribute('aria-live', 'polite'); this._document.body.appendChild(container); this._containerElement = container; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: OverlayContainer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: OverlayContainer, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: OverlayContainer, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); /** * Reference to an overlay that has been created with the Overlay service. * Used to manipulate or dispose of said overlay. */ class OverlayRef { _portalHost; constructor(_portalHost) { this._portalHost = _portalHost; } attach(portal, newestOnTop = true) { return this._portalHost.attach(portal, newestOnTop); } /** * Detaches an overlay from a portal. * @returns Resolves when the overlay has been detached. */ detach() { return this._portalHost.detach(); } } /** * Service to create Overlays. Overlays are dynamically added pieces of floating UI, meant to be * used as a low-level building building block for other components. Dialogs, tooltips, menus, * selects, etc. can all be built using overlays. The service should primarily be used by authors * of re-usable components rather than developers building end-user applications. * * An overlay *is* a PortalHost, so any kind of Portal can be loaded into one. */ class Overlay { _overlayContainer = inject(OverlayContainer); _appRef = inject(ApplicationRef); _document = inject(DOCUMENT); // Namespace panes by overlay container _paneElements = new Map(); /** * Creates an overlay. * @returns A reference to the created overlay. */ create(positionClass, overlayContainer) { // get existing pane if possible return this._createOverlayRef(this.getPaneElement(positionClass, overlayContainer)); } getPaneElement(positionClass = '', overlayContainer) { if (!this._paneElements.get(overlayContainer)) { this._paneElements.set(overlayContainer, {}); } if (!this._paneElements.get(overlayContainer)[positionClass]) { this._paneElements.get(overlayContainer)[positionClass] = this._createPaneElement(positionClass, overlayContainer); } return this._paneElements.get(overlayContainer)[positionClass]; } /** * Creates the DOM element for an overlay and appends it to the overlay container. * @returns Newly-created pane element */ _createPaneElement(positionClass, overlayContainer) { const pane = this._document.createElement('div'); pane.id = 'toast-container'; pane.classList.add(positionClass); pane.classList.add('toast-container'); if (!overlayContainer) { this._overlayContainer.getContainerElement().appendChild(pane); } else { overlayContainer.getContainerElement().appendChild(pane); } return pane; } /** * Create a DomPortalHost into which the overlay content can be loaded. * @param pane The DOM element to turn into a portal host. * @returns A portal host for the given DOM element. */ _createPortalHost(pane) { return new DomPortalHost(pane, this._appRef); } /** * Creates an OverlayRef for an overlay in the given DOM element. * @param pane DOM element for the overlay */ _createOverlayRef(pane) { return new OverlayRef(this._createPortalHost(pane)); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: Overlay, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: Overlay, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: Overlay, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); /** * Reference to a toast opened via the Toastr service. */ class ToastRef { _overlayRef; /** The instance of component opened into the toast. */ componentInstance; /** Count of duplicates of this toast */ duplicatesCount = 0; /** Subject for notifying the user that the toast has finished closing. */ _afterClosed = new Subject(); /** triggered when toast is activated */ _activate = new Subject(); /** notifies the toast that it should close before the timeout */ _manualClose = new Subject(); /** notifies the toast that it should reset the timeouts */ _resetTimeout = new Subject(); /** notifies the toast that it should count a duplicate toast */ _countDuplicate = new Subject(); constructor(_overlayRef) { this._overlayRef = _overlayRef; } manualClose() { this._manualClose.next(); this._manualClose.complete(); } manualClosed() { return this._manualClose.asObservable(); } timeoutReset() { return this._resetTimeout.asObservable(); } countDuplicate() { return this._countDuplicate.asObservable(); } /** * Close the toast. */ close() { this._overlayRef.detach(); this._afterClosed.next(); this._manualClose.next(); this._afterClosed.complete(); this._manualClose.complete(); this._activate.complete(); this._resetTimeout.complete(); this._countDuplicate.complete(); } /** Gets an observable that is notified when the toast is finished closing. */ afterClosed() { return this._afterClosed.asObservable(); } isInactive() { return this._activate.closed; } activate() { this._activate.next(); this._activate.complete(); } /** Gets an observable that is notified when the toast has started opening. */ afterActivate() { return this._activate.asObservable(); } /** Reset the toast timouts and count duplicates */ onDuplicate(resetTimeout, countDuplicate) { if (resetTimeout) { this._resetTimeout.next(); } if (countDuplicate) { this._countDuplicate.next(++this.duplicatesCount); } } } class ToastrService { overlay = inject(Overlay); _injector = inject(Injector); sanitizer = inject(DomSanitizer); ngZone = inject(NgZone); toastrConfig; currentlyActive = 0; toasts = []; overlayContainer; previousToastMessage; index = 0; constructor() { const token = inject(TOAST_CONFIG); this.toastrConfig = { ...token.default, ...token.config, }; if (token.config.iconClasses) { this.toastrConfig.iconClasses = { ...token.default.iconClasses, ...token.config.iconClasses, }; } } /** show toast */ show(message, title, override = {}, type = '') { return this._preBuildNotification(type, message, title, this.applyConfig(override)); } /** show successful toast */ success(message, title, override = {}) { const type = this.toastrConfig.iconClasses.success || ''; return this._preBuildNotification(type, message, title, this.applyConfig(override)); } /** show error toast */ error(message, title, override = {}) { const type = this.toastrConfig.iconClasses.error || ''; return this._preBuildNotification(type, message, title, this.applyConfig(override)); } /** show info toast */ info(message, title, override = {}) { const type = this.toastrConfig.iconClasses.info || ''; return this._preBuildNotification(type, message, title, this.applyConfig(override)); } /** show warning toast */ warning(message, title, override = {}) { const type = this.toastrConfig.iconClasses.warning || ''; return this._preBuildNotification(type, message, title, this.applyConfig(override)); } /** * Remove all or a single toast by id */ clear(toastId) { // Call every toastRef manualClose function for (const toast of this.toasts) { if (toastId !== undefined) { if (toast.toastId === toastId) { toast.toastRef.manualClose(); return; } } else { toast.toastRef.manualClose(); } } } /** * Remove and destroy a single toast by id */ remove(toastId) { const found = this._findToast(toastId); if (!found) { return false; } found.activeToast.toastRef.close(); this.toasts.splice(found.index, 1); this.currentlyActive = this.currentlyActive - 1; if (!this.toastrConfig.maxOpened || !this.toasts.length) { return false; } if (this.currentlyActive < this.toastrConfig.maxOpened && this.toasts[this.currentlyActive]) { const p = this.toasts[this.currentlyActive].toastRef; if (!p.isInactive()) { this.currentlyActive = this.currentlyActive + 1; p.activate(); } } return true; } /** * Determines if toast message is already shown */ findDuplicate(title = '', message = '', resetOnDuplicate, countDuplicates) { const { includeTitleDuplicates } = this.toastrConfig; for (const toast of this.toasts) { const hasDuplicateTitle = includeTitleDuplicates && toast.title === title; if ((!includeTitleDuplicates || hasDuplicateTitle) && toast.message === message) { toast.toastRef.onDuplicate(resetOnDuplicate, countDuplicates); return toast; } } return null; } /** create a clone of global config and apply individual settings */ applyConfig(override = {}) { return { ...this.toastrConfig, ...override }; } /** * Find toast object by id */ _findToast(toastId) { for (let i = 0; i < this.toasts.length; i++) { if (this.toasts[i].toastId === toastId) { return { index: i, activeToast: this.toasts[i] }; } } return null; } /** * Determines the need to run inside angular's zone then builds the toast */ _preBuildNotification(toastType, message, title, config) { if (config.onActivateTick) { return this.ngZone.run(() => this._buildNotification(toastType, message, title, config)); } return this._buildNotification(toastType, message, title, config); } /** * Creates and attaches toast data to component * returns the active toast, or in case preventDuplicates is enabled the original/non-duplicate active toast. */ _buildNotification(toastType, message, title, config) { if (!config.toastComponent) { throw new Error('toastComponent required'); } // max opened and auto dismiss = true // if timeout = 0 resetting it would result in setting this.hideTime = Date.now(). Hence, we only want to reset timeout if there is // a timeout at all const duplicate = this.findDuplicate(title, message, this.toastrConfig.resetTimeoutOnDuplicate && config.timeOut > 0, this.toastrConfig.countDuplicates); if (((this.toastrConfig.includeTitleDuplicates && title) || message) && this.toastrConfig.preventDuplicates && duplicate !== null) { return duplicate; } this.previousToastMessage = message; let keepInactive = false; if (this.toastrConfig.maxOpened && this.currentlyActive >= this.toastrConfig.maxOpened) { keepInactive = true; if (this.toastrConfig.autoDismiss) { this.clear(this.toasts[0].toastId); } } const overlayRef = this.overlay.create(config.positionClass, this.overlayContainer); this.index = this.index + 1; let sanitizedMessage = message; if (message && config.enableHtml) { sanitizedMessage = this.sanitizer.sanitize(SecurityContext.HTML, message); } const toastRef = new ToastRef(overlayRef); const toastPackage = new ToastPackage(this.index, config, sanitizedMessage, title, toastType, toastRef); /** New injector that contains an instance of `ToastPackage`. */ const providers = [{ provide: ToastPackage, useValue: toastPackage }]; const toastInjector = Injector.create({ providers, parent: this._injector }); const component = new ComponentPortal(config.toastComponent, toastInjector); const portal = overlayRef.attach(component, config.newestOnTop); toastRef.componentInstance = portal.instance; const ins = { toastId: this.index, title: title || '', message: message || '', toastRef, onShown: toastRef.afterActivate(), onHidden: toastRef.afterClosed(), onTap: toastPackage.onTap(), onAction: toastPackage.onAction(), portal, }; if (!keepInactive) { this.currentlyActive = this.currentlyActive + 1; setTimeout(() => { ins.toastRef.activate(); }); } this.toasts.push(ins); return ins; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastrService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastrService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastrService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [] }); class TimeoutsService { ngZone = inject(NgZone); setInterval(func, timeout) { if (this.ngZone) { return this.ngZone.runOutsideAngular(() => window.setInterval(() => this.runInsideAngular(func), timeout)); } else { return window.setInterval(() => func(), timeout); } } setTimeout(func, timeout) { if (this.ngZone) { return this.ngZone.runOutsideAngular(() => window.setTimeout(() => this.runInsideAngular(func), timeout)); } else { return window.setTimeout(() => func(), timeout); } } runInsideAngular(func) { if (this.ngZone) { this.ngZone.run(() => func()); } else { func(); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TimeoutsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TimeoutsService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TimeoutsService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class ToastBase { toastPackage = inject(ToastPackage); toastrService = inject(ToastrService); appRef = inject(ApplicationRef); timeoutsService = inject(TimeoutsService); duplicatesCount; hideTime; /** width of progress bar */ width = signal(-1, ...(ngDevMode ? [{ debugName: "width" }] : [])); state = signal('inactive', ...(ngDevMode ? [{ debugName: "state" }] : [])); /** hides component when waiting to be displayed */ displayStyle = computed(() => (this.state() === 'inactive' ? 'none' : undefined), ...(ngDevMode ? [{ debugName: "displayStyle" }] : [])); message = computed(() => this.toastPackage.message, ...(ngDevMode ? [{ debugName: "message" }] : [])); title = computed(() => this.toastPackage.title, ...(ngDevMode ? [{ debugName: "title" }] : [])); options = linkedSignal(() => this.toastPackage.config, ...(ngDevMode ? [{ debugName: "options" }] : [])); originalTimeout = computed(() => this.toastPackage.config.timeOut, ...(ngDevMode ? [{ debugName: "originalTimeout" }] : [])); toastClasses = computed(() => `${this.toastPackage.toastType} ${this.toastPackage.config.toastClass}`, ...(ngDevMode ? [{ debugName: "toastClasses" }] : [])); timeout; intervalId; afterActivateSubscription; manualClosedSubscription; timeoutResetSubscription; countDuplicateSubscription; constructor() { this.afterActivateSubscription = this.toastPackage.toastRef.afterActivate().subscribe(() => { this.activateToast(); }); this.manualClosedSubscription = this.toastPackage.toastRef.manualClosed().subscribe(() => { this.remove(); }); this.timeoutResetSubscription = this.toastPackage.toastRef.timeoutReset().subscribe(() => { this.resetTimeout(); }); this.countDuplicateSubscription = this.toastPackage.toastRef .countDuplicate() .subscribe(count => { this.duplicatesCount = count; }); } ngOnDestroy() { this.afterActivateSubscription.unsubscribe(); this.manualClosedSubscription.unsubscribe(); this.timeoutResetSubscription.unsubscribe(); this.countDuplicateSubscription.unsubscribe(); clearInterval(this.intervalId); clearTimeout(this.timeout); } /** * activates toast and sets timeout */ activateToast() { const options = this.options(); this.state.set('active'); if (!(options.disableTimeOut === true || options.disableTimeOut === 'timeOut') && options.timeOut) { this.timeout = this.timeoutsService.setTimeout(() => this.remove(), options.timeOut); this.hideTime = new Date().getTime() + options.timeOut; if (options.progressBar) { this.intervalId = this.timeoutsService.setInterval(() => this.updateProgress(), 10); } } } /** * updates progress bar width */ updateProgress() { const options = this.options(); if (this.width() === 0 || this.width() === 100 || !options.timeOut) { return; } const now = new Date().getTime(); const remaining = this.hideTime - now; this.width.set((remaining / options.timeOut) * 100); if (options.progressAnimation === 'increasing') { this.width.update(width => 100 - width); } if (this.width() <= 0) { this.width.set(0); } if (this.width() >= 100) { this.width.set(100); } } resetTimeout() { const options = this.options(); clearTimeout(this.timeout); clearInterval(this.intervalId); this.state.set('active'); this.options.update(options => ({ ...options, timeOut: this.originalTimeout() })); this.timeout = this.timeoutsService.setTimeout(() => this.remove(), this.originalTimeout()); this.hideTime = new Date().getTime() + (this.originalTimeout() || 0); this.width.set(-1); if (options.progressBar) this.intervalId = this.timeoutsService.setInterval(() => this.updateProgress(), 10); } /** * tells toastrService to remove this toast after animation time */ remove() { if (this.state() === 'removed') return; clearTimeout(this.timeout); this.state.set('removed'); this.timeout = this.timeoutsService.setTimeout(() => this.toastrService.remove(this.toastPackage.toastId)); } tapToast() { if (this.state() === 'removed') return; this.toastPackage.triggerTap(); if (this.options().tapToDismiss) { this.remove(); } } stickAround() { if (this.state() === 'removed') return; if (this.options().disableTimeOut !== 'extendedTimeOut') { clearTimeout(this.timeout); this.options.update(options => ({ ...options, timeOut: 0 })); this.hideTime = 0; // disable progressBar clearInterval(this.intervalId); this.width.set(0); } } delayedHideToast() { const options = this.options(); if (options.disableTimeOut === true || options.disableTimeOut === 'extendedTimeOut' || options.extendedTimeOut === 0 || this.state() === 'removed') { return; } const extendedTimeOut = options.extendedTimeOut; this.timeout = this.timeoutsService.setTimeout(() => this.remove(), extendedTimeOut); this.options.update(options => ({ ...options, timeOut: extendedTimeOut })); this.hideTime = new Date().getTime() + (extendedTimeOut || 0); this.width.set(-1); if (options.progressBar) { this.intervalId = this.timeoutsService.setInterval(() => this.updateProgress(), 10); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastBase, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: ToastBase, isStandalone: true, selector: "[toast-component]", host: { listeners: { "mouseenter": "stickAround()", "mouseleave": "delayedHideToast()", "click": "tapToast()" }, properties: { "class": "toastClasses()", "style.display": "displayStyle()" } }, ngImport: i0, template: "@let _options = options();\n\n@if (_options.closeButton) {\n <button (click)=\"remove()\" type=\"button\" class=\"toast-close-button\" aria-label=\"Close\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n}\n\n@if (title()) {\n <div [class]=\"_options.titleClass\" [attr.aria-label]=\"title()\">\n {{ title() }}\n\n @if (duplicatesCount) {\n <ng-container>[{{ duplicatesCount + 1 }}]</ng-container>\n }\n </div>\n}\n\n@if (message()) {\n @if (_options.enableHtml) {\n <div role=\"alert\" [class]=\"_options.messageClass\" [innerHTML]=\"message()\"></div>\n } @else {\n <div role=\"alert\" [class]=\"_options.messageClass\" [attr.aria-label]=\"message()\">\n {{ message() }}\n </div>\n }\n}\n\n@if (_options.progressBar) {\n <div>\n <div class=\"toast-progress\" [style.width]=\"width() + '%'\"></div>\n </div>\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastBase, decorators: [{ type: Component, args: [{ selector: '[toast-component]', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: { '[class]': 'toastClasses()', '[style.display]': 'displayStyle()', '(mouseenter)': 'stickAround()', '(mouseleave)': 'delayedHideToast()', '(click)': 'tapToast()', }, template: "@let _options = options();\n\n@if (_options.closeButton) {\n <button (click)=\"remove()\" type=\"button\" class=\"toast-close-button\" aria-label=\"Close\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n}\n\n@if (title()) {\n <div [class]=\"_options.titleClass\" [attr.aria-label]=\"title()\">\n {{ title() }}\n\n @if (duplicatesCount) {\n <ng-container>[{{ duplicatesCount + 1 }}]</ng-container>\n }\n </div>\n}\n\n@if (message()) {\n @if (_options.enableHtml) {\n <div role=\"alert\" [class]=\"_options.messageClass\" [innerHTML]=\"message()\"></div>\n } @else {\n <div role=\"alert\" [class]=\"_options.messageClass\" [attr.aria-label]=\"message()\">\n {{ message() }}\n </div>\n }\n}\n\n@if (_options.progressBar) {\n <div>\n <div class=\"toast-progress\" [style.width]=\"width() + '%'\"></div>\n </div>\n}\n" }] }], ctorParameters: () => [] }); class Toast extends ToastBase { params = { easeTime: this.toastPackage.config.easeTime, easing: 'ease-in' }; elementRef = inject(ElementRef); remove() { if (this.state() === 'removed') return; clearTimeout(this.timeout); this.state.set('removed'); this.elementRef.nativeElement.classList.add('toast-out'); this.timeout = this.timeoutsService.setTimeout(() => this.toastrService.remove(this.toastPackage.toastId), +this.params.easeTime); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: Toast, deps: null, target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: Toast, isStandalone: true, selector: "[toast-component]", host: { attributes: { "animate.enter": "toast-in" }, properties: { "style.--animation-easing": "params.easing", "style.--animation-duration": "params.easeTime + \"ms\"" } }, usesInheritance: true, ngImport: i0, template: "@let _options = options();\n\n@if (_options.closeButton) {\n <button (click)=\"remove()\" type=\"button\" class=\"toast-close-button\" aria-label=\"Close\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n}\n\n@if (title()) {\n <div [class]=\"_options.titleClass\" [attr.aria-label]=\"title()\">\n {{ title() }}\n\n @if (duplicatesCount) {\n <ng-container>[{{ duplicatesCount + 1 }}]</ng-container>\n }\n </div>\n}\n\n@if (message()) {\n @if (_options.enableHtml) {\n <div role=\"alert\" [class]=\"_options.messageClass\" [innerHTML]=\"message()\"></div>\n } @else {\n <div role=\"alert\" [class]=\"_options.messageClass\" [attr.aria-label]=\"message()\">\n {{ message() }}\n </div>\n }\n}\n\n@if (_options.progressBar) {\n <div>\n <div class=\"toast-progress\" [style.width]=\"width() + '%'\"></div>\n </div>\n}\n", styles: [":host.toast-in{animation:toast-animation var(--animation-duration) var(--animation-easing)}:host.toast-out{animation:toast-animation var(--animation-duration) var(--animation-easing) reverse forwards}@keyframes toast-animation{0%{opacity:0}to{opacity:1}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: Toast, decorators: [{ type: Component, args: [{ selector: '[toast-component]', host: { '[style.--animation-easing]': 'params.easing', '[style.--animation-duration]': 'params.easeTime + "ms"', 'animate.enter': 'toast-in', }, standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let _options = options();\n\n@if (_options.closeButton) {\n <button (click)=\"remove()\" type=\"button\" class=\"toast-close-button\" aria-label=\"Close\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n}\n\n@if (title()) {\n <div [class]=\"_options.titleClass\" [attr.aria-label]=\"title()\">\n {{ title() }}\n\n @if (duplicatesCount) {\n <ng-container>[{{ duplicatesCount + 1 }}]</ng-container>\n }\n </div>\n}\n\n@if (message()) {\n @if (_options.enableHtml) {\n <div role=\"alert\" [class]=\"_options.messageClass\" [innerHTML]=\"message()\"></div>\n } @else {\n <div role=\"alert\" [class]=\"_options.messageClass\" [attr.aria-label]=\"message()\">\n {{ message() }}\n </div>\n }\n}\n\n@if (_options.progressBar) {\n <div>\n <div class=\"toast-progress\" [style.width]=\"width() + '%'\"></div>\n </div>\n}\n", styles: [":host.toast-in{animation:toast-animation var(--animation-duration) var(--animation-easing)}:host.toast-out{animation:toast-animation var(--animation-duration) var(--animation-easing) reverse forwards}@keyframes toast-animation{0%{opacity:0}to{opacity:1}}\n"] }] }] }); const DefaultGlobalConfig = { ...DefaultNoComponentGlobalConfig, toastComponent: Toast, }; /** * @description * Provides the `TOAST_CONFIG` token with the given config. * * @param config The config to configure toastr. * @returns The environment providers. * * @example * ```ts * import { provideToastr } from 'ngx-toastr'; * * bootstrap(AppComponent, { * providers: [ * provideToastr({ * timeOut: 2000, * positionClass: 'toast-top-right', * }), * ], * }) */ const provideToastr = (config = {}) => { const providers = [ { provide: TOAST_CONFIG, useValue: { default: DefaultGlobalConfig, config, }, }, ]; return makeEnvironmentProviders(providers); }; class ToastrModule { static forRoot(config = {}) { return { ngModule: ToastrModule, providers: [provideToastr(config)], }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastrModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.0", ngImport: i0, type: ToastrModule, imports: [Toast], exports: [Toast] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastrModule }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastrModule, decorators: [{ type: NgModule, args: [{ imports: [Toast], exports: [Toast], }] }] }); class ToastrComponentlessModule { static forRoot(config = {}) { return { ngModule: ToastrModule, providers: [ { provide: TOAST_CONFIG, useValue: { default: DefaultNoComponentGlobalConfig, config, }, }, ], }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastrComponentlessModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.0", ngImport: i0, type: ToastrComponentlessModule }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastrComponentlessModule }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastrComponentlessModule, decorators: [{ type: NgModule, args: [{}] }] }); const DefaultNoAnimationsGlobalConfig = { ...DefaultNoComponentGlobalConfig, toastComponent: ToastBase, }; class ToastNoAnimationModule { static forRoot(config = {}) { return { ngModule: ToastNoAnimationModule, providers: [ { provide: TOAST_CONFIG, useValue: { default: DefaultNoAnimationsGlobalConfig, config, }, }, ], }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastNoAnimationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.0", ngImport: i0, type: ToastNoAnimationModule, imports: [ToastBase], exports: [ToastBase] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastNoAnimationModule }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ToastNoAnimationModule, decorators: [{ type: NgModule, args: [{ imports: [ToastBase], exports: [ToastBase], }] }] }); /* * Public API Surface of ngx-toastr */ /** * Generated bundle index. Do not edit. */ export { BasePortalHost, ComponentPortal, DefaultGlobalConfig, DefaultNoAnimationsGlobalConfig, DefaultNoComponentGlobalConfig, Overlay, OverlayContainer, OverlayRef, TOAST_CONFIG, Toast, ToastContainerDirective, ToastBase as ToastNoAnimation, ToastNoAnimationModule, ToastPackage, ToastRef, ToastrComponentlessModule, ToastrModule, ToastrService, provideToastr }; //# sourceMappingURL=ngx-toastr.mjs.map