primeng
Version:
PrimeNG is an open source UI library for Angular featuring a rich set of 80+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeB
1,011 lines (963 loc) • 41.2 kB
JavaScript
import { trigger, state, transition, style, animate, query, animateChild } from '@angular/animations';
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { Injectable, EventEmitter, inject, numberAttribute, ViewChild, Output, Input, ChangeDetectionStrategy, ViewEncapsulation, Component, booleanAttribute, ContentChildren, ContentChild, NgModule } from '@angular/core';
import { uuid, isEmpty, setAttribute } from '@primeuix/utils';
import { SharedModule, MessageService, PrimeTemplate } from 'primeng/api';
import { BaseComponent } from 'primeng/basecomponent';
import { CheckIcon, ExclamationTriangleIcon, InfoCircleIcon, TimesIcon, TimesCircleIcon } from 'primeng/icons';
import { ZIndexUtils } from 'primeng/utils';
import { BaseStyle } from 'primeng/base';
const theme = ({ dt }) => `
.p-toast {
width: ${dt('toast.width')};
white-space: pre-line;
word-break: break-word;
}
.p-toast-message {
margin: 0 0 1rem 0;
}
.p-toast-message-icon {
flex-shrink: 0;
font-size: ${dt('toast.icon.size')};
width: ${dt('toast.icon.size')};
height: ${dt('toast.icon.size')};
}
.p-toast-message-content {
display: flex;
align-items: flex-start;
padding: ${dt('toast.content.padding')};
gap: ${dt('toast.content.gap')};
}
.p-toast-message-text {
flex: 1 1 auto;
display: flex;
flex-direction: column;
gap: ${dt('toast.text.gap')};
}
.p-toast-summary {
font-weight: ${dt('toast.summary.font.weight')};
font-size: ${dt('toast.summary.font.size')};
}
.p-toast-detail {
font-weight: ${dt('toast.detail.font.weight')};
font-size: ${dt('toast.detail.font.size')};
}
.p-toast-close-button {
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
cursor: pointer;
background: transparent;
transition: background ${dt('toast.transition.duration')}, color ${dt('toast.transition.duration')}, outline-color ${dt('toast.transition.duration')}, box-shadow ${dt('toast.transition.duration')};
outline-color: transparent;
color: inherit;
width: ${dt('toast.close.button.width')};
height: ${dt('toast.close.button.height')};
border-radius: ${dt('toast.close.button.border.radius')};
margin: -25% 0 0 0;
right: -25%;
padding: 0;
border: none;
user-select: none;
}
.p-toast-close-button:dir(rtl) {
margin: -25% 0 0 auto;
left: -25%;
right: auto;
}
.p-toast-message-info,
.p-toast-message-success,
.p-toast-message-warn,
.p-toast-message-error,
.p-toast-message-secondary,
.p-toast-message-contrast {
border-width: ${dt('toast.border.width')};
border-style: solid;
backdrop-filter: blur(${dt('toast.blur')});
border-radius: ${dt('toast.border.radius')};
}
.p-toast-close-icon {
font-size: ${dt('toast.close.icon.size')};
width: ${dt('toast.close.icon.size')};
height: ${dt('toast.close.icon.size')};
}
.p-toast-close-button:focus-visible {
outline-width: ${dt('focus.ring.width')};
outline-style: ${dt('focus.ring.style')};
outline-offset: ${dt('focus.ring.offset')};
}
.p-toast-message-info {
background: ${dt('toast.info.background')};
border-color: ${dt('toast.info.border.color')};
color: ${dt('toast.info.color')};
box-shadow: ${dt('toast.info.shadow')};
}
.p-toast-message-info .p-toast-detail {
color: ${dt('toast.info.detail.color')};
}
.p-toast-message-info .p-toast-close-button:focus-visible {
outline-color: ${dt('toast.info.close.button.focus.ring.color')};
box-shadow: ${dt('toast.info.close.button.focus.ring.shadow')};
}
.p-toast-message-info .p-toast-close-button:hover {
background: ${dt('toast.info.close.button.hover.background')};
}
.p-toast-message-success {
background: ${dt('toast.success.background')};
border-color: ${dt('toast.success.border.color')};
color: ${dt('toast.success.color')};
box-shadow: ${dt('toast.success.shadow')};
}
.p-toast-message-success .p-toast-detail {
color: ${dt('toast.success.detail.color')};
}
.p-toast-message-success .p-toast-close-button:focus-visible {
outline-color: ${dt('toast.success.close.button.focus.ring.color')};
box-shadow: ${dt('toast.success.close.button.focus.ring.shadow')};
}
.p-toast-message-success .p-toast-close-button:hover {
background: ${dt('toast.success.close.button.hover.background')};
}
.p-toast-message-warn {
background: ${dt('toast.warn.background')};
border-color: ${dt('toast.warn.border.color')};
color: ${dt('toast.warn.color')};
box-shadow: ${dt('toast.warn.shadow')};
}
.p-toast-message-warn .p-toast-detail {
color: ${dt('toast.warn.detail.color')};
}
.p-toast-message-warn .p-toast-close-button:focus-visible {
outline-color: ${dt('toast.warn.close.button.focus.ring.color')};
box-shadow: ${dt('toast.warn.close.button.focus.ring.shadow')};
}
.p-toast-message-warn .p-toast-close-button:hover {
background: ${dt('toast.warn.close.button.hover.background')};
}
.p-toast-message-error {
background: ${dt('toast.error.background')};
border-color: ${dt('toast.error.border.color')};
color: ${dt('toast.error.color')};
box-shadow: ${dt('toast.error.shadow')};
}
.p-toast-message-error .p-toast-detail {
color: ${dt('toast.error.detail.color')};
}
.p-toast-message-error .p-toast-close-button:focus-visible {
outline-color: ${dt('toast.error.close.button.focus.ring.color')};
box-shadow: ${dt('toast.error.close.button.focus.ring.shadow')};
}
.p-toast-message-error .p-toast-close-button:hover {
background: ${dt('toast.error.close.button.hover.background')};
}
.p-toast-message-secondary {
background: ${dt('toast.secondary.background')};
border-color: ${dt('toast.secondary.border.color')};
color: ${dt('toast.secondary.color')};
box-shadow: ${dt('toast.secondary.shadow')};
}
.p-toast-message-secondary .p-toast-detail {
color: ${dt('toast.secondary.detail.color')};
}
.p-toast-message-secondary .p-toast-close-button:focus-visible {
outline-color: ${dt('toast.secondary.close.button.focus.ring.color')};
box-shadow: ${dt('toast.secondary.close.button.focus.ring.shadow')};
}
.p-toast-message-secondary .p-toast-close-button:hover {
background: ${dt('toast.secondary.close.button.hover.background')};
}
.p-toast-message-contrast {
background: ${dt('toast.contrast.background')};
border-color: ${dt('toast.contrast.border.color')};
color: ${dt('toast.contrast.color')};
box-shadow: ${dt('toast.contrast.shadow')};
}
.p-toast-message-contrast .p-toast-detail {
color: ${dt('toast.contrast.detail.color')};
}
.p-toast-message-contrast .p-toast-close-button:focus-visible {
outline-color: ${dt('toast.contrast.close.button.focus.ring.color')};
box-shadow: ${dt('toast.contrast.close.button.focus.ring.shadow')};
}
.p-toast-message-contrast .p-toast-close-button:hover {
background: ${dt('toast.contrast.close.button.hover.background')};
}
.p-toast-top-center {
transform: translateX(-50%);
}
.p-toast-bottom-center {
transform: translateX(-50%);
}
.p-toast-center {
min-width: 20vw;
transform: translate(-50%, -50%);
}
.p-toast-message-enter-from {
opacity: 0;
transform: translateY(50%);
}
.p-toast-message-leave-from {
max-height: 1000px;
}
.p-toast .p-toast-message.p-toast-message-leave-to {
max-height: 0;
opacity: 0;
margin-bottom: 0;
overflow: hidden;
}
.p-toast-message-enter-active {
transition: transform 0.3s, opacity 0.3s;
}
.p-toast-message-leave-active {
transition: max-height 0.45s cubic-bezier(0, 1, 0, 1), opacity 0.3s, margin-bottom 0.3s;
}
`;
// Position
const inlineStyles = {
root: ({ instance }) => {
const { _position } = instance;
return {
position: 'fixed',
top: _position === 'top-right' || _position === 'top-left' || _position === 'top-center' ? '20px' : _position === 'center' ? '50%' : null,
right: (_position === 'top-right' || _position === 'bottom-right') && '20px',
bottom: (_position === 'bottom-left' || _position === 'bottom-right' || _position === 'bottom-center') && '20px',
left: _position === 'top-left' || _position === 'bottom-left' ? '20px' : _position === 'center' || _position === 'top-center' || _position === 'bottom-center' ? '50%' : null
};
}
};
const classes = {
root: ({ instance }) => ({ 'p-toast p-component': true, [`p-toast-${instance._position}`]: !!instance._position }),
message: ({ instance }) => ({
'p-toast-message': true,
'p-toast-message-info': instance.message.severity === 'info' || instance.message.severity === undefined,
'p-toast-message-warn': instance.message.severity === 'warn',
'p-toast-message-error': instance.message.severity === 'error',
'p-toast-message-success': instance.message.severity === 'success',
'p-toast-message-secondary': instance.message.severity === 'secondary',
'p-toast-message-contrast': instance.message.severity === 'contrast'
}),
messageContent: 'p-toast-message-content',
messageIcon: ({ instance }) => ({
'p-toast-message-icon': true,
[`pi ${instance.message.icon}`]: !!instance.message.icon
}),
messageText: 'p-toast-message-text',
summary: 'p-toast-summary',
detail: 'p-toast-detail',
closeButton: 'p-toast-close-button',
closeIcon: ({ instance }) => ({
'p-toast-close-icon': true,
[`pi ${instance.message.closeIcon}`]: !!instance.message.closeIcon
})
};
class ToastStyle extends BaseStyle {
name = 'toast';
theme = theme;
classes = classes;
inlineStyles = inlineStyles;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ToastStyle, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ToastStyle });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ToastStyle, decorators: [{
type: Injectable
}] });
/**
*
* Toast is used to display messages in an overlay.
*
* [Live Demo](https://www.primeng.org/toast/)
*
* @module toaststyle
*
*/
var ToastClasses;
(function (ToastClasses) {
/**
* Class name of the root element
*/
ToastClasses["root"] = "p-toast";
/**
* Class name of the message element
*/
ToastClasses["message"] = "p-toast-message";
/**
* Class name of the message content element
*/
ToastClasses["messageContent"] = "p-toast-message-content";
/**
* Class name of the message icon element
*/
ToastClasses["messageIcon"] = "p-toast-message-icon";
/**
* Class name of the message text element
*/
ToastClasses["messageText"] = "p-toast-message-text";
/**
* Class name of the summary element
*/
ToastClasses["summary"] = "p-toast-summary";
/**
* Class name of the detail element
*/
ToastClasses["detail"] = "p-toast-detail";
/**
* Class name of the close button element
*/
ToastClasses["closeButton"] = "p-toast-close-button";
/**
* Class name of the close icon element
*/
ToastClasses["closeIcon"] = "p-toast-close-icon";
})(ToastClasses || (ToastClasses = {}));
class ToastItem extends BaseComponent {
zone;
message;
index;
life;
template;
headlessTemplate;
showTransformOptions;
hideTransformOptions;
showTransitionOptions;
hideTransitionOptions;
onClose = new EventEmitter();
containerViewChild;
_componentStyle = inject(ToastStyle);
timeout;
constructor(zone) {
super();
this.zone = zone;
}
ngAfterViewInit() {
super.ngAfterViewInit();
this.initTimeout();
}
initTimeout() {
if (!this.message?.sticky) {
this.zone.runOutsideAngular(() => {
this.timeout = setTimeout(() => {
this.onClose.emit({
index: this.index,
message: this.message
});
}, this.message?.life || this.life || 3000);
});
}
}
clearTimeout() {
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
}
onMouseEnter() {
this.clearTimeout();
}
onMouseLeave() {
this.initTimeout();
}
onCloseIconClick = (event) => {
this.clearTimeout();
this.onClose.emit({
index: this.index,
message: this.message
});
event.preventDefault();
};
get closeAriaLabel() {
return this.config.translation.aria ? this.config.translation.aria.close : undefined;
}
ngOnDestroy() {
this.clearTimeout();
super.ngOnDestroy();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ToastItem, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: ToastItem, isStandalone: true, selector: "p-toastItem", inputs: { message: "message", index: ["index", "index", numberAttribute], life: ["life", "life", numberAttribute], template: "template", headlessTemplate: "headlessTemplate", showTransformOptions: "showTransformOptions", hideTransformOptions: "hideTransformOptions", showTransitionOptions: "showTransitionOptions", hideTransitionOptions: "hideTransitionOptions" }, outputs: { onClose: "onClose" }, providers: [ToastStyle], viewQueries: [{ propertyName: "containerViewChild", first: true, predicate: ["container"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
<div
#container
[attr.id]="message?.id"
[class]="message?.styleClass"
[ngClass]="cx('message')"
[@messageState]="{
value: 'visible',
params: {
showTransformParams: showTransformOptions,
hideTransformParams: hideTransformOptions,
showTransitionParams: showTransitionOptions,
hideTransitionParams: hideTransitionOptions
}
}"
(mouseenter)="onMouseEnter()"
(mouseleave)="onMouseLeave()"
role="alert"
aria-live="assertive"
aria-atomic="true"
[attr.data-pc-name]="'toast'"
[attr.data-pc-section]="'root'"
>
@if (headlessTemplate) {
<ng-container *ngTemplateOutlet="headlessTemplate; context: { $implicit: message, closeFn: onCloseIconClick }"></ng-container>
} @else {
<div [ngClass]="cx('messageContent')" [class]="message?.contentStyleClass" [attr.data-pc-section]="'content'">
<ng-container *ngIf="!template">
<span *ngIf="message.icon" [ngClass]="cx('messageIcon')"></span>
<span [ngClass]="cx('messageIcon')" *ngIf="!message.icon" [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'">
@switch (message.severity) {
@case ('success') {
<CheckIcon [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'" />
}
@case ('info') {
<InfoCircleIcon [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'" />
}
@case ('error') {
<TimesCircleIcon [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'" />
}
@case ('warn') {
<ExclamationTriangleIcon [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'" />
}
@default {
<InfoCircleIcon [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'" />
}
}
</span>
<div [ngClass]="cx('messageText')" [attr.data-pc-section]="'text'">
<div [ngClass]="cx('summary')" [attr.data-pc-section]="'summary'">
{{ message.summary }}
</div>
<div [ngClass]="cx('detail')" [attr.data-pc-section]="'detail'">{{ message.detail }}</div>
</div>
</ng-container>
<ng-container *ngTemplateOutlet="template; context: { $implicit: message }"></ng-container>
@if (message?.closable !== false) {
<div>
<button type="button" [attr.class]="cx('closeButton')" (click)="onCloseIconClick($event)" (keydown.enter)="onCloseIconClick($event)" [ariaLabel]="closeAriaLabel" [attr.data-pc-section]="'closebutton'" autofocus>
@if (message.closeIcon) {
<span *ngIf="message.closeIcon" [ngClass]="cx('closeIcon')"></span>
} @else {
<TimesIcon [ngClass]="cx('closeIcon')" [attr.aria-hidden]="true" [attr.data-pc-section]="'closeicon'" />
}
</button>
</div>
}
</div>
}
</div>
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CheckIcon, selector: "CheckIcon" }, { kind: "component", type: ExclamationTriangleIcon, selector: "ExclamationTriangleIcon" }, { kind: "component", type: InfoCircleIcon, selector: "InfoCircleIcon" }, { kind: "component", type: TimesIcon, selector: "TimesIcon" }, { kind: "component", type: TimesCircleIcon, selector: "TimesCircleIcon" }, { kind: "ngmodule", type: SharedModule }], animations: [
trigger('messageState', [
state('visible', style({
transform: 'translateY(0)',
opacity: 1
})),
transition('void => *', [
style({
transform: '{{showTransformParams}}',
opacity: 0
}),
animate('{{showTransitionParams}}')
]),
transition('* => void', [
animate('{{hideTransitionParams}}', style({
height: 0,
opacity: 0,
transform: '{{hideTransformParams}}'
}))
])
])
], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ToastItem, decorators: [{
type: Component,
args: [{
selector: 'p-toastItem',
standalone: true,
imports: [CommonModule, CheckIcon, ExclamationTriangleIcon, InfoCircleIcon, TimesIcon, TimesCircleIcon, SharedModule],
template: `
<div
#container
[attr.id]="message?.id"
[class]="message?.styleClass"
[ngClass]="cx('message')"
[@messageState]="{
value: 'visible',
params: {
showTransformParams: showTransformOptions,
hideTransformParams: hideTransformOptions,
showTransitionParams: showTransitionOptions,
hideTransitionParams: hideTransitionOptions
}
}"
(mouseenter)="onMouseEnter()"
(mouseleave)="onMouseLeave()"
role="alert"
aria-live="assertive"
aria-atomic="true"
[attr.data-pc-name]="'toast'"
[attr.data-pc-section]="'root'"
>
@if (headlessTemplate) {
<ng-container *ngTemplateOutlet="headlessTemplate; context: { $implicit: message, closeFn: onCloseIconClick }"></ng-container>
} @else {
<div [ngClass]="cx('messageContent')" [class]="message?.contentStyleClass" [attr.data-pc-section]="'content'">
<ng-container *ngIf="!template">
<span *ngIf="message.icon" [ngClass]="cx('messageIcon')"></span>
<span [ngClass]="cx('messageIcon')" *ngIf="!message.icon" [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'">
@switch (message.severity) {
@case ('success') {
<CheckIcon [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'" />
}
@case ('info') {
<InfoCircleIcon [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'" />
}
@case ('error') {
<TimesCircleIcon [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'" />
}
@case ('warn') {
<ExclamationTriangleIcon [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'" />
}
@default {
<InfoCircleIcon [attr.aria-hidden]="true" [attr.data-pc-section]="'icon'" />
}
}
</span>
<div [ngClass]="cx('messageText')" [attr.data-pc-section]="'text'">
<div [ngClass]="cx('summary')" [attr.data-pc-section]="'summary'">
{{ message.summary }}
</div>
<div [ngClass]="cx('detail')" [attr.data-pc-section]="'detail'">{{ message.detail }}</div>
</div>
</ng-container>
<ng-container *ngTemplateOutlet="template; context: { $implicit: message }"></ng-container>
@if (message?.closable !== false) {
<div>
<button type="button" [attr.class]="cx('closeButton')" (click)="onCloseIconClick($event)" (keydown.enter)="onCloseIconClick($event)" [ariaLabel]="closeAriaLabel" [attr.data-pc-section]="'closebutton'" autofocus>
@if (message.closeIcon) {
<span *ngIf="message.closeIcon" [ngClass]="cx('closeIcon')"></span>
} @else {
<TimesIcon [ngClass]="cx('closeIcon')" [attr.aria-hidden]="true" [attr.data-pc-section]="'closeicon'" />
}
</button>
</div>
}
</div>
}
</div>
`,
animations: [
trigger('messageState', [
state('visible', style({
transform: 'translateY(0)',
opacity: 1
})),
transition('void => *', [
style({
transform: '{{showTransformParams}}',
opacity: 0
}),
animate('{{showTransitionParams}}')
]),
transition('* => void', [
animate('{{hideTransitionParams}}', style({
height: 0,
opacity: 0,
transform: '{{hideTransformParams}}'
}))
])
])
],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [ToastStyle]
}]
}], ctorParameters: () => [{ type: i0.NgZone }], propDecorators: { message: [{
type: Input
}], index: [{
type: Input,
args: [{ transform: numberAttribute }]
}], life: [{
type: Input,
args: [{ transform: numberAttribute }]
}], template: [{
type: Input
}], headlessTemplate: [{
type: Input
}], showTransformOptions: [{
type: Input
}], hideTransformOptions: [{
type: Input
}], showTransitionOptions: [{
type: Input
}], hideTransitionOptions: [{
type: Input
}], onClose: [{
type: Output
}], containerViewChild: [{
type: ViewChild,
args: ['container']
}] } });
/**
* Toast is used to display messages in an overlay.
* @group Components
*/
class Toast extends BaseComponent {
/**
* Key of the message in case message is targeted to a specific toast component.
* @group Props
*/
key;
/**
* Whether to automatically manage layering.
* @group Props
*/
autoZIndex = true;
/**
* Base zIndex value to use in layering.
* @group Props
*/
baseZIndex = 0;
/**
* The default time to display messages for in milliseconds.
* @group Props
*/
life = 3000;
/**
* Inline style of the component.
* @group Props
*/
style;
/**
* Inline class of the component.
* @group Props
*/
styleClass;
/**
* Position of the toast in viewport.
* @group Props
*/
get position() {
return this._position;
}
set position(value) {
this._position = value;
this.cd.markForCheck();
}
/**
* It does not add the new message if there is already a toast displayed with the same content
* @group Props
*/
preventOpenDuplicates = false;
/**
* Displays only once a message with the same content.
* @group Props
*/
preventDuplicates = false;
/**
* Transform options of the show animation.
* @group Props
*/
showTransformOptions = 'translateY(100%)';
/**
* Transform options of the hide animation.
* @group Props
*/
hideTransformOptions = 'translateY(-100%)';
/**
* Transition options of the show animation.
* @group Props
*/
showTransitionOptions = '300ms ease-out';
/**
* Transition options of the hide animation.
* @group Props
*/
hideTransitionOptions = '250ms ease-in';
/**
* Object literal to define styles per screen size.
* @group Props
*/
breakpoints;
/**
* Callback to invoke when a message is closed.
* @param {ToastCloseEvent} event - custom close event.
* @group Emits
*/
onClose = new EventEmitter();
/**
* Custom template of message.
* @group Templates
*/
template;
/**
* Custom headless template.
* @group Templates
*/
headlessTemplate;
containerViewChild;
messageSubscription;
clearSubscription;
messages;
messagesArchieve;
_position = 'top-right';
messageService = inject(MessageService);
_componentStyle = inject(ToastStyle);
styleElement;
id = uuid('pn_id_');
templates;
ngOnInit() {
super.ngOnInit();
this.messageSubscription = this.messageService.messageObserver.subscribe((messages) => {
if (messages) {
if (Array.isArray(messages)) {
const filteredMessages = messages.filter((m) => this.canAdd(m));
this.add(filteredMessages);
}
else if (this.canAdd(messages)) {
this.add([messages]);
}
}
});
this.clearSubscription = this.messageService.clearObserver.subscribe((key) => {
if (key) {
if (this.key === key) {
this.messages = null;
}
}
else {
this.messages = null;
}
this.cd.markForCheck();
});
}
_template;
_headlessTemplate;
ngAfterContentInit() {
this.templates?.forEach((item) => {
switch (item.getType()) {
case 'message':
this._template = item.template;
break;
case 'headless':
this._headlessTemplate = item.template;
break;
default:
this._template = item.template;
break;
}
});
}
ngAfterViewInit() {
super.ngAfterViewInit();
if (this.breakpoints) {
this.createStyle();
}
}
add(messages) {
this.messages = this.messages ? [...this.messages, ...messages] : [...messages];
if (this.preventDuplicates) {
this.messagesArchieve = this.messagesArchieve ? [...this.messagesArchieve, ...messages] : [...messages];
}
this.cd.markForCheck();
}
canAdd(message) {
let allow = this.key === message.key;
if (allow && this.preventOpenDuplicates) {
allow = !this.containsMessage(this.messages, message);
}
if (allow && this.preventDuplicates) {
allow = !this.containsMessage(this.messagesArchieve, message);
}
return allow;
}
containsMessage(collection, message) {
if (!collection) {
return false;
}
return (collection.find((m) => {
return m.summary === message.summary && m.detail == message.detail && m.severity === message.severity;
}) != null);
}
onMessageClose(event) {
this.messages?.splice(event.index, 1);
this.onClose.emit({
message: event.message
});
this.cd.detectChanges();
}
onAnimationStart(event) {
if (event.fromState === 'void') {
this.renderer.setAttribute(this.containerViewChild?.nativeElement, this.id, '');
if (this.autoZIndex && this.containerViewChild?.nativeElement.style.zIndex === '') {
ZIndexUtils.set('modal', this.containerViewChild?.nativeElement, this.baseZIndex || this.config.zIndex.modal);
}
}
}
onAnimationEnd(event) {
if (event.toState === 'void') {
if (this.autoZIndex && isEmpty(this.messages)) {
ZIndexUtils.clear(this.containerViewChild?.nativeElement);
}
}
}
createStyle() {
if (!this.styleElement) {
this.styleElement = this.renderer.createElement('style');
this.styleElement.type = 'text/css';
this.renderer.appendChild(this.document.head, this.styleElement);
let innerHTML = '';
for (let breakpoint in this.breakpoints) {
let breakpointStyle = '';
for (let styleProp in this.breakpoints[breakpoint]) {
breakpointStyle += styleProp + ':' + this.breakpoints[breakpoint][styleProp] + ' !important;';
}
innerHTML += `
@media screen and (max-width: ${breakpoint}) {
.p-toast[${this.id}] {
${breakpointStyle}
}
}
`;
}
this.renderer.setProperty(this.styleElement, 'innerHTML', innerHTML);
setAttribute(this.styleElement, 'nonce', this.config?.csp()?.nonce);
}
}
destroyStyle() {
if (this.styleElement) {
this.renderer.removeChild(this.document.head, this.styleElement);
this.styleElement = null;
}
}
ngOnDestroy() {
if (this.messageSubscription) {
this.messageSubscription.unsubscribe();
}
if (this.containerViewChild && this.autoZIndex) {
ZIndexUtils.clear(this.containerViewChild.nativeElement);
}
if (this.clearSubscription) {
this.clearSubscription.unsubscribe();
}
this.destroyStyle();
super.ngOnDestroy();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: Toast, deps: null, target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "19.2.10", type: Toast, isStandalone: true, selector: "p-toast", inputs: { key: "key", autoZIndex: ["autoZIndex", "autoZIndex", booleanAttribute], baseZIndex: ["baseZIndex", "baseZIndex", numberAttribute], life: ["life", "life", numberAttribute], style: "style", styleClass: "styleClass", position: "position", preventOpenDuplicates: ["preventOpenDuplicates", "preventOpenDuplicates", booleanAttribute], preventDuplicates: ["preventDuplicates", "preventDuplicates", booleanAttribute], showTransformOptions: "showTransformOptions", hideTransformOptions: "hideTransformOptions", showTransitionOptions: "showTransitionOptions", hideTransitionOptions: "hideTransitionOptions", breakpoints: "breakpoints" }, outputs: { onClose: "onClose" }, providers: [ToastStyle], queries: [{ propertyName: "template", first: true, predicate: ["message"], descendants: true }, { propertyName: "headlessTemplate", first: true, predicate: ["headless"], descendants: true }, { propertyName: "templates", predicate: PrimeTemplate }], viewQueries: [{ propertyName: "containerViewChild", first: true, predicate: ["container"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
<div #container [ngClass]="cx('root')" [ngStyle]="sx('root')" [style]="style" [class]="styleClass">
<p-toastItem
*ngFor="let msg of messages; let i = index"
[message]="msg"
[index]="i"
[life]="life"
(onClose)="onMessageClose($event)"
[template]="template || _template"
[headlessTemplate]="headlessTemplate || _headlessTemplate"
@toastAnimation
(@toastAnimation.start)="onAnimationStart($event)"
(@toastAnimation.done)="onAnimationEnd($event)"
[showTransformOptions]="showTransformOptions"
[hideTransformOptions]="hideTransformOptions"
[showTransitionOptions]="showTransitionOptions"
[hideTransitionOptions]="hideTransitionOptions"
></p-toastItem>
</div>
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ToastItem, selector: "p-toastItem", inputs: ["message", "index", "life", "template", "headlessTemplate", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onClose"] }, { kind: "ngmodule", type: SharedModule }], animations: [trigger('toastAnimation', [transition(':enter, :leave', [query('@*', animateChild())])])], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: Toast, decorators: [{
type: Component,
args: [{
selector: 'p-toast',
standalone: true,
imports: [CommonModule, ToastItem, SharedModule],
template: `
<div #container [ngClass]="cx('root')" [ngStyle]="sx('root')" [style]="style" [class]="styleClass">
<p-toastItem
*ngFor="let msg of messages; let i = index"
[message]="msg"
[index]="i"
[life]="life"
(onClose)="onMessageClose($event)"
[template]="template || _template"
[headlessTemplate]="headlessTemplate || _headlessTemplate"
@toastAnimation
(@toastAnimation.start)="onAnimationStart($event)"
(@toastAnimation.done)="onAnimationEnd($event)"
[showTransformOptions]="showTransformOptions"
[hideTransformOptions]="hideTransformOptions"
[showTransitionOptions]="showTransitionOptions"
[hideTransitionOptions]="hideTransitionOptions"
></p-toastItem>
</div>
`,
animations: [trigger('toastAnimation', [transition(':enter, :leave', [query('@*', animateChild())])])],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
providers: [ToastStyle]
}]
}], propDecorators: { key: [{
type: Input
}], autoZIndex: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], baseZIndex: [{
type: Input,
args: [{ transform: numberAttribute }]
}], life: [{
type: Input,
args: [{ transform: numberAttribute }]
}], style: [{
type: Input
}], styleClass: [{
type: Input
}], position: [{
type: Input
}], preventOpenDuplicates: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], preventDuplicates: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], showTransformOptions: [{
type: Input
}], hideTransformOptions: [{
type: Input
}], showTransitionOptions: [{
type: Input
}], hideTransitionOptions: [{
type: Input
}], breakpoints: [{
type: Input
}], onClose: [{
type: Output
}], template: [{
type: ContentChild,
args: ['message']
}], headlessTemplate: [{
type: ContentChild,
args: ['headless']
}], containerViewChild: [{
type: ViewChild,
args: ['container']
}], templates: [{
type: ContentChildren,
args: [PrimeTemplate]
}] } });
class ToastModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ToastModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: ToastModule, imports: [Toast, SharedModule], exports: [Toast, SharedModule] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ToastModule, imports: [Toast, SharedModule, SharedModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: ToastModule, decorators: [{
type: NgModule,
args: [{
imports: [Toast, SharedModule],
exports: [Toast, SharedModule]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { Toast, ToastClasses, ToastItem, ToastModule, ToastStyle };
//# sourceMappingURL=primeng-toast.mjs.map