@progress/kendo-angular-notification
Version:
Kendo UI Notification for Angular
315 lines (312 loc) • 12.7 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* 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">
(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">
(templateRef) {
<ng-template
[ngTemplateOutlet]="templateRef">
</ng-template>
}
(templateString) {
{{ templateString }}
}
<ng-container #container></ng-container>
</div>
(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">
(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">
(templateRef) {
<ng-template
[ngTemplateOutlet]="templateRef">
</ng-template>
}
(templateString) {
{{ templateString }}
}
<ng-container #container></ng-container>
</div>
(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']
}] } });