UNPKG

mk-magic-alerts

Version:
306 lines (292 loc) 42.5 kB
import * as i0 from '@angular/core'; import { Service, Pipe, inject, ElementRef, DestroyRef, input, viewChild, signal, computed, ChangeDetectionStrategy, Component, InjectionToken, makeEnvironmentProviders, ApplicationRef, Injector, createComponent } from '@angular/core'; import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { BehaviorSubject, Subject, fromEvent, timer, race } from 'rxjs'; import { takeUntil, repeat, take, tap } from 'rxjs/operators'; const AlertState = { DISPLAY: 'display', DISMISS: 'dismiss', DISMISSED: 'dismissed', }; class AlertsStore { constructor() { this.alertsSubject = new BehaviorSubject([]); this.nextAlertId = 1; this.alerts = toSignal(this.alertsSubject.asObservable(), { initialValue: [], manualCleanup: true }); this.dismissAllSubject = new Subject(); this.dismissAll$ = this.dismissAllSubject.asObservable(); } dismissAll() { this.dismissAllSubject.next(); } addAlert(text, type, dismissTimeInMillis) { // Remove alerts that already started or finished their exit animation. // filter() makes a shallow copy of the array (a new array, but pointing to the same objects) const activeAlerts = this.alertsSubject .getValue() .filter((alert) => alert.state === AlertState.DISPLAY); // Create and add new message: this.alertsSubject.next([ ...activeAlerts, this.createAlert(text, type, dismissTimeInMillis) ]); } createAlert(text, type, dismissTimeInMillis) { return { id: `alert-${this.nextAlertId++}`, text, type, dismissTimeInMillis, state: AlertState.DISPLAY }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: AlertsStore, deps: [], target: i0.ɵɵFactoryTarget.Service }); } static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.0", ngImport: i0, type: AlertsStore }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: AlertsStore, decorators: [{ type: Service }] }); class NewlineAndTabsPipe { transform(value) { return value?.toString().replace(/(?:\r\n|\r|\n)/g, '<br />').replace(/(?:\t)/g, '&nbsp;&nbsp;&nbsp;&nbsp;') ?? ''; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: NewlineAndTabsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); } static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.0", ngImport: i0, type: NewlineAndTabsPipe, isStandalone: true, name: "newlineAndTabs" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: NewlineAndTabsPipe, decorators: [{ type: Pipe, args: [{ name: 'newlineAndTabs', standalone: true }] }] }); const AlertEntryAnimation = { DOT: 'dot', BURST: 'burst', DROP: 'drop', SLIDE_LEFT: 'slide-left', SLIDE_RIGHT: 'slide-right', UNFOLD: 'unfold' }; const AlertAppearance = { CLASSIC: 'classic', GRADIENT: 'gradient' }; class AlertComponent { constructor() { this.elementRef = inject((ElementRef)); this.alertsStore = inject(AlertsStore); this.destroyRef = inject(DestroyRef); this.alertParams = input.required(/* @ts-ignore */ ...(ngDevMode ? [{ debugName: "alertParams" }] : /* istanbul ignore next */ [])); this.entryAnimation = input.required(/* @ts-ignore */ ...(ngDevMode ? [{ debugName: "entryAnimation" }] : /* istanbul ignore next */ [])); this.alertAppearance = input.required(/* @ts-ignore */ ...(ngDevMode ? [{ debugName: "alertAppearance" }] : /* istanbul ignore next */ [])); this.container = viewChild('container', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "container" }] : /* istanbul ignore next */ [])); this.state = signal(AlertState.DISPLAY, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ [])); this.fixedEntryAnimation = signal(AlertEntryAnimation.DOT, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "fixedEntryAnimation" }] : /* istanbul ignore next */ [])); this.fixedAlertAppearance = signal(AlertAppearance.CLASSIC, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "fixedAlertAppearance" }] : /* istanbul ignore next */ [])); this.entryAnimationDone = signal(false, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "entryAnimationDone" }] : /* istanbul ignore next */ [])); this.isRendered = computed(() => this.state() !== AlertState.DISMISSED, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "isRendered" }] : /* istanbul ignore next */ [])); this.dismissTimeInMillis = computed(() => this.alertParams().dismissTimeInMillis, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "dismissTimeInMillis" }] : /* istanbul ignore next */ [])); this.enterAnimationClass = computed(() => `alert-enter-${this.fixedEntryAnimation()}`, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "enterAnimationClass" }] : /* istanbul ignore next */ [])); this.leaveAnimationClass = computed(() => `alert-leave-${this.fixedEntryAnimation()}`, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "leaveAnimationClass" }] : /* istanbul ignore next */ [])); this.animationClass = computed(() => this.state() === AlertState.DISMISS ? this.leaveAnimationClass() : this.entryAnimationDone() ? '' : this.enterAnimationClass(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "animationClass" }] : /* istanbul ignore next */ [])); } ngOnInit() { this.fixedEntryAnimation.set(this.entryAnimation()); this.fixedAlertAppearance.set(this.alertAppearance()); const el = this.elementRef.nativeElement; const mouseenter$ = fromEvent(el, 'mouseenter'); const mouseleave$ = fromEvent(el, 'mouseleave'); // Observable that allows closing of the alert by user-click: const dismissalByUser$ = fromEvent(el, 'mouseup'); // If dismissal is requested programmatically from alerts-service: const dismissalByService$ = this.alertsStore.dismissAll$; // Observable that closes the alert after a given time, // unless user hovers over the alert with a cursor => 'takeUntil()' and 'repeat()' const dismissalAfterTimeout$ = timer(this.dismissTimeInMillis()).pipe(takeUntil(mouseenter$), repeat({ delay: () => mouseleave$ })); race([dismissalByUser$, dismissalByService$, dismissalAfterTimeout$]) .pipe(take(1), tap(() => this.setDismissalStart()), takeUntilDestroyed(this.destroyRef)) .subscribe(); } /* Triggers the animated disappearing of the alert */ setDismissalStart() { if (this.state() !== AlertState.DISMISS) { const el = this.container()?.nativeElement; if (el) { // Lock current height via CSS var used by the stylesheet el.style.setProperty('--h', `${el.offsetHeight}px`); } this.alertParams().state = AlertState.DISMISS; this.state.set(AlertState.DISMISS); } } /** After the leave animation finishes, mark as DISMISSED */ onContainerAnimationEnd(event) { if (event.target !== this.container()?.nativeElement) { return; } if (this.state() === AlertState.DISMISS) { this.alertParams().state = AlertState.DISMISSED; this.state.set(AlertState.DISMISSED); return; } this.entryAnimationDone.set(true); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: AlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: AlertComponent, isStandalone: true, selector: "app-alert", inputs: { alertParams: { classPropertyName: "alertParams", publicName: "alertParams", isSignal: true, isRequired: true, transformFunction: null }, entryAnimation: { classPropertyName: "entryAnimation", publicName: "entryAnimation", isSignal: true, isRequired: true, transformFunction: null }, alertAppearance: { classPropertyName: "alertAppearance", publicName: "alertAppearance", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (alertParams(); as params) {\n <div class=\"clickable-area\">\n @if (isRendered()) {\n <div\n #container\n class=\"alert-container alert-{{ params.type }} alert-{{ fixedAlertAppearance() }} {{ animationClass() }}\"\n role=\"alert\"\n (animationend)=\"onContainerAnimationEnd($event)\">\n\n <div class=\"alert-icon\" aria-hidden=\"true\">\n @switch (params.type) {\n @case ('info') {\n <i class=\"fa fa-info-circle\"></i>\n }\n @case ('success') {\n <i class=\"fa fa-check\"></i>\n }\n @case ('warning') {\n <i class=\"fa fa-exclamation-triangle\"></i>\n }\n @case ('error') {\n <i class=\"fa fa-exclamation-triangle\"></i>\n }\n }\n </div>\n\n <div class=\"alert-text\" [innerHtml]=\"params.text | newlineAndTabs\"></div>\n\n <button type=\"button\" class=\"btn-dismiss\" aria-label=\"Alert schliessen\">\n <i class=\"fa fa-times\"></i>\n </button>\n </div>\n }\n </div>\n}\n", styles: ["@charset \"UTF-8\";.clickable-area{cursor:pointer;margin-top:5px}.clickable-area .alert-container{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:15px;align-items:center;height:var(--h, auto);margin:0;padding:5px 15px;overflow:hidden;border:1px solid;border-radius:4px;z-index:1020!important}.clickable-area .alert-container .alert-icon{display:none}.clickable-area .alert-container .alert-text{min-width:0;overflow-wrap:anywhere;word-break:break-word;font:400 16px/20px Roboto}.clickable-area .alert-container .btn-dismiss{justify-self:end;align-self:baseline;padding:0;border:0;background:transparent;cursor:pointer;font-size:15px}.clickable-area .alert-container.alert-gradient{grid-template-columns:auto minmax(0,1fr) auto;column-gap:12px;padding:10px 10px 10px 14px;border-radius:10px}.clickable-area .alert-container.alert-gradient .alert-icon{align-self:start;display:grid;width:32px;height:32px;place-items:center;border-radius:50%;font-size:16px}.clickable-area .alert-container.alert-gradient .alert-text{font:400 16px/21px Roboto}.clickable-area .alert-container.alert-gradient .btn-dismiss{display:grid;width:28px;height:28px;place-items:center;align-self:start;border-radius:50%;transition:color .16s ease,background-color .16s ease,box-shadow .16s ease}.clickable-area .alert-enter-dot{transform-origin:top left;animation:alert-enter-dot .32s ease both}.clickable-area .alert-enter-dot .alert-text,.clickable-area .alert-enter-dot .alert-icon,.clickable-area .alert-enter-dot .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-dot{height:var(--h, auto);transform-origin:top left;animation:alert-leave-dot .48s ease-in forwards}.clickable-area .alert-leave-dot .alert-text,.clickable-area .alert-leave-dot .alert-icon,.clickable-area .alert-leave-dot .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-enter-burst{transform-origin:center;animation:alert-enter-burst .36s cubic-bezier(.18,1.45,.35,1) both}.clickable-area .alert-enter-burst .alert-text,.clickable-area .alert-enter-burst .alert-icon,.clickable-area .alert-enter-burst .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-burst{height:var(--h, auto);transform-origin:center;animation:alert-leave-burst .42s ease-in forwards}.clickable-area .alert-leave-burst .alert-text,.clickable-area .alert-leave-burst .alert-icon,.clickable-area .alert-leave-burst .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-enter-drop{transform-origin:center top;animation:alert-enter-drop .48s cubic-bezier(.2,1.25,.34,1) both}.clickable-area .alert-enter-drop .alert-text,.clickable-area .alert-enter-drop .alert-icon,.clickable-area .alert-enter-drop .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-drop{height:var(--h, auto);transform-origin:center top;animation:alert-leave-drop .4s ease-in forwards}.clickable-area .alert-leave-drop .alert-text,.clickable-area .alert-leave-drop .alert-icon,.clickable-area .alert-leave-drop .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-enter-slide-right{transform-origin:right center;animation:alert-enter-slide-right .4s cubic-bezier(.22,1,.36,1) both}.clickable-area .alert-enter-slide-right .alert-text,.clickable-area .alert-enter-slide-right .alert-icon,.clickable-area .alert-enter-slide-right .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-slide-right{height:var(--h, auto);transform-origin:right center;animation:alert-leave-slide-right .44s ease-in forwards}.clickable-area .alert-leave-slide-right .alert-text,.clickable-area .alert-leave-slide-right .alert-icon,.clickable-area .alert-leave-slide-right .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-enter-slide-left{transform-origin:left center;animation:alert-enter-slide-left .4s cubic-bezier(.22,1,.36,1) both}.clickable-area .alert-enter-slide-left .alert-text,.clickable-area .alert-enter-slide-left .alert-icon,.clickable-area .alert-enter-slide-left .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-slide-left{height:var(--h, auto);transform-origin:left center;animation:alert-leave-slide-left .44s ease-in forwards}.clickable-area .alert-leave-slide-left .alert-text,.clickable-area .alert-leave-slide-left .alert-icon,.clickable-area .alert-leave-slide-left .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-enter-unfold{transform-origin:center top;animation:alert-enter-unfold .42s cubic-bezier(.22,1,.36,1) both}.clickable-area .alert-enter-unfold .alert-text,.clickable-area .alert-enter-unfold .alert-icon,.clickable-area .alert-enter-unfold .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-unfold{height:var(--h, auto);transform-origin:center top;animation:alert-leave-unfold .44s ease-in forwards}.clickable-area .alert-leave-unfold .alert-text,.clickable-area .alert-leave-unfold .alert-icon,.clickable-area .alert-leave-unfold .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-classic.alert-info{color:#004085;border-color:#004085;background-color:#b8daff;box-shadow:0 4px 8px #00000014,0 6px 20px #00000014}.clickable-area .alert-classic.alert-info .btn-dismiss{color:inherit}.clickable-area .alert-classic.alert-info .btn-dismiss:hover{text-shadow:0 0 10px rgb(51,102,255),0 0 20px rgb(51,102,255)}.clickable-area .alert-classic.alert-success{color:#155724;border-color:#155724;background-color:#c3e6cb;box-shadow:0 4px 8px #00000014,0 6px 20px #00000014}.clickable-area .alert-classic.alert-success .btn-dismiss{color:inherit}.clickable-area .alert-classic.alert-success .btn-dismiss:hover{text-shadow:0 0 10px rgb(48,162,77),0 0 20px rgb(48,162,77)}.clickable-area .alert-classic.alert-warning{color:#856404;border-color:#856404;background-color:#ffeeba;box-shadow:0 4px 8px #00000014,0 6px 20px #00000014}.clickable-area .alert-classic.alert-warning .btn-dismiss{color:inherit}.clickable-area .alert-classic.alert-warning .btn-dismiss:hover{text-shadow:0 0 10px rgb(179,134,0),0 0 20px rgb(179,134,0)}.clickable-area .alert-classic.alert-error{color:#721c24;border-color:#721c24;background-color:#f8d7da;box-shadow:0 4px 8px #00000014,0 6px 20px #00000014}.clickable-area .alert-classic.alert-error .btn-dismiss{color:inherit}.clickable-area .alert-classic.alert-error .btn-dismiss:hover{text-shadow:0 0 10px rgb(255,76,89),0 0 20px rgb(255,76,89)}.clickable-area .alert-gradient.alert-info{color:#004085;border-color:#0040854d;background:linear-gradient(105deg,#daebff,#f4f9ff 68%,#fff);box-shadow:0 5px 12px #0000001a,0 14px 30px #0040851a}.clickable-area .alert-gradient.alert-info .alert-icon{color:#004085;background-color:#c9e2ff}.clickable-area .alert-gradient.alert-info .btn-dismiss{color:#004085}.clickable-area .alert-gradient.alert-info .btn-dismiss:hover{text-shadow:0 0 10px rgb(51,102,255),0 0 20px rgb(51,102,255)}.clickable-area .alert-gradient.alert-success{color:#155724;border-color:#1557244d;background:linear-gradient(105deg,#d8f0dd,#f6fcf7 68%,#fff);box-shadow:0 5px 12px #0000001a,0 14px 30px #1557241a}.clickable-area .alert-gradient.alert-success .alert-icon{color:#155724;background-color:#c9e8d1}.clickable-area .alert-gradient.alert-success .btn-dismiss{color:#155724}.clickable-area .alert-gradient.alert-success .btn-dismiss:hover{text-shadow:0 0 10px rgb(48,162,77),0 0 20px rgb(48,162,77)}.clickable-area .alert-gradient.alert-warning{color:#856404;border-color:#8564044d;background:linear-gradient(105deg,#fff0c0,#fffbed 68%,#fff);box-shadow:0 5px 12px #0000001a,0 14px 30px #8564041a}.clickable-area .alert-gradient.alert-warning .alert-icon{color:#856404;background-color:#ffe599}.clickable-area .alert-gradient.alert-warning .btn-dismiss{color:#856404}.clickable-area .alert-gradient.alert-warning .btn-dismiss:hover{text-shadow:0 0 10px rgb(179,134,0),0 0 20px rgb(179,134,0)}.clickable-area .alert-gradient.alert-error{color:#721c24;border-color:#721c244d;background:linear-gradient(105deg,#fadcdf,#fff7f8 68%,#fff);box-shadow:0 5px 12px #0000001a,0 14px 30px #721c241a}.clickable-area .alert-gradient.alert-error .alert-icon{color:#721c24;background-color:#f7ccd1}.clickable-area .alert-gradient.alert-error .btn-dismiss{color:#721c24}.clickable-area .alert-gradient.alert-error .btn-dismiss:hover{text-shadow:0 0 10px rgb(255,76,89),0 0 20px rgb(255,76,89)}@media(prefers-reduced-motion:reduce){.clickable-area,.clickable-area *{transition-duration:1ms!important;animation-duration:1ms!important}}@keyframes alert-content-in{0%{opacity:0}to{opacity:1}}@keyframes alert-content-out{to{opacity:0}}@keyframes alert-enter-dot{0%{transform:scale(0);opacity:0;border-width:0}to{transform:none;opacity:1;border-width:1px}}@keyframes alert-enter-burst{0%{transform:scale(.72);opacity:0;border-width:0}to{transform:scale(1);opacity:1;border-width:1px}}@keyframes alert-enter-drop{0%{transform:translateY(-48px) scale(.98);opacity:0;border-width:0}64%{transform:translateY(5px) scale(1.01);opacity:1;border-width:1px}82%{transform:translateY(-2px) scale(.995)}to{transform:translateY(0) scale(1);opacity:1;border-width:1px}}@keyframes alert-enter-slide-right{0%{transform:translate(42px);opacity:0;border-width:0}to{transform:translate(0);opacity:1;border-width:1px}}@keyframes alert-enter-slide-left{0%{transform:translate(-42px);opacity:0;border-width:0}to{transform:translate(0);opacity:1;border-width:1px}}@keyframes alert-enter-unfold{0%{transform:scaleY(.02);opacity:0;border-width:0}to{transform:scaleY(1);opacity:1;border-width:1px}}@keyframes alert-leave-dot{to{transform:scale(0);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}@keyframes alert-leave-burst{to{transform:scale(.82);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}@keyframes alert-leave-drop{to{transform:translateY(18px) scale(.98);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}@keyframes alert-leave-slide-right{to{transform:translate(28px);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}@keyframes alert-leave-slide-left{to{transform:translate(-28px);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}@keyframes alert-leave-unfold{to{transform:scaleY(.04);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}\n"], dependencies: [{ kind: "pipe", type: NewlineAndTabsPipe, name: "newlineAndTabs" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: AlertComponent, decorators: [{ type: Component, args: [{ selector: 'app-alert', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NewlineAndTabsPipe], template: "@if (alertParams(); as params) {\n <div class=\"clickable-area\">\n @if (isRendered()) {\n <div\n #container\n class=\"alert-container alert-{{ params.type }} alert-{{ fixedAlertAppearance() }} {{ animationClass() }}\"\n role=\"alert\"\n (animationend)=\"onContainerAnimationEnd($event)\">\n\n <div class=\"alert-icon\" aria-hidden=\"true\">\n @switch (params.type) {\n @case ('info') {\n <i class=\"fa fa-info-circle\"></i>\n }\n @case ('success') {\n <i class=\"fa fa-check\"></i>\n }\n @case ('warning') {\n <i class=\"fa fa-exclamation-triangle\"></i>\n }\n @case ('error') {\n <i class=\"fa fa-exclamation-triangle\"></i>\n }\n }\n </div>\n\n <div class=\"alert-text\" [innerHtml]=\"params.text | newlineAndTabs\"></div>\n\n <button type=\"button\" class=\"btn-dismiss\" aria-label=\"Alert schliessen\">\n <i class=\"fa fa-times\"></i>\n </button>\n </div>\n }\n </div>\n}\n", styles: ["@charset \"UTF-8\";.clickable-area{cursor:pointer;margin-top:5px}.clickable-area .alert-container{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:15px;align-items:center;height:var(--h, auto);margin:0;padding:5px 15px;overflow:hidden;border:1px solid;border-radius:4px;z-index:1020!important}.clickable-area .alert-container .alert-icon{display:none}.clickable-area .alert-container .alert-text{min-width:0;overflow-wrap:anywhere;word-break:break-word;font:400 16px/20px Roboto}.clickable-area .alert-container .btn-dismiss{justify-self:end;align-self:baseline;padding:0;border:0;background:transparent;cursor:pointer;font-size:15px}.clickable-area .alert-container.alert-gradient{grid-template-columns:auto minmax(0,1fr) auto;column-gap:12px;padding:10px 10px 10px 14px;border-radius:10px}.clickable-area .alert-container.alert-gradient .alert-icon{align-self:start;display:grid;width:32px;height:32px;place-items:center;border-radius:50%;font-size:16px}.clickable-area .alert-container.alert-gradient .alert-text{font:400 16px/21px Roboto}.clickable-area .alert-container.alert-gradient .btn-dismiss{display:grid;width:28px;height:28px;place-items:center;align-self:start;border-radius:50%;transition:color .16s ease,background-color .16s ease,box-shadow .16s ease}.clickable-area .alert-enter-dot{transform-origin:top left;animation:alert-enter-dot .32s ease both}.clickable-area .alert-enter-dot .alert-text,.clickable-area .alert-enter-dot .alert-icon,.clickable-area .alert-enter-dot .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-dot{height:var(--h, auto);transform-origin:top left;animation:alert-leave-dot .48s ease-in forwards}.clickable-area .alert-leave-dot .alert-text,.clickable-area .alert-leave-dot .alert-icon,.clickable-area .alert-leave-dot .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-enter-burst{transform-origin:center;animation:alert-enter-burst .36s cubic-bezier(.18,1.45,.35,1) both}.clickable-area .alert-enter-burst .alert-text,.clickable-area .alert-enter-burst .alert-icon,.clickable-area .alert-enter-burst .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-burst{height:var(--h, auto);transform-origin:center;animation:alert-leave-burst .42s ease-in forwards}.clickable-area .alert-leave-burst .alert-text,.clickable-area .alert-leave-burst .alert-icon,.clickable-area .alert-leave-burst .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-enter-drop{transform-origin:center top;animation:alert-enter-drop .48s cubic-bezier(.2,1.25,.34,1) both}.clickable-area .alert-enter-drop .alert-text,.clickable-area .alert-enter-drop .alert-icon,.clickable-area .alert-enter-drop .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-drop{height:var(--h, auto);transform-origin:center top;animation:alert-leave-drop .4s ease-in forwards}.clickable-area .alert-leave-drop .alert-text,.clickable-area .alert-leave-drop .alert-icon,.clickable-area .alert-leave-drop .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-enter-slide-right{transform-origin:right center;animation:alert-enter-slide-right .4s cubic-bezier(.22,1,.36,1) both}.clickable-area .alert-enter-slide-right .alert-text,.clickable-area .alert-enter-slide-right .alert-icon,.clickable-area .alert-enter-slide-right .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-slide-right{height:var(--h, auto);transform-origin:right center;animation:alert-leave-slide-right .44s ease-in forwards}.clickable-area .alert-leave-slide-right .alert-text,.clickable-area .alert-leave-slide-right .alert-icon,.clickable-area .alert-leave-slide-right .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-enter-slide-left{transform-origin:left center;animation:alert-enter-slide-left .4s cubic-bezier(.22,1,.36,1) both}.clickable-area .alert-enter-slide-left .alert-text,.clickable-area .alert-enter-slide-left .alert-icon,.clickable-area .alert-enter-slide-left .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-slide-left{height:var(--h, auto);transform-origin:left center;animation:alert-leave-slide-left .44s ease-in forwards}.clickable-area .alert-leave-slide-left .alert-text,.clickable-area .alert-leave-slide-left .alert-icon,.clickable-area .alert-leave-slide-left .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-enter-unfold{transform-origin:center top;animation:alert-enter-unfold .42s cubic-bezier(.22,1,.36,1) both}.clickable-area .alert-enter-unfold .alert-text,.clickable-area .alert-enter-unfold .alert-icon,.clickable-area .alert-enter-unfold .btn-dismiss{animation:alert-content-in .12s linear .12s both}.clickable-area .alert-leave-unfold{height:var(--h, auto);transform-origin:center top;animation:alert-leave-unfold .44s ease-in forwards}.clickable-area .alert-leave-unfold .alert-text,.clickable-area .alert-leave-unfold .alert-icon,.clickable-area .alert-leave-unfold .btn-dismiss{animation:alert-content-out .08s linear forwards}.clickable-area .alert-classic.alert-info{color:#004085;border-color:#004085;background-color:#b8daff;box-shadow:0 4px 8px #00000014,0 6px 20px #00000014}.clickable-area .alert-classic.alert-info .btn-dismiss{color:inherit}.clickable-area .alert-classic.alert-info .btn-dismiss:hover{text-shadow:0 0 10px rgb(51,102,255),0 0 20px rgb(51,102,255)}.clickable-area .alert-classic.alert-success{color:#155724;border-color:#155724;background-color:#c3e6cb;box-shadow:0 4px 8px #00000014,0 6px 20px #00000014}.clickable-area .alert-classic.alert-success .btn-dismiss{color:inherit}.clickable-area .alert-classic.alert-success .btn-dismiss:hover{text-shadow:0 0 10px rgb(48,162,77),0 0 20px rgb(48,162,77)}.clickable-area .alert-classic.alert-warning{color:#856404;border-color:#856404;background-color:#ffeeba;box-shadow:0 4px 8px #00000014,0 6px 20px #00000014}.clickable-area .alert-classic.alert-warning .btn-dismiss{color:inherit}.clickable-area .alert-classic.alert-warning .btn-dismiss:hover{text-shadow:0 0 10px rgb(179,134,0),0 0 20px rgb(179,134,0)}.clickable-area .alert-classic.alert-error{color:#721c24;border-color:#721c24;background-color:#f8d7da;box-shadow:0 4px 8px #00000014,0 6px 20px #00000014}.clickable-area .alert-classic.alert-error .btn-dismiss{color:inherit}.clickable-area .alert-classic.alert-error .btn-dismiss:hover{text-shadow:0 0 10px rgb(255,76,89),0 0 20px rgb(255,76,89)}.clickable-area .alert-gradient.alert-info{color:#004085;border-color:#0040854d;background:linear-gradient(105deg,#daebff,#f4f9ff 68%,#fff);box-shadow:0 5px 12px #0000001a,0 14px 30px #0040851a}.clickable-area .alert-gradient.alert-info .alert-icon{color:#004085;background-color:#c9e2ff}.clickable-area .alert-gradient.alert-info .btn-dismiss{color:#004085}.clickable-area .alert-gradient.alert-info .btn-dismiss:hover{text-shadow:0 0 10px rgb(51,102,255),0 0 20px rgb(51,102,255)}.clickable-area .alert-gradient.alert-success{color:#155724;border-color:#1557244d;background:linear-gradient(105deg,#d8f0dd,#f6fcf7 68%,#fff);box-shadow:0 5px 12px #0000001a,0 14px 30px #1557241a}.clickable-area .alert-gradient.alert-success .alert-icon{color:#155724;background-color:#c9e8d1}.clickable-area .alert-gradient.alert-success .btn-dismiss{color:#155724}.clickable-area .alert-gradient.alert-success .btn-dismiss:hover{text-shadow:0 0 10px rgb(48,162,77),0 0 20px rgb(48,162,77)}.clickable-area .alert-gradient.alert-warning{color:#856404;border-color:#8564044d;background:linear-gradient(105deg,#fff0c0,#fffbed 68%,#fff);box-shadow:0 5px 12px #0000001a,0 14px 30px #8564041a}.clickable-area .alert-gradient.alert-warning .alert-icon{color:#856404;background-color:#ffe599}.clickable-area .alert-gradient.alert-warning .btn-dismiss{color:#856404}.clickable-area .alert-gradient.alert-warning .btn-dismiss:hover{text-shadow:0 0 10px rgb(179,134,0),0 0 20px rgb(179,134,0)}.clickable-area .alert-gradient.alert-error{color:#721c24;border-color:#721c244d;background:linear-gradient(105deg,#fadcdf,#fff7f8 68%,#fff);box-shadow:0 5px 12px #0000001a,0 14px 30px #721c241a}.clickable-area .alert-gradient.alert-error .alert-icon{color:#721c24;background-color:#f7ccd1}.clickable-area .alert-gradient.alert-error .btn-dismiss{color:#721c24}.clickable-area .alert-gradient.alert-error .btn-dismiss:hover{text-shadow:0 0 10px rgb(255,76,89),0 0 20px rgb(255,76,89)}@media(prefers-reduced-motion:reduce){.clickable-area,.clickable-area *{transition-duration:1ms!important;animation-duration:1ms!important}}@keyframes alert-content-in{0%{opacity:0}to{opacity:1}}@keyframes alert-content-out{to{opacity:0}}@keyframes alert-enter-dot{0%{transform:scale(0);opacity:0;border-width:0}to{transform:none;opacity:1;border-width:1px}}@keyframes alert-enter-burst{0%{transform:scale(.72);opacity:0;border-width:0}to{transform:scale(1);opacity:1;border-width:1px}}@keyframes alert-enter-drop{0%{transform:translateY(-48px) scale(.98);opacity:0;border-width:0}64%{transform:translateY(5px) scale(1.01);opacity:1;border-width:1px}82%{transform:translateY(-2px) scale(.995)}to{transform:translateY(0) scale(1);opacity:1;border-width:1px}}@keyframes alert-enter-slide-right{0%{transform:translate(42px);opacity:0;border-width:0}to{transform:translate(0);opacity:1;border-width:1px}}@keyframes alert-enter-slide-left{0%{transform:translate(-42px);opacity:0;border-width:0}to{transform:translate(0);opacity:1;border-width:1px}}@keyframes alert-enter-unfold{0%{transform:scaleY(.02);opacity:0;border-width:0}to{transform:scaleY(1);opacity:1;border-width:1px}}@keyframes alert-leave-dot{to{transform:scale(0);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}@keyframes alert-leave-burst{to{transform:scale(.82);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}@keyframes alert-leave-drop{to{transform:translateY(18px) scale(.98);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}@keyframes alert-leave-slide-right{to{transform:translate(28px);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}@keyframes alert-leave-slide-left{to{transform:translate(-28px);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}@keyframes alert-leave-unfold{to{transform:scaleY(.04);opacity:0;height:0;padding-top:0;padding-bottom:0;border-width:0;margin-top:-5px}}\n"] }] }], propDecorators: { alertParams: [{ type: i0.Input, args: [{ isSignal: true, alias: "alertParams", required: true }] }], entryAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "entryAnimation", required: true }] }], alertAppearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "alertAppearance", required: true }] }], container: [{ type: i0.ViewChild, args: ['container', { isSignal: true }] }] } }); class AlertsContainerComponent { constructor() { this.entryAnimation = input(AlertEntryAnimation.DOT, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "entryAnimation" }] : /* istanbul ignore next */ [])); this.alertAppearance = input(AlertAppearance.CLASSIC, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "alertAppearance" }] : /* istanbul ignore next */ [])); this.alerts = input([], /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "alerts" }] : /* istanbul ignore next */ [])); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: AlertsContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: AlertsContainerComponent, isStandalone: true, selector: "magic-alerts", inputs: { entryAnimation: { classPropertyName: "entryAnimation", publicName: "entryAnimation", isSignal: true, isRequired: false, transformFunction: null }, alertAppearance: { classPropertyName: "alertAppearance", publicName: "alertAppearance", isSignal: true, isRequired: false, transformFunction: null }, alerts: { classPropertyName: "alerts", publicName: "alerts", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<link href=\"https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap\" rel=\"stylesheet\">\n<link href=\"https://use.fontawesome.com/releases/v5.3.1/css/all.css\" rel=\"stylesheet\" integrity=\"sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU\" crossorigin=\"anonymous\">\n\n<!-- Alerts Container -->\n<div id=\"mk-magic-messages\" class=\"alerts-container\">\n\t@for (alertParams of alerts(); track alertParams.id) {\n\t\t<app-alert\n\t\t\t[alertParams]=\"alertParams\"\n\t\t\t[entryAnimation]=\"entryAnimation()\"\n\t\t\t[alertAppearance]=\"alertAppearance()\">\n\t\t</app-alert>\n\t}\n</div>\n", styles: ["#mk-magic-messages.alerts-container{position:fixed;top:0;left:15px;right:15px;z-index:20000}@media(min-width:768px){#mk-magic-messages.alerts-container{left:10%;right:10%}}@media(min-width:992px){#mk-magic-messages.alerts-container{left:20%;right:20%}}@media(min-width:1200px){#mk-magic-messages.alerts-container{left:25%;right:25%}}@media(min-width:1500px){#mk-magic-messages.alerts-container{left:30%;right:30%}}\n"], dependencies: [{ kind: "component", type: AlertComponent, selector: "app-alert", inputs: ["alertParams", "entryAnimation", "alertAppearance"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: AlertsContainerComponent, decorators: [{ type: Component, args: [{ selector: 'magic-alerts', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AlertComponent], template: "<link href=\"https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap\" rel=\"stylesheet\">\n<link href=\"https://use.fontawesome.com/releases/v5.3.1/css/all.css\" rel=\"stylesheet\" integrity=\"sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU\" crossorigin=\"anonymous\">\n\n<!-- Alerts Container -->\n<div id=\"mk-magic-messages\" class=\"alerts-container\">\n\t@for (alertParams of alerts(); track alertParams.id) {\n\t\t<app-alert\n\t\t\t[alertParams]=\"alertParams\"\n\t\t\t[entryAnimation]=\"entryAnimation()\"\n\t\t\t[alertAppearance]=\"alertAppearance()\">\n\t\t</app-alert>\n\t}\n</div>\n", styles: ["#mk-magic-messages.alerts-container{position:fixed;top:0;left:15px;right:15px;z-index:20000}@media(min-width:768px){#mk-magic-messages.alerts-container{left:10%;right:10%}}@media(min-width:992px){#mk-magic-messages.alerts-container{left:20%;right:20%}}@media(min-width:1200px){#mk-magic-messages.alerts-container{left:25%;right:25%}}@media(min-width:1500px){#mk-magic-messages.alerts-container{left:30%;right:30%}}\n"] }] }], propDecorators: { entryAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "entryAnimation", required: false }] }], alertAppearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "alertAppearance", required: false }] }], alerts: [{ type: i0.Input, args: [{ isSignal: true, alias: "alerts", required: false }] }] } }); const DEFAULT_MAGIC_ALERTS_CONFIG = { entryAnimation: AlertEntryAnimation.DOT, alertAppearance: AlertAppearance.CLASSIC }; const MAGIC_ALERTS_CONFIG = new InjectionToken('MAGIC_ALERTS_CONFIG', { providedIn: 'root', factory: () => DEFAULT_MAGIC_ALERTS_CONFIG }); function provideMagicAlerts(config = {}) { return makeEnvironmentProviders([ { provide: MAGIC_ALERTS_CONFIG, useValue: { ...DEFAULT_MAGIC_ALERTS_CONFIG, ...config } } ]); } class AlertsService { constructor() { this.alertsStore = inject(AlertsStore); this.applicationRef = inject(ApplicationRef); this.injector = inject(Injector); this.config = inject(MAGIC_ALERTS_CONFIG); this.renderQueued = false; this.initializeAlertsComponent(); } initializeAlertsComponent() { // Create a div element and append it to the document body const hostElement = document.createElement('div'); document.body.appendChild(hostElement); // Create AlertsContainerComponent and attach it to the DOM this.alertsComponentRef = createComponent(AlertsContainerComponent, { hostElement, environmentInjector: this.applicationRef.injector, elementInjector: this.injector }); this.alertsComponentRef.setInput('entryAnimation', this.config.entryAnimation); this.alertsComponentRef.setInput('alertAppearance', this.config.alertAppearance); this.alertsComponentRef.setInput('alerts', this.alertsStore.alerts()); // Attach the AlertsContainerComponent to the application this.applicationRef.attachView(this.alertsComponentRef.hostView); this.alertsComponentRef.changeDetectorRef.detectChanges(); } showInfo(text, dismissTimeInMillis = 10_000) { this.alertsStore.addAlert(text, 'info', dismissTimeInMillis); this.syncAlertsToContainer(); this.queueContainerRender(); } showSuccess(text, dismissTimeInMillis = 4_000) { this.alertsStore.addAlert(text, 'success', dismissTimeInMillis); this.syncAlertsToContainer(); this.queueContainerRender(); } showWarning(text, dismissTimeInMillis = 10_000) { this.alertsStore.addAlert(text, 'warning', dismissTimeInMillis); this.syncAlertsToContainer(); this.queueContainerRender(); } showError(text, dismissTimeInMillis = 2_147_483_647) { this.alertsStore.addAlert(text, 'error', dismissTimeInMillis); this.syncAlertsToContainer(); this.queueContainerRender(); } setEntryAnimation(entryAnimation) { this.alertsComponentRef.setInput('entryAnimation', entryAnimation); this.queueContainerRender(); } setAlertAppearance(alertAppearance) { this.alertsComponentRef.setInput('alertAppearance', alertAppearance); this.queueContainerRender(); } clear() { this.alertsStore.dismissAll(); this.queueContainerRender(); } syncAlertsToContainer() { this.alertsComponentRef.setInput('alerts', this.alertsStore.alerts()); } queueContainerRender() { // This container is created outside the normal component tree, so input updates // need an explicit render pass to show reliably in production and zoneless apps. if (this.renderQueued) { return; } this.renderQueued = true; queueMicrotask(() => { this.renderQueued = false; this.alertsComponentRef.changeDetectorRef.detectChanges(); }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: AlertsService, deps: [], target: i0.ɵɵFactoryTarget.Service }); } static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.0", ngImport: i0, type: AlertsService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: AlertsService, decorators: [{ type: Service }], ctorParameters: () => [] }); class MockAlertsService { showInfo(text, dismissTimeInMillis = 10_000) { } showSuccess(text, dismissTimeInMillis = 4_000) { } showWarning(text, dismissTimeInMillis = 10_000) { } showError(text, dismissTimeInMillis = 2_147_483_647) { } setEntryAnimation(entryAnimation) { } setAlertAppearance(alertAppearance) { } clear() { } } /* * Public API Surface of mk-magic-alerts */ /** * Generated bundle index. Do not edit. */ export { AlertAppearance, AlertEntryAnimation, AlertsService, DEFAULT_MAGIC_ALERTS_CONFIG, MAGIC_ALERTS_CONFIG, MockAlertsService, provideMagicAlerts }; //# sourceMappingURL=mk-magic-alerts.mjs.map