UNPKG

@progress/kendo-angular-notification

Version:

Kendo UI Notification for Angular

315 lines (312 loc) 12.7 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { Component, EventEmitter, HostBinding, Input, TemplateRef, ChangeDetectorRef, ViewChild, ViewContainerRef, ElementRef, Renderer2 } from '@angular/core'; import { NgClass, NgTemplateOutlet } from '@angular/common'; import { AnimationBuilder } from '@angular/animations'; import { take } from 'rxjs/operators'; import { validatePackage } from '@progress/kendo-licensing'; import { LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n'; import { checkOutlineIcon, exclamationCircleIcon, infoCircleIcon, xIcon, xOutlineIcon } from '@progress/kendo-svg-icons'; import { guid } from '@progress/kendo-angular-common'; import { IconWrapperComponent } from '@progress/kendo-angular-icons'; import { packageMetadata } from './package-metadata'; import { fadeAnimation, fadeCloseAnimation, slideAnimation, slideCloseAnimation } from './utils/animations'; import { LocalizedMessagesDirective } from './localization/localized-messages.directive'; import * as i0 from "@angular/core"; import * as i1 from "@angular/animations"; import * as i2 from "@progress/kendo-angular-l10n"; /** * @hidden * */ export class NotificationComponent { cdr; element; renderer; builder; localizationService; /** * @hidden */ xIcon = xIcon; contentId = `k-${guid()}`; container; closeClickSubscription; close = new EventEmitter(); templateRef; templateString; width = null; height = null; notificationLabel = 'Notification'; cssClass; hideAfter; closable; type; animation; closeTitle; /** * @hidden */ direction; get closeButtonTitle() { return this.closeTitle || this.localizationService.get('closeTitle'); } defaultHideAfter = 5000; hideTimeout; animationEnd = new EventEmitter(); dynamicRTLSubscription; rtl = false; constructor(cdr, element, renderer, builder, localizationService) { this.cdr = cdr; this.element = element; this.renderer = renderer; this.builder = builder; this.localizationService = localizationService; validatePackage(packageMetadata); this.dynamicRTLSubscription = localizationService.changes.subscribe(({ rtl }) => { this.rtl = rtl; this.direction = this.rtl ? 'rtl' : 'ltr'; }); } notificationClasses() { return `${this.type ? this.typeClass() : ''} ${this.closable ? 'k-notification-closable' : ''}`; } ngOnInit() { clearTimeout(this.hideTimeout); } ngOnDestroy() { clearTimeout(this.hideTimeout); if (this.dynamicRTLSubscription) { this.dynamicRTLSubscription.unsubscribe(); } } ngAfterViewInit() { if (!this.closable && !this.animation) { this.setHideTimeout(); } if (!this.closable && this.animation) { this.animationEnd.pipe(take(1)) .subscribe(() => this.setHideTimeout()); } if (this.animation) { this.animate(this.animation); } } typeClass() { return { 'none': '', 'success': 'k-notification-success', 'warning': 'k-notification-warning', 'error': 'k-notification-error', 'info': 'k-notification-info' }[this.type.style]; } typeIconClass() { return { 'none': '', 'success': 'check-outline', 'warning': 'exclamation-circle', 'error': 'x-outline', 'info': 'info-circle' }[this.type.style]; } typeSVGIcon() { return { 'none': null, 'success': checkOutlineIcon, 'warning': exclamationCircleIcon, 'error': xOutlineIcon, 'info': infoCircleIcon }[this.type.style]; } onCloseClick() { clearTimeout(this.hideTimeout); this.hide(); } hide(customComponent) { const elementHeight = getComputedStyle(this.element.nativeElement).height; if (this.animation && elementHeight) { this.animate(this.animation, true); this.animationEnd.subscribe(() => { this.emitClose(customComponent); }); return; } this.emitClose(customComponent); } setHideTimeout() { const hideAfter = this.hideAfter || this.defaultHideAfter; this.hideTimeout = window.setTimeout(() => this.onCloseClick(), hideAfter); } emitClose(customComponent) { if (customComponent) { customComponent.destroy(); } this.close.emit(); } play(animation, animatedElement) { const factory = this.builder.build(animation); const element = this.element.nativeElement; this.renderer.addClass(element, 'k-notification-container-animating'); let player = factory.create(animatedElement); player.onDone(() => { this.renderer.removeClass(element, 'k-notification-container-animating'); this.animationEnd.emit(); if (player) { player.destroy(); player = null; } }); player.play(); } animate(animation, onclose) { const element = this.element.nativeElement; const duration = animation.duration; const height = element.offsetHeight; const generatedAnimation = animation.type === 'slide' ? this.slideAnimation(height, duration, onclose) : this.fadeAnimation(duration, onclose); this.play(generatedAnimation, element); } slideAnimation(height, duration, onclose) { return onclose ? slideCloseAnimation(height, duration) : slideAnimation(height, duration); } fadeAnimation(duration, onclose) { return onclose ? fadeCloseAnimation(duration) : fadeAnimation(duration); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NotificationComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.AnimationBuilder }, { token: i2.LocalizationService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: NotificationComponent, isStandalone: true, selector: "kendo-notification", inputs: { templateRef: "templateRef", templateString: "templateString", width: "width", height: "height", notificationLabel: "notificationLabel", cssClass: "cssClass", hideAfter: "hideAfter", closable: "closable", type: "type", animation: "animation" }, host: { properties: { "attr.dir": "this.direction" } }, providers: [ LocalizationService, { provide: L10N_PREFIX, useValue: 'kendo.notification' } ], viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: ` <ng-container kendoNotificationLocalizedMessages i18n-closeTitle="kendo.notification.closeTitle|The title of the close button" closeTitle="Close" > </ng-container> <div class="k-notification k-notification-base {{ notificationClasses() }}" [ngClass]="cssClass" [style.height.px]="height" [style.width.px]="width" role="alert" aria-live="polite" [attr.aria-describedby]="contentId" [attr.aria-label]="notificationLabel"> @if (type && type.icon && type.style !== 'none') { <kendo-icon-wrapper innerCssClass="k-notification-status" [name]="typeIconClass()" [svgIcon]="typeSVGIcon()" > </kendo-icon-wrapper> } <div [id]="contentId" class="k-notification-content"> @if (templateRef) { <ng-template [ngTemplateOutlet]="templateRef"> </ng-template> } @if (templateString) { {{ templateString }} } <ng-container #container></ng-container> </div> @if (closable) { <span class="k-notification-actions" aria-hidden="true"> <span class="k-notification-action k-notification-close-action" [attr.title]="closeButtonTitle" (click)="onCloseClick()"> <kendo-icon-wrapper name="x" [svgIcon]="xIcon"></kendo-icon-wrapper> </span> </span> } </div> `, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "[kendoNotificationLocalizedMessages]", inputs: ["closeTitle"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NotificationComponent, decorators: [{ type: Component, args: [{ selector: 'kendo-notification', template: ` <ng-container kendoNotificationLocalizedMessages i18n-closeTitle="kendo.notification.closeTitle|The title of the close button" closeTitle="Close" > </ng-container> <div class="k-notification k-notification-base {{ notificationClasses() }}" [ngClass]="cssClass" [style.height.px]="height" [style.width.px]="width" role="alert" aria-live="polite" [attr.aria-describedby]="contentId" [attr.aria-label]="notificationLabel"> @if (type && type.icon && type.style !== 'none') { <kendo-icon-wrapper innerCssClass="k-notification-status" [name]="typeIconClass()" [svgIcon]="typeSVGIcon()" > </kendo-icon-wrapper> } <div [id]="contentId" class="k-notification-content"> @if (templateRef) { <ng-template [ngTemplateOutlet]="templateRef"> </ng-template> } @if (templateString) { {{ templateString }} } <ng-container #container></ng-container> </div> @if (closable) { <span class="k-notification-actions" aria-hidden="true"> <span class="k-notification-action k-notification-close-action" [attr.title]="closeButtonTitle" (click)="onCloseClick()"> <kendo-icon-wrapper name="x" [svgIcon]="xIcon"></kendo-icon-wrapper> </span> </span> } </div> `, providers: [ LocalizationService, { provide: L10N_PREFIX, useValue: 'kendo.notification' } ], standalone: true, imports: [LocalizedMessagesDirective, NgClass, IconWrapperComponent, NgTemplateOutlet] }] }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.AnimationBuilder }, { type: i2.LocalizationService }], propDecorators: { container: [{ type: ViewChild, args: ['container', { read: ViewContainerRef, static: true }] }], templateRef: [{ type: Input }], templateString: [{ type: Input }], width: [{ type: Input }], height: [{ type: Input }], notificationLabel: [{ type: Input }], cssClass: [{ type: Input }], hideAfter: [{ type: Input }], closable: [{ type: Input }], type: [{ type: Input }], animation: [{ type: Input }], direction: [{ type: HostBinding, args: ['attr.dir'] }] } });