ngx-dynamic-toast 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,791 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, output, inject, ElementRef, NgZone, ChangeDetectorRef, signal, computed, effect, ViewEncapsulation, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, Injectable } from '@angular/core';
3
+ import { NgTemplateOutlet, DOCUMENT } from '@angular/common';
4
+ import { DomSanitizer } from '@angular/platform-browser';
5
+
6
+ const HEIGHT = 40;
7
+ const WIDTH = 350;
8
+ const DEFAULT_ROUNDNESS = 16;
9
+ const DURATION_MS = 600;
10
+ const DURATION_S = DURATION_MS / 1000;
11
+ const DEFAULT_TOAST_DURATION = 6000;
12
+ const EXIT_DURATION = DEFAULT_TOAST_DURATION * 0.1;
13
+ const AUTO_EXPAND_DELAY = DEFAULT_TOAST_DURATION * 0.025;
14
+ const AUTO_COLLAPSE_DELAY = DEFAULT_TOAST_DURATION - 2000;
15
+ const BLUR_RATIO = 0.5;
16
+ const PILL_PADDING = 10;
17
+ const MIN_EXPAND_RATIO = 2.25;
18
+ const SWAP_COLLAPSE_MS = 200;
19
+ const HEADER_EXIT_MS = DURATION_MS * 0.7;
20
+
21
+ const baseSvg = (title, body, extra) => `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ${extra ?? ""}><title>${title}</title>${body}</svg>`;
22
+ const ICONS = {
23
+ arrowRight: baseSvg("Arrow Right", `<path d="M5 12h14" /><path d="m12 5 7 7-7 7" />`),
24
+ lifeBuoy: baseSvg("Life Buoy", `<circle cx="12" cy="12" r="10" /><path d="m4.93 4.93 4.24 4.24" /><path d="m14.83 9.17 4.24-4.24" /><path d="m14.83 14.83 4.24 4.24" /><path d="m9.17 14.83-4.24 4.24" /><circle cx="12" cy="12" r="4" />`),
25
+ loaderCircle: (extra) => baseSvg("Loader Circle", `<path d="M21 12a9 9 0 1 1-6.219-8.56" />`, extra),
26
+ x: baseSvg("X", `<path d="M18 6 6 18" /><path d="m6 6 12 12" />`),
27
+ circleAlert: baseSvg("Circle Alert", `<circle cx="12" cy="12" r="10" /><line x1="12" x2="12" y1="8" y2="12" /><line x1="12" x2="12.01" y1="16" y2="16" />`),
28
+ check: baseSvg("Check", `<path d="M20 6 9 17l-5-5" />`),
29
+ };
30
+
31
+ class DynamicToastComponent {
32
+ toast = input.required(...(ngDevMode ? [{ debugName: "toast" }] : []));
33
+ pillAlign = input("left", ...(ngDevMode ? [{ debugName: "pillAlign" }] : []));
34
+ expandEdge = input("bottom", ...(ngDevMode ? [{ debugName: "expandEdge" }] : []));
35
+ canExpand = input(true, ...(ngDevMode ? [{ debugName: "canExpand" }] : []));
36
+ interruptKey = input(undefined, ...(ngDevMode ? [{ debugName: "interruptKey" }] : []));
37
+ dismissed = output();
38
+ entered = output();
39
+ left = output();
40
+ HEIGHT = HEIGHT;
41
+ WIDTH = WIDTH;
42
+ sanitizer = inject(DomSanitizer);
43
+ hostEl = inject(ElementRef);
44
+ ngZone = inject(NgZone);
45
+ cdr = inject(ChangeDetectorRef);
46
+ hasMeasured = false;
47
+ roHeader = null;
48
+ roContent = null;
49
+ headerExitTimer = null;
50
+ autoExpandTimer = null;
51
+ autoCollapseTimer = null;
52
+ swapTimer = null;
53
+ lastRefreshKey;
54
+ pendingSwap = null;
55
+ pointerStartY = null;
56
+ ready = signal(false, ...(ngDevMode ? [{ debugName: "ready" }] : []));
57
+ isExpanded = signal(true, ...(ngDevMode ? [{ debugName: "isExpanded" }] : [])); // Default to expanded if description exists
58
+ pillWidth = signal(0, ...(ngDevMode ? [{ debugName: "pillWidth" }] : []));
59
+ contentHeight = signal(0, ...(ngDevMode ? [{ debugName: "contentHeight" }] : []));
60
+ // view = signal<View>({
61
+ // title: "",
62
+ // description: "",
63
+ // state: "success",
64
+ // iconSvg: null,
65
+ // fill: "#FFFFFF",
66
+ // });
67
+ // Use a default toast state to avoid NG0950 during initialization
68
+ view = computed(() => {
69
+ try {
70
+ const t = this.toast();
71
+ return {
72
+ title: t.title,
73
+ description: t.description,
74
+ contentTemplate: t.contentTemplate,
75
+ state: t.state,
76
+ iconSvg: t.iconSvg,
77
+ styles: t.styles,
78
+ button: t.button,
79
+ fill: t.fill ?? "#151515",
80
+ };
81
+ }
82
+ catch (e) {
83
+ // Return safe default if input is not yet bound
84
+ return {
85
+ title: "",
86
+ state: "info",
87
+ fill: "#151515",
88
+ };
89
+ }
90
+ }, ...(ngDevMode ? [{ debugName: "view" }] : []));
91
+ // headerLayerCurrent = signal<HeaderLayer>({
92
+ // key: "",
93
+ // view: this.view(),
94
+ // });
95
+ // headerLayerPrev = signal<HeaderLayer | null>(null);
96
+ filterId = `dt-gooey-${Math.random().toString(36).slice(2, 8)}`;
97
+ hasDesc = computed(() => {
98
+ const v = this.view();
99
+ return (Boolean(v.description) || Boolean(v.contentTemplate) || Boolean(v.button));
100
+ }, ...(ngDevMode ? [{ debugName: "hasDesc" }] : []));
101
+ isLoading = computed(() => this.view().state === "loading", ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
102
+ allowExpand = computed(() => {
103
+ if (this.isLoading())
104
+ return false;
105
+ const interrupt = this.interruptKey();
106
+ const id = this.toast().id;
107
+ return this.canExpand() ?? (!interrupt || interrupt === id);
108
+ }, ...(ngDevMode ? [{ debugName: "allowExpand" }] : []));
109
+ open = computed(() => this.hasDesc() && this.isExpanded() && !this.isLoading(), ...(ngDevMode ? [{ debugName: "open" }] : []));
110
+ resolvedRoundness = computed(() => {
111
+ try {
112
+ return Math.max(0, this.toast().roundness ?? DEFAULT_ROUNDNESS);
113
+ }
114
+ catch {
115
+ return DEFAULT_ROUNDNESS;
116
+ }
117
+ }, ...(ngDevMode ? [{ debugName: "resolvedRoundness" }] : []));
118
+ blur = computed(() => this.resolvedRoundness() * BLUR_RATIO, ...(ngDevMode ? [{ debugName: "blur" }] : []));
119
+ minExpanded = computed(() => HEIGHT * MIN_EXPAND_RATIO, ...(ngDevMode ? [{ debugName: "minExpanded" }] : []));
120
+ rawExpanded = computed(() => {
121
+ const min = this.minExpanded();
122
+ try {
123
+ if (!this.hasDesc())
124
+ return min;
125
+ return Math.max(min, HEIGHT + this.contentHeight());
126
+ }
127
+ catch {
128
+ return min;
129
+ }
130
+ }, ...(ngDevMode ? [{ debugName: "rawExpanded" }] : []));
131
+ frozenExpanded = signal(HEIGHT * MIN_EXPAND_RATIO, ...(ngDevMode ? [{ debugName: "frozenExpanded" }] : []));
132
+ expanded = computed(() => this.open() ? this.rawExpanded() : this.frozenExpanded(), ...(ngDevMode ? [{ debugName: "expanded" }] : []));
133
+ svgHeight = computed(() => this.hasDesc() ? Math.max(this.expanded(), this.minExpanded()) : HEIGHT, ...(ngDevMode ? [{ debugName: "svgHeight" }] : []));
134
+ expandedContent = computed(() => Math.max(0, this.expanded() - HEIGHT), ...(ngDevMode ? [{ debugName: "expandedContent" }] : []));
135
+ resolvedPillWidth = computed(() => Math.max(this.pillWidth() || HEIGHT, HEIGHT), ...(ngDevMode ? [{ debugName: "resolvedPillWidth" }] : []));
136
+ pillHeight = computed(() => HEIGHT + this.blur() * 3, ...(ngDevMode ? [{ debugName: "pillHeight" }] : []));
137
+ pillX = computed(() => {
138
+ const w = this.resolvedPillWidth();
139
+ const pos = this.pillAlign();
140
+ if (pos === "right")
141
+ return WIDTH - w;
142
+ if (pos === "center")
143
+ return (WIDTH - w) / 2;
144
+ return 0;
145
+ }, ...(ngDevMode ? [{ debugName: "pillX" }] : []));
146
+ pillPath = computed(() => {
147
+ const w = this.resolvedPillWidth();
148
+ const h = HEIGHT;
149
+ const r = this.resolvedRoundness();
150
+ const align = this.pillAlign();
151
+ const open = this.open();
152
+ const x = this.pillX();
153
+ // Helper for rounded corner arc relative
154
+ const arc = (dx, dy) => `a ${r} ${r} 0 0 1 ${dx} ${dy}`;
155
+ let d = "";
156
+ // Start at Top-Left of the pill (relative to x)
157
+ // We'll draw in absolute coordinates or relative? Path commands usually absolute M x y is easiest.
158
+ // Top Left Corner
159
+ d += `M ${x} ${h - r}`; // Start before top-left corner? No, let's start top-left.
160
+ // Actually, standard rect path:
161
+ // Move to x, y+r
162
+ // Arc to x+r, y
163
+ // Line to x+w-r, y
164
+ // Arc to x+w, y+r
165
+ // Line to x+w, y+h-r
166
+ // Arc to x+w-r, y+h
167
+ // Line to x+r, y+h
168
+ // Arc to x, y+h-r
169
+ // Close
170
+ // Top Left
171
+ d += `M ${x} ${r} ${arc(r, -r)}`;
172
+ // Top Right
173
+ d += `L ${x + w - r} 0 ${arc(r, r)}`;
174
+ // Bottom Right
175
+ if (open && align === "right") {
176
+ d += `L ${x + w} ${h}`; // Sharp corner
177
+ }
178
+ else {
179
+ d += `L ${x + w} ${h - r} ${arc(-r, r)}`; // Rounded
180
+ }
181
+ // Bottom Left
182
+ if (open && align === "left") {
183
+ d += `L ${x} ${h}`; // Sharp corner
184
+ }
185
+ else {
186
+ d += `L ${x + r} ${h} ${arc(-r, -r)}`; // Rounded
187
+ }
188
+ d += "Z";
189
+ return d;
190
+ }, ...(ngDevMode ? [{ debugName: "pillPath" }] : []));
191
+ headerTransform = computed(() => {
192
+ const open = this.open();
193
+ const expand = this.expandEdge();
194
+ const ty = open ? (expand === "bottom" ? 3 : -3) : 0;
195
+ const scale = open ? 0.9 : 1;
196
+ return `translateY(${ty}px) scale(${scale})`;
197
+ }, ...(ngDevMode ? [{ debugName: "headerTransform" }] : []));
198
+ bodyPath = computed(() => {
199
+ const w = WIDTH;
200
+ const h = this.open() ? this.expandedContent() : 0;
201
+ const r = this.resolvedRoundness();
202
+ const y = HEIGHT - 1; // 1px overlap to ensure connection
203
+ const align = this.pillAlign();
204
+ if (h <= 0)
205
+ return "";
206
+ // Helper for rounded corner arc
207
+ // A rx ry x-axis-rotation large-arc-flag sweep-flag x y
208
+ const arc = (dx, dy) => `a ${r} ${r} 0 0 1 ${dx} ${dy}`;
209
+ let d = "";
210
+ // Top Left
211
+ if (align === "left") {
212
+ d += `M 0 ${y}`; // Sharp corner
213
+ }
214
+ else {
215
+ d += `M 0 ${y + r} ${arc(r, -r)}`; // Rounded start
216
+ }
217
+ // Top Right
218
+ if (align === "right") {
219
+ d += `L ${w} ${y}`; // Sharp line to corner
220
+ }
221
+ else {
222
+ d += `L ${w - r} ${y} ${arc(r, r)}`; // Line then rounded
223
+ }
224
+ // Bottom Right (Always rounded)
225
+ d += `L ${w} ${y + h - r} ${arc(-r, r)}`;
226
+ // Bottom Left (Always rounded)
227
+ d += `L ${r} ${y + h} ${arc(-r, -r)}`;
228
+ // Close path
229
+ d += "Z";
230
+ return d;
231
+ }, ...(ngDevMode ? [{ debugName: "bodyPath" }] : []));
232
+ constructor() {
233
+ // If no description, collapse immediately
234
+ effect(() => {
235
+ if (!this.hasDesc()) {
236
+ this.isExpanded.set(false);
237
+ }
238
+ else {
239
+ // If has description, start expanded by default
240
+ // But we might want to respect auto-collapse later
241
+ this.isExpanded.set(true);
242
+ }
243
+ }, { allowSignalWrites: true });
244
+ queueMicrotask(() => {
245
+ this.ready.set(true);
246
+ this.ensureMeasurements();
247
+ });
248
+ }
249
+ // private applyView(next: View) {
250
+ // const prev = this.view();
251
+ // const headerKey = `${next.state}-${next.title}`;
252
+ // const prevKey = `${prev.state}-${prev.title}`;
253
+ // this.view.set(next);
254
+ // if (headerKey !== prevKey) {
255
+ // const currentLayer: HeaderLayer = { key: headerKey, view: next };
256
+ // const prevLayer: HeaderLayer = { key: prevKey, view: prev };
257
+ // this.headerLayerPrev.set(prevLayer);
258
+ // this.headerLayerCurrent.set(currentLayer);
259
+ // if (this.headerExitTimer) window.clearTimeout(this.headerExitTimer);
260
+ // this.headerExitTimer = window.setTimeout(() => {
261
+ // this.headerExitTimer = null;
262
+ // this.headerLayerPrev.set(null);
263
+ // }, HEADER_EXIT_MS);
264
+ // } else {
265
+ // this.headerLayerCurrent.set({ key: headerKey, view: next });
266
+ // }
267
+ // }
268
+ ngOnDestroy() {
269
+ this.roHeader?.disconnect();
270
+ this.roContent?.disconnect();
271
+ if (this.headerExitTimer)
272
+ window.clearTimeout(this.headerExitTimer);
273
+ if (this.autoExpandTimer)
274
+ window.clearTimeout(this.autoExpandTimer);
275
+ if (this.autoCollapseTimer)
276
+ window.clearTimeout(this.autoCollapseTimer);
277
+ if (this.swapTimer)
278
+ window.clearTimeout(this.swapTimer);
279
+ }
280
+ ensureMeasurements() {
281
+ if (this.hasMeasured)
282
+ return;
283
+ this.hasMeasured = true;
284
+ const root = this.hostEl.nativeElement;
285
+ const inner = root.querySelector("[data-dt-header-inner][data-layer='current']");
286
+ const header = root.querySelector("[data-dt-header]");
287
+ const content = root.querySelector("[data-dt-description]");
288
+ if (!inner || !header)
289
+ return;
290
+ // Throttled measurement
291
+ let rafHeader = null;
292
+ const measureHeader = () => {
293
+ if (rafHeader)
294
+ return;
295
+ // Run outside angular to avoid infinite CD loops from RO
296
+ this.ngZone.runOutsideAngular(() => {
297
+ rafHeader = requestAnimationFrame(() => {
298
+ rafHeader = null;
299
+ const cs = getComputedStyle(header);
300
+ const pad = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight);
301
+ const w = inner.scrollWidth + pad + PILL_PADDING;
302
+ // Only update if difference is significant to stop 1px loops
303
+ if (Math.abs(w - this.pillWidth()) > 1.5) {
304
+ this.pillWidth.set(w);
305
+ this.cdr.detectChanges(); // Local detect changes only
306
+ }
307
+ });
308
+ });
309
+ };
310
+ let rafContent = null;
311
+ const measureContent = () => {
312
+ const el = root.querySelector("[data-dt-description]");
313
+ if (!el)
314
+ return;
315
+ if (rafContent)
316
+ return;
317
+ this.ngZone.runOutsideAngular(() => {
318
+ rafContent = requestAnimationFrame(() => {
319
+ rafContent = null;
320
+ if (Math.abs(el.scrollHeight - this.contentHeight()) > 1.5) {
321
+ this.contentHeight.set(el.scrollHeight);
322
+ this.cdr.detectChanges();
323
+ }
324
+ });
325
+ });
326
+ };
327
+ measureHeader();
328
+ measureContent();
329
+ this.roHeader = new ResizeObserver(() => measureHeader());
330
+ this.roHeader.observe(inner);
331
+ if (content) {
332
+ this.roContent = new ResizeObserver(() => measureContent());
333
+ this.roContent.observe(content);
334
+ }
335
+ }
336
+ resolvedIcon(v) {
337
+ const icon = v.iconSvg ??
338
+ (v.state === "success"
339
+ ? ICONS.check
340
+ : v.state === "loading"
341
+ ? ICONS.loaderCircle('data-dt-icon="spin" aria-hidden="true"')
342
+ : v.state === "error"
343
+ ? ICONS.x
344
+ : v.state === "warning"
345
+ ? ICONS.circleAlert
346
+ : v.state === "info"
347
+ ? ICONS.lifeBuoy
348
+ : ICONS.arrowRight);
349
+ return this.sanitizer.bypassSecurityTrustHtml(icon);
350
+ }
351
+ handleEnter() {
352
+ this.entered.emit(this.toast().id);
353
+ if (this.hasDesc())
354
+ this.isExpanded.set(true);
355
+ }
356
+ handleLeave() {
357
+ this.left.emit(this.toast().id);
358
+ this.isExpanded.set(false);
359
+ }
360
+ handleTransitionEnd(e) {
361
+ if (e.propertyName !== "height" && e.propertyName !== "transform")
362
+ return;
363
+ if (this.open())
364
+ return;
365
+ const pending = this.pendingSwap;
366
+ if (!pending)
367
+ return;
368
+ if (this.swapTimer) {
369
+ window.clearTimeout(this.swapTimer);
370
+ this.swapTimer = null;
371
+ }
372
+ // this.applyView(pending.payload);
373
+ this.pendingSwap = null;
374
+ }
375
+ handleButtonClick(e) {
376
+ e.preventDefault();
377
+ e.stopPropagation();
378
+ this.view().button?.onClick();
379
+ }
380
+ handlePointerDown(e) {
381
+ if (this.toast().exiting)
382
+ return;
383
+ const target = e.target;
384
+ if (target.closest("[data-dt-button]"))
385
+ return;
386
+ this.pointerStartY = e.clientY;
387
+ const el = e.currentTarget;
388
+ const SWIPE_DISMISS = 30;
389
+ const SWIPE_MAX = 20;
390
+ const onMove = (ev) => {
391
+ if (this.pointerStartY == null)
392
+ return;
393
+ const dy = ev.clientY - this.pointerStartY;
394
+ const sign = dy > 0 ? 1 : -1;
395
+ const clamped = Math.min(Math.abs(dy), SWIPE_MAX) * sign;
396
+ el.style.transform = `translateY(${clamped}px)`;
397
+ };
398
+ const onUp = (ev) => {
399
+ if (this.pointerStartY == null)
400
+ return;
401
+ const dy = ev.clientY - this.pointerStartY;
402
+ this.pointerStartY = null;
403
+ el.style.transform = "";
404
+ el.removeEventListener("pointermove", onMove);
405
+ el.removeEventListener("pointerup", onUp);
406
+ if (Math.abs(dy) > SWIPE_DISMISS) {
407
+ this.dismissed.emit(this.toast().id);
408
+ }
409
+ else if (Math.abs(dy) < 5) {
410
+ // It's a tap
411
+ this.handleTap();
412
+ }
413
+ };
414
+ el.setPointerCapture(e.pointerId);
415
+ el.addEventListener("pointermove", onMove, { passive: true });
416
+ el.addEventListener("pointerup", onUp, { passive: true });
417
+ }
418
+ handleTap() {
419
+ if (this.hasDesc()) {
420
+ if (this.isExpanded()) {
421
+ // 1 click to collapse if it has description and is open
422
+ this.isExpanded.set(false);
423
+ }
424
+ else {
425
+ // If already collapsed, another click closes the toast
426
+ this.dismissed.emit(this.toast().id);
427
+ }
428
+ }
429
+ else {
430
+ // If no description, a click simply closes it
431
+ this.dismissed.emit(this.toast().id);
432
+ }
433
+ }
434
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: DynamicToastComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
435
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: DynamicToastComponent, isStandalone: true, selector: "dt-toast", inputs: { toast: { classPropertyName: "toast", publicName: "toast", isSignal: true, isRequired: true, transformFunction: null }, pillAlign: { classPropertyName: "pillAlign", publicName: "pillAlign", isSignal: true, isRequired: false, transformFunction: null }, expandEdge: { classPropertyName: "expandEdge", publicName: "expandEdge", isSignal: true, isRequired: false, transformFunction: null }, canExpand: { classPropertyName: "canExpand", publicName: "canExpand", isSignal: true, isRequired: false, transformFunction: null }, interruptKey: { classPropertyName: "interruptKey", publicName: "interruptKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed", entered: "entered", left: "left" }, ngImport: i0, template: "<button\n type=\"button\"\n data-dt-toast\n [attr.data-ready]=\"ready()\"\n [attr.data-expanded]=\"open()\"\n [attr.data-exiting]=\"toast().exiting || false\"\n [attr.data-edge]=\"expandEdge()\"\n [attr.data-position]=\"pillAlign()\"\n [attr.data-state]=\"view().state\"\n [class]=\"toast().className || ''\"\n [style.--_h]=\"HEIGHT + 'px'\"\n [style.--_pw]=\"(pillWidth() || HEIGHT) + 'px'\"\n [style.--_px]=\"pillX() + 'px'\"\n [style.--_ht]=\"headerTransform()\"\n [style.--_co]=\"open() ? 1 : 0\"\n [style.animation-duration]=\"(toast().duration || 6000) + 'ms'\"\n (mouseenter)=\"handleEnter()\"\n (mouseleave)=\"handleLeave()\"\n (transitionend)=\"handleTransitionEnd($event)\"\n (pointerdown)=\"handlePointerDown($event)\"\n>\n <div\n data-dt-canvas\n [attr.data-edge]=\"expandEdge()\"\n [style.filter]=\"'url(#' + filterId + ')'\"\n >\n <svg\n data-dt-svg\n [attr.width]=\"WIDTH\"\n [attr.height]=\"svgHeight()\"\n [attr.viewBox]=\"'0 0 ' + WIDTH + ' ' + svgHeight()\"\n >\n <defs>\n <filter\n [id]=\"filterId\"\n x=\"-20%\"\n y=\"-20%\"\n width=\"140%\"\n height=\"140%\"\n colorInterpolationFilters=\"sRGB\"\n >\n <feGaussianBlur\n in=\"SourceGraphic\"\n [attr.stdDeviation]=\"blur()\"\n result=\"blur\"\n />\n <feColorMatrix\n in=\"blur\"\n mode=\"matrix\"\n values=\"1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10\"\n result=\"goo\"\n />\n <feComposite in=\"SourceGraphic\" in2=\"goo\" operator=\"atop\" />\n </filter>\n </defs>\n\n <path\n data-dt-pill\n [attr.d]=\"pillPath()\"\n [attr.fill]=\"view().fill\"\n />\n\n <path\n data-dt-body\n [attr.d]=\"bodyPath()\"\n [attr.fill]=\"view().fill\"\n [attr.opacity]=\"open() ? 1 : 0\"\n />\n </svg>\n </div>\n\n <div #headerRef data-dt-header [attr.data-edge]=\"expandEdge()\">\n <div data-dt-header-stack>\n <div\n #innerRef\n data-dt-header-inner\n data-layer=\"current\"\n >\n <div\n data-dt-badge\n [attr.data-state]=\"view().state\"\n [class]=\"view().styles?.badge || ''\"\n [innerHTML]=\"resolvedIcon(view())\"\n ></div>\n <span\n data-dt-title\n [attr.data-state]=\"view().state\"\n [class]=\"view().styles?.title || ''\"\n >\n {{ view().title }}\n </span>\n </div>\n\n <!-- @if (headerLayerPrev(); as prev) {\n <div data-dt-header-inner data-layer=\"prev\" data-exiting=\"true\">\n <div\n data-dt-badge\n [attr.data-state]=\"prev.view.state\"\n [class]=\"prev.view.styles?.badge || ''\"\n [innerHTML]=\"resolvedIcon(prev.view)\"\n ></div>\n <span\n data-dt-title\n [attr.data-state]=\"prev.view.state\"\n [class]=\"prev.view.styles?.title || ''\"\n >\n {{ prev.view.title }}\n </span>\n </div>\n } -->\n </div>\n </div>\n\n @if (hasDesc()) {\n <div\n data-dt-content\n [attr.data-edge]=\"expandEdge()\"\n [attr.data-visible]=\"open()\"\n >\n <div\n #contentRef\n data-dt-description\n [class]=\"view().styles?.description || ''\"\n >\n @if (view().description) {\n <span>{{ view().description }}</span>\n }\n @if (view().contentTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"view().contentTemplate\"\n ></ng-container>\n }\n @if (view().button) {\n <a\n href=\"#\"\n data-dt-button\n [attr.data-state]=\"view().state\"\n [class]=\"view().styles?.button || ''\"\n (click)=\"handleButtonClick($event)\"\n >\n {{ view().button?.title }}\n </a>\n }\n </div>\n </div>\n }\n</button>\n\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
436
+ }
437
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: DynamicToastComponent, decorators: [{
438
+ type: Component,
439
+ args: [{ selector: "dt-toast", standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<button\n type=\"button\"\n data-dt-toast\n [attr.data-ready]=\"ready()\"\n [attr.data-expanded]=\"open()\"\n [attr.data-exiting]=\"toast().exiting || false\"\n [attr.data-edge]=\"expandEdge()\"\n [attr.data-position]=\"pillAlign()\"\n [attr.data-state]=\"view().state\"\n [class]=\"toast().className || ''\"\n [style.--_h]=\"HEIGHT + 'px'\"\n [style.--_pw]=\"(pillWidth() || HEIGHT) + 'px'\"\n [style.--_px]=\"pillX() + 'px'\"\n [style.--_ht]=\"headerTransform()\"\n [style.--_co]=\"open() ? 1 : 0\"\n [style.animation-duration]=\"(toast().duration || 6000) + 'ms'\"\n (mouseenter)=\"handleEnter()\"\n (mouseleave)=\"handleLeave()\"\n (transitionend)=\"handleTransitionEnd($event)\"\n (pointerdown)=\"handlePointerDown($event)\"\n>\n <div\n data-dt-canvas\n [attr.data-edge]=\"expandEdge()\"\n [style.filter]=\"'url(#' + filterId + ')'\"\n >\n <svg\n data-dt-svg\n [attr.width]=\"WIDTH\"\n [attr.height]=\"svgHeight()\"\n [attr.viewBox]=\"'0 0 ' + WIDTH + ' ' + svgHeight()\"\n >\n <defs>\n <filter\n [id]=\"filterId\"\n x=\"-20%\"\n y=\"-20%\"\n width=\"140%\"\n height=\"140%\"\n colorInterpolationFilters=\"sRGB\"\n >\n <feGaussianBlur\n in=\"SourceGraphic\"\n [attr.stdDeviation]=\"blur()\"\n result=\"blur\"\n />\n <feColorMatrix\n in=\"blur\"\n mode=\"matrix\"\n values=\"1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10\"\n result=\"goo\"\n />\n <feComposite in=\"SourceGraphic\" in2=\"goo\" operator=\"atop\" />\n </filter>\n </defs>\n\n <path\n data-dt-pill\n [attr.d]=\"pillPath()\"\n [attr.fill]=\"view().fill\"\n />\n\n <path\n data-dt-body\n [attr.d]=\"bodyPath()\"\n [attr.fill]=\"view().fill\"\n [attr.opacity]=\"open() ? 1 : 0\"\n />\n </svg>\n </div>\n\n <div #headerRef data-dt-header [attr.data-edge]=\"expandEdge()\">\n <div data-dt-header-stack>\n <div\n #innerRef\n data-dt-header-inner\n data-layer=\"current\"\n >\n <div\n data-dt-badge\n [attr.data-state]=\"view().state\"\n [class]=\"view().styles?.badge || ''\"\n [innerHTML]=\"resolvedIcon(view())\"\n ></div>\n <span\n data-dt-title\n [attr.data-state]=\"view().state\"\n [class]=\"view().styles?.title || ''\"\n >\n {{ view().title }}\n </span>\n </div>\n\n <!-- @if (headerLayerPrev(); as prev) {\n <div data-dt-header-inner data-layer=\"prev\" data-exiting=\"true\">\n <div\n data-dt-badge\n [attr.data-state]=\"prev.view.state\"\n [class]=\"prev.view.styles?.badge || ''\"\n [innerHTML]=\"resolvedIcon(prev.view)\"\n ></div>\n <span\n data-dt-title\n [attr.data-state]=\"prev.view.state\"\n [class]=\"prev.view.styles?.title || ''\"\n >\n {{ prev.view.title }}\n </span>\n </div>\n } -->\n </div>\n </div>\n\n @if (hasDesc()) {\n <div\n data-dt-content\n [attr.data-edge]=\"expandEdge()\"\n [attr.data-visible]=\"open()\"\n >\n <div\n #contentRef\n data-dt-description\n [class]=\"view().styles?.description || ''\"\n >\n @if (view().description) {\n <span>{{ view().description }}</span>\n }\n @if (view().contentTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"view().contentTemplate\"\n ></ng-container>\n }\n @if (view().button) {\n <a\n href=\"#\"\n data-dt-button\n [attr.data-state]=\"view().state\"\n [class]=\"view().styles?.button || ''\"\n (click)=\"handleButtonClick($event)\"\n >\n {{ view().button?.title }}\n </a>\n }\n </div>\n </div>\n }\n</button>\n\n" }]
440
+ }], ctorParameters: () => [], propDecorators: { toast: [{ type: i0.Input, args: [{ isSignal: true, alias: "toast", required: true }] }], pillAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "pillAlign", required: false }] }], expandEdge: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandEdge", required: false }] }], canExpand: [{ type: i0.Input, args: [{ isSignal: true, alias: "canExpand", required: false }] }], interruptKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "interruptKey", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }], entered: [{ type: i0.Output, args: ["entered"] }], left: [{ type: i0.Output, args: ["left"] }] } });
441
+
442
+ const pillAlign = (pos) => pos.includes("right") ? "right" : pos.includes("center") ? "center" : "left";
443
+ const expandDir = (pos) => pos.startsWith("top") ? "bottom" : "top";
444
+ class DynamicToastViewportComponent {
445
+ position = input("top-right", ...(ngDevMode ? [{ debugName: "position" }] : []));
446
+ offset = input(undefined, ...(ngDevMode ? [{ debugName: "offset" }] : []));
447
+ service = inject(DynamicToastService);
448
+ hovering = signal(new Set(), ...(ngDevMode ? [{ debugName: "hovering" }] : []));
449
+ activeId = signal(undefined, ...(ngDevMode ? [{ debugName: "activeId" }] : []));
450
+ latestId = computed(() => {
451
+ const list = this.service.toasts();
452
+ for (let i = list.length - 1; i >= 0; i--) {
453
+ if (!list[i].exiting)
454
+ return list[i].id;
455
+ }
456
+ return undefined;
457
+ }, ...(ngDevMode ? [{ debugName: "latestId" }] : []));
458
+ groups = computed(() => {
459
+ const toasts = this.service.toasts();
460
+ const byPos = new Map();
461
+ for (const t of toasts) {
462
+ const p = (t.position ?? this.position());
463
+ const arr = byPos.get(p);
464
+ if (arr)
465
+ arr.push(t);
466
+ else
467
+ byPos.set(p, [t]);
468
+ }
469
+ const offset = this.offset();
470
+ const off = offset === undefined
471
+ ? undefined
472
+ : typeof offset === "object"
473
+ ? offset
474
+ : { top: offset, right: offset, bottom: offset, left: offset };
475
+ const px = (v) => v === undefined ? undefined : typeof v === "number" ? `${v}px` : v;
476
+ const res = [];
477
+ for (const [pos, items] of byPos) {
478
+ const style = {};
479
+ if (off) {
480
+ if (pos.startsWith("top") && off.top !== undefined)
481
+ style.top = px(off.top);
482
+ if (pos.startsWith("bottom") && off.bottom !== undefined)
483
+ style.bottom = px(off.bottom);
484
+ if (pos.endsWith("left") && off.left !== undefined)
485
+ style.left = px(off.left);
486
+ if (pos.endsWith("right") && off.right !== undefined)
487
+ style.right = px(off.right);
488
+ }
489
+ res.push({
490
+ pos,
491
+ items,
492
+ pill: pillAlign(pos),
493
+ expand: expandDir(pos),
494
+ style: off ? style : undefined,
495
+ });
496
+ }
497
+ return res;
498
+ }, ...(ngDevMode ? [{ debugName: "groups" }] : []));
499
+ onToastEnter(id) {
500
+ const next = new Set(this.hovering());
501
+ next.add(id);
502
+ this.hovering.set(next);
503
+ this.activeId.set(id);
504
+ this.service.pauseTimers();
505
+ }
506
+ onToastLeave(id) {
507
+ const next = new Set(this.hovering());
508
+ next.delete(id);
509
+ this.hovering.set(next);
510
+ if (next.size > 0)
511
+ return;
512
+ queueMicrotask(() => {
513
+ if (this.hovering().size > 0)
514
+ return;
515
+ this.activeId.set(this.latestId());
516
+ this.service.resumeTimers();
517
+ });
518
+ }
519
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: DynamicToastViewportComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
520
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: DynamicToastViewportComponent, isStandalone: true, selector: "dt-viewport", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@for (group of groups(); track group.pos) {\n <section\n data-dt-viewport\n [attr.data-position]=\"group.pos\"\n aria-live=\"polite\"\n [style.top]=\"group.style?.top\"\n [style.right]=\"group.style?.right\"\n [style.bottom]=\"group.style?.bottom\"\n [style.left]=\"group.style?.left\"\n >\n @for (t of group.items; track t.id) {\n <dt-toast\n [toast]=\"t\"\n [pillAlign]=\"group.pill\"\n [expandEdge]=\"group.expand\"\n [canExpand]=\"activeId() === undefined || activeId() === t.id\"\n (entered)=\"onToastEnter($event)\"\n (left)=\"onToastLeave($event)\"\n (dismissed)=\"service.dismiss($event)\"\n />\n }\n </section>\n}\n\n", styles: ["[data-dt-viewport]{--sileo-spring-easing: linear( 0, .002 .6%, .007 1.2%, .015 1.8%, .026 2.4%, .041 3.1%, .06 3.8%, .108 5.3%, .157 6.6%, .214 8%, .467 13.7%, .577 16.3%, .631 17.7%, .682 19.1%, .73 20.5%, .771 21.8%, .808 23.1%, .844 24.5%, .874 25.8%, .903 27.2%, .928 28.6%, .952 30.1%, .972 31.6%, .988 33.1%, 1.01 35.7%, 1.025 38.5%, 1.034 41.6%, 1.038 45%, 1.035 50.1%, 1.012 64.2%, 1.003 73%, .999 83.7%, 1 );--sileo-duration: .6s;--sileo-height: 40px;--sileo-width: 350px;--sileo-state-success: oklch(.723 .219 142.136);--sileo-state-loading: oklch(.556 0 0);--sileo-state-error: oklch(.637 .237 25.331);--sileo-state-warning: oklch(.795 .184 86.047);--sileo-state-info: oklch(.685 .169 237.323);--sileo-state-action: oklch(.623 .214 259.815)}[data-dt-toast]{position:relative;cursor:pointer;pointer-events:auto;touch-action:none;border:0;background:transparent;padding:0;width:var(--sileo-width);height:var(--_h, var(--sileo-height));opacity:0;transform:translateZ(0) scale(.95);transform-origin:center;contain:layout style;overflow:visible;color:#fff;transition:all var(--sileo-duration) var(--sileo-spring-easing);filter:drop-shadow(0 4px 6px rgba(0,0,0,.1)) drop-shadow(0 10px 15px rgba(0,0,0,.2))}[data-dt-toast]:after{display:none!important}[data-dt-viewport]:not(:hover) [data-dt-toast]{position:absolute;right:1.5rem;margin:0!important;transition:all .6s cubic-bezier(.16,1,.3,1)}[data-dt-viewport][data-position$=left]:not(:hover) [data-dt-toast]{right:auto;left:1.5rem}[data-dt-viewport][data-position$=center]:not(:hover) [data-dt-toast]{right:auto;left:auto;position:relative;margin-bottom:-30px!important}[data-dt-viewport][data-position^=top]:not(:hover) [data-dt-toast]{top:1.5rem!important}[data-dt-viewport][data-position^=bottom]:not(:hover) [data-dt-toast]{bottom:1.5rem!important}[data-dt-viewport]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(1){z-index:5;transform:translateY(0) scale(1);opacity:1}[data-dt-viewport][data-position^=top]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(2){z-index:4;transform:translateY(-14px) scale(.95);opacity:1;filter:brightness(.9)}[data-dt-viewport][data-position^=bottom]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(2){z-index:4;transform:translateY(14px) scale(.95);opacity:1;filter:brightness(.9)}[data-dt-viewport][data-position^=top]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(3){z-index:3;transform:translateY(-28px) scale(.9);opacity:.8;filter:brightness(.8)}[data-dt-viewport][data-position^=bottom]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(3){z-index:3;transform:translateY(28px) scale(.9);opacity:.8;filter:brightness(.8)}[data-dt-viewport]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(n+4){opacity:0;pointer-events:none;transform:translateY(0) scale(.8);z-index:0}[data-dt-viewport]:hover [data-dt-toast]{position:relative;transform:none;opacity:1;filter:none;z-index:auto}[data-dt-viewport][data-position^=top]:hover [data-dt-toast]+[data-dt-toast]{margin-top:10px}[data-dt-viewport][data-position^=bottom]:hover [data-dt-toast]+[data-dt-toast]{margin-bottom:10px}[data-dt-toast][data-state=loading]{cursor:default}[data-dt-toast][data-ready=true]{opacity:1;transform:translateZ(0) scale(1);transition:transform calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),opacity calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),margin-bottom calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),margin-top calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),height var(--sileo-duration) var(--sileo-spring-easing)}[data-dt-toast][data-ready=true][data-exiting=true]{opacity:0!important;pointer-events:none}[data-dt-viewport][data-position^=top] [data-dt-toast]:not([data-ready=true]){transform:translateY(-6px) scale(.95);opacity:0!important}[data-dt-viewport][data-position^=bottom] [data-dt-toast]:not([data-ready=true]){transform:translateY(6px) scale(.95);opacity:0!important}[data-dt-viewport][data-position^=top] [data-dt-toast][data-ready=true][data-exiting=true]{transform:translateY(-6px) scale(.95)}[data-dt-viewport][data-position^=bottom] [data-dt-toast][data-ready=true][data-exiting=true]{transform:translateY(6px) scale(.95)}[data-dt-canvas]{position:absolute;left:0;right:0;pointer-events:none;transform:translateZ(0);contain:layout style;overflow:visible}[data-dt-canvas][data-edge=top]{bottom:0;transform:scaleY(-1) translateZ(0)}[data-dt-canvas][data-edge=bottom]{top:0}[data-dt-svg]{overflow:visible}[data-dt-header]{position:absolute;z-index:20;display:flex;align-items:center;padding:.5rem;height:var(--sileo-height);overflow:hidden;left:var(--_px, 0px);transform:var(--_ht);max-width:var(--_pw)}[data-dt-toast][data-ready=true] [data-dt-header]{transition:transform var(--sileo-duration) var(--sileo-spring-easing),left var(--sileo-duration) var(--sileo-spring-easing),max-width var(--sileo-duration) var(--sileo-spring-easing)}[data-dt-header][data-edge=top]{bottom:0}[data-dt-header][data-edge=bottom]{top:0}[data-dt-header-stack]{position:relative;display:inline-flex;align-items:center;height:100%}[data-dt-header-inner]{display:flex;align-items:center;gap:.5rem;white-space:nowrap;opacity:1;filter:blur(0px);transform:translateZ(0)}[data-dt-header-inner][data-layer=current]{position:relative;z-index:1;animation:dt-header-enter var(--sileo-duration) var(--sileo-spring-easing) both}[data-dt-header-inner][data-layer=prev]{position:absolute;left:0;top:0;z-index:0;pointer-events:none}[data-dt-header-inner][data-exiting=true]{animation:dt-header-exit calc(var(--sileo-duration) * .7) ease forwards}[data-dt-badge]{display:flex;height:24px;width:24px;flex-shrink:0;align-items:center;justify-content:center;padding:2px;box-sizing:border-box;border-radius:9999px;color:var(--sileo-tone, currentColor);background-color:var(--sileo-tone-bg, transparent)}[data-dt-title]{font-size:.825rem;line-height:1rem;font-weight:500;text-transform:capitalize;color:var(--sileo-tone, currentColor)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state]{--_c: var(--sileo-state-success)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state=loading]{--_c: var(--sileo-state-loading)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state=error]{--_c: var(--sileo-state-error)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state=warning]{--_c: var(--sileo-state-warning)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state=info]{--_c: var(--sileo-state-info)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state=action]{--_c: var(--sileo-state-action)}:is([data-dt-badge],[data-dt-title])[data-state]{--sileo-tone: var(--_c);--sileo-tone-bg: color-mix(in oklch, var(--_c) 20%, transparent)}[data-dt-content]{position:absolute;left:0;z-index:10;width:100%;pointer-events:none;opacity:var(--_co, 0)}[data-dt-content]:not([data-visible=true]){content-visibility:hidden}[data-dt-toast][data-ready=true] [data-dt-content]{transition:opacity calc(var(--sileo-duration) * .08) ease calc(var(--sileo-duration) * .04)}[data-dt-content][data-edge=top]{top:0}[data-dt-content][data-edge=bottom]{top:var(--sileo-height)}[data-dt-content][data-visible=true]{pointer-events:auto}[data-dt-toast][data-ready=true] [data-dt-content][data-visible=true]{transition:opacity calc(var(--sileo-duration) * .6) ease calc(var(--sileo-duration) * .3)}[data-dt-description]{width:100%;text-align:left;padding:1rem;font-size:.875rem;line-height:1.25rem;contain:layout style paint;content-visibility:auto}[data-dt-button]{display:flex;align-items:center;justify-content:center;height:1.75rem;padding:0 .625rem;margin-top:.75rem;border-radius:9999px;border:0;font-size:.75rem;font-weight:500;cursor:pointer;color:var(--sileo-btn-color, currentColor);background-color:var(--sileo-btn-bg, transparent);transition:background-color .15s ease}[data-dt-button]:hover{background-color:var(--sileo-btn-bg-hover, transparent)}[data-dt-button][data-state]{--sileo-btn-color: var(--_c);--sileo-btn-bg: color-mix(in oklch, var(--_c) 15%, transparent);--sileo-btn-bg-hover: color-mix(in oklch, var(--_c) 25%, transparent)}[data-dt-icon=spin]{animation:dt-spin 1s linear infinite}@keyframes dt-spin{to{transform:rotate(360deg)}}@keyframes dt-header-enter{0%{opacity:0;filter:blur(6px)}to{opacity:1;filter:blur(0px)}}@keyframes dt-header-exit{0%{opacity:1;filter:blur(0px)}to{opacity:0;filter:blur(6px)}}[data-dt-viewport]{position:fixed;z-index:50;display:flex;gap:0;padding:1.5rem;pointer-events:auto;max-width:calc(100vw - 1.5rem);contain:layout style;transition:all .3s ease;height:auto}[data-dt-viewport]{pointer-events:none}[data-dt-toast]{pointer-events:auto}[data-dt-viewport][data-position^=top] [data-dt-toast]:not([data-ready=true]){margin-bottom:calc(-1 * (var(--sileo-height) + .75rem))}[data-dt-viewport][data-position^=bottom] [data-dt-toast]:not([data-ready=true]){margin-top:calc(-1 * (var(--sileo-height) + .75rem))}[data-dt-viewport][data-position^=top]{top:0;flex-direction:column-reverse}[data-dt-viewport][data-position^=bottom]{bottom:0;flex-direction:column}[data-dt-viewport][data-position$=left]{left:0;align-items:flex-start}[data-dt-viewport][data-position$=right]{right:0;align-items:flex-end}[data-dt-viewport][data-position$=center]{left:50%;transform:translate(-50%);align-items:center}@media(prefers-reduced-motion:no-preference){[data-dt-toast][data-ready=true]:hover,[data-dt-toast][data-ready=true][data-exiting=true]{will-change:transform,opacity,height}}@media(prefers-reduced-motion:reduce){[data-dt-viewport],[data-dt-viewport] *,[data-dt-viewport] *:before,[data-dt-viewport] *:after{animation-duration:.01ms;animation-iteration-count:1;transition-duration:.01ms}}\n"], dependencies: [{ kind: "component", type: DynamicToastComponent, selector: "dt-toast", inputs: ["toast", "pillAlign", "expandEdge", "canExpand", "interruptKey"], outputs: ["dismissed", "entered", "left"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
521
+ }
522
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: DynamicToastViewportComponent, decorators: [{
523
+ type: Component,
524
+ args: [{ selector: "dt-viewport", standalone: true, imports: [DynamicToastComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@for (group of groups(); track group.pos) {\n <section\n data-dt-viewport\n [attr.data-position]=\"group.pos\"\n aria-live=\"polite\"\n [style.top]=\"group.style?.top\"\n [style.right]=\"group.style?.right\"\n [style.bottom]=\"group.style?.bottom\"\n [style.left]=\"group.style?.left\"\n >\n @for (t of group.items; track t.id) {\n <dt-toast\n [toast]=\"t\"\n [pillAlign]=\"group.pill\"\n [expandEdge]=\"group.expand\"\n [canExpand]=\"activeId() === undefined || activeId() === t.id\"\n (entered)=\"onToastEnter($event)\"\n (left)=\"onToastLeave($event)\"\n (dismissed)=\"service.dismiss($event)\"\n />\n }\n </section>\n}\n\n", styles: ["[data-dt-viewport]{--sileo-spring-easing: linear( 0, .002 .6%, .007 1.2%, .015 1.8%, .026 2.4%, .041 3.1%, .06 3.8%, .108 5.3%, .157 6.6%, .214 8%, .467 13.7%, .577 16.3%, .631 17.7%, .682 19.1%, .73 20.5%, .771 21.8%, .808 23.1%, .844 24.5%, .874 25.8%, .903 27.2%, .928 28.6%, .952 30.1%, .972 31.6%, .988 33.1%, 1.01 35.7%, 1.025 38.5%, 1.034 41.6%, 1.038 45%, 1.035 50.1%, 1.012 64.2%, 1.003 73%, .999 83.7%, 1 );--sileo-duration: .6s;--sileo-height: 40px;--sileo-width: 350px;--sileo-state-success: oklch(.723 .219 142.136);--sileo-state-loading: oklch(.556 0 0);--sileo-state-error: oklch(.637 .237 25.331);--sileo-state-warning: oklch(.795 .184 86.047);--sileo-state-info: oklch(.685 .169 237.323);--sileo-state-action: oklch(.623 .214 259.815)}[data-dt-toast]{position:relative;cursor:pointer;pointer-events:auto;touch-action:none;border:0;background:transparent;padding:0;width:var(--sileo-width);height:var(--_h, var(--sileo-height));opacity:0;transform:translateZ(0) scale(.95);transform-origin:center;contain:layout style;overflow:visible;color:#fff;transition:all var(--sileo-duration) var(--sileo-spring-easing);filter:drop-shadow(0 4px 6px rgba(0,0,0,.1)) drop-shadow(0 10px 15px rgba(0,0,0,.2))}[data-dt-toast]:after{display:none!important}[data-dt-viewport]:not(:hover) [data-dt-toast]{position:absolute;right:1.5rem;margin:0!important;transition:all .6s cubic-bezier(.16,1,.3,1)}[data-dt-viewport][data-position$=left]:not(:hover) [data-dt-toast]{right:auto;left:1.5rem}[data-dt-viewport][data-position$=center]:not(:hover) [data-dt-toast]{right:auto;left:auto;position:relative;margin-bottom:-30px!important}[data-dt-viewport][data-position^=top]:not(:hover) [data-dt-toast]{top:1.5rem!important}[data-dt-viewport][data-position^=bottom]:not(:hover) [data-dt-toast]{bottom:1.5rem!important}[data-dt-viewport]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(1){z-index:5;transform:translateY(0) scale(1);opacity:1}[data-dt-viewport][data-position^=top]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(2){z-index:4;transform:translateY(-14px) scale(.95);opacity:1;filter:brightness(.9)}[data-dt-viewport][data-position^=bottom]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(2){z-index:4;transform:translateY(14px) scale(.95);opacity:1;filter:brightness(.9)}[data-dt-viewport][data-position^=top]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(3){z-index:3;transform:translateY(-28px) scale(.9);opacity:.8;filter:brightness(.8)}[data-dt-viewport][data-position^=bottom]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(3){z-index:3;transform:translateY(28px) scale(.9);opacity:.8;filter:brightness(.8)}[data-dt-viewport]:not(:hover) [data-dt-toast][data-ready=true]:not([data-exiting=true]):nth-last-child(n+4){opacity:0;pointer-events:none;transform:translateY(0) scale(.8);z-index:0}[data-dt-viewport]:hover [data-dt-toast]{position:relative;transform:none;opacity:1;filter:none;z-index:auto}[data-dt-viewport][data-position^=top]:hover [data-dt-toast]+[data-dt-toast]{margin-top:10px}[data-dt-viewport][data-position^=bottom]:hover [data-dt-toast]+[data-dt-toast]{margin-bottom:10px}[data-dt-toast][data-state=loading]{cursor:default}[data-dt-toast][data-ready=true]{opacity:1;transform:translateZ(0) scale(1);transition:transform calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),opacity calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),margin-bottom calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),margin-top calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),height var(--sileo-duration) var(--sileo-spring-easing)}[data-dt-toast][data-ready=true][data-exiting=true]{opacity:0!important;pointer-events:none}[data-dt-viewport][data-position^=top] [data-dt-toast]:not([data-ready=true]){transform:translateY(-6px) scale(.95);opacity:0!important}[data-dt-viewport][data-position^=bottom] [data-dt-toast]:not([data-ready=true]){transform:translateY(6px) scale(.95);opacity:0!important}[data-dt-viewport][data-position^=top] [data-dt-toast][data-ready=true][data-exiting=true]{transform:translateY(-6px) scale(.95)}[data-dt-viewport][data-position^=bottom] [data-dt-toast][data-ready=true][data-exiting=true]{transform:translateY(6px) scale(.95)}[data-dt-canvas]{position:absolute;left:0;right:0;pointer-events:none;transform:translateZ(0);contain:layout style;overflow:visible}[data-dt-canvas][data-edge=top]{bottom:0;transform:scaleY(-1) translateZ(0)}[data-dt-canvas][data-edge=bottom]{top:0}[data-dt-svg]{overflow:visible}[data-dt-header]{position:absolute;z-index:20;display:flex;align-items:center;padding:.5rem;height:var(--sileo-height);overflow:hidden;left:var(--_px, 0px);transform:var(--_ht);max-width:var(--_pw)}[data-dt-toast][data-ready=true] [data-dt-header]{transition:transform var(--sileo-duration) var(--sileo-spring-easing),left var(--sileo-duration) var(--sileo-spring-easing),max-width var(--sileo-duration) var(--sileo-spring-easing)}[data-dt-header][data-edge=top]{bottom:0}[data-dt-header][data-edge=bottom]{top:0}[data-dt-header-stack]{position:relative;display:inline-flex;align-items:center;height:100%}[data-dt-header-inner]{display:flex;align-items:center;gap:.5rem;white-space:nowrap;opacity:1;filter:blur(0px);transform:translateZ(0)}[data-dt-header-inner][data-layer=current]{position:relative;z-index:1;animation:dt-header-enter var(--sileo-duration) var(--sileo-spring-easing) both}[data-dt-header-inner][data-layer=prev]{position:absolute;left:0;top:0;z-index:0;pointer-events:none}[data-dt-header-inner][data-exiting=true]{animation:dt-header-exit calc(var(--sileo-duration) * .7) ease forwards}[data-dt-badge]{display:flex;height:24px;width:24px;flex-shrink:0;align-items:center;justify-content:center;padding:2px;box-sizing:border-box;border-radius:9999px;color:var(--sileo-tone, currentColor);background-color:var(--sileo-tone-bg, transparent)}[data-dt-title]{font-size:.825rem;line-height:1rem;font-weight:500;text-transform:capitalize;color:var(--sileo-tone, currentColor)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state]{--_c: var(--sileo-state-success)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state=loading]{--_c: var(--sileo-state-loading)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state=error]{--_c: var(--sileo-state-error)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state=warning]{--_c: var(--sileo-state-warning)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state=info]{--_c: var(--sileo-state-info)}:is([data-dt-badge],[data-dt-title],[data-dt-button])[data-state=action]{--_c: var(--sileo-state-action)}:is([data-dt-badge],[data-dt-title])[data-state]{--sileo-tone: var(--_c);--sileo-tone-bg: color-mix(in oklch, var(--_c) 20%, transparent)}[data-dt-content]{position:absolute;left:0;z-index:10;width:100%;pointer-events:none;opacity:var(--_co, 0)}[data-dt-content]:not([data-visible=true]){content-visibility:hidden}[data-dt-toast][data-ready=true] [data-dt-content]{transition:opacity calc(var(--sileo-duration) * .08) ease calc(var(--sileo-duration) * .04)}[data-dt-content][data-edge=top]{top:0}[data-dt-content][data-edge=bottom]{top:var(--sileo-height)}[data-dt-content][data-visible=true]{pointer-events:auto}[data-dt-toast][data-ready=true] [data-dt-content][data-visible=true]{transition:opacity calc(var(--sileo-duration) * .6) ease calc(var(--sileo-duration) * .3)}[data-dt-description]{width:100%;text-align:left;padding:1rem;font-size:.875rem;line-height:1.25rem;contain:layout style paint;content-visibility:auto}[data-dt-button]{display:flex;align-items:center;justify-content:center;height:1.75rem;padding:0 .625rem;margin-top:.75rem;border-radius:9999px;border:0;font-size:.75rem;font-weight:500;cursor:pointer;color:var(--sileo-btn-color, currentColor);background-color:var(--sileo-btn-bg, transparent);transition:background-color .15s ease}[data-dt-button]:hover{background-color:var(--sileo-btn-bg-hover, transparent)}[data-dt-button][data-state]{--sileo-btn-color: var(--_c);--sileo-btn-bg: color-mix(in oklch, var(--_c) 15%, transparent);--sileo-btn-bg-hover: color-mix(in oklch, var(--_c) 25%, transparent)}[data-dt-icon=spin]{animation:dt-spin 1s linear infinite}@keyframes dt-spin{to{transform:rotate(360deg)}}@keyframes dt-header-enter{0%{opacity:0;filter:blur(6px)}to{opacity:1;filter:blur(0px)}}@keyframes dt-header-exit{0%{opacity:1;filter:blur(0px)}to{opacity:0;filter:blur(6px)}}[data-dt-viewport]{position:fixed;z-index:50;display:flex;gap:0;padding:1.5rem;pointer-events:auto;max-width:calc(100vw - 1.5rem);contain:layout style;transition:all .3s ease;height:auto}[data-dt-viewport]{pointer-events:none}[data-dt-toast]{pointer-events:auto}[data-dt-viewport][data-position^=top] [data-dt-toast]:not([data-ready=true]){margin-bottom:calc(-1 * (var(--sileo-height) + .75rem))}[data-dt-viewport][data-position^=bottom] [data-dt-toast]:not([data-ready=true]){margin-top:calc(-1 * (var(--sileo-height) + .75rem))}[data-dt-viewport][data-position^=top]{top:0;flex-direction:column-reverse}[data-dt-viewport][data-position^=bottom]{bottom:0;flex-direction:column}[data-dt-viewport][data-position$=left]{left:0;align-items:flex-start}[data-dt-viewport][data-position$=right]{right:0;align-items:flex-end}[data-dt-viewport][data-position$=center]{left:50%;transform:translate(-50%);align-items:center}@media(prefers-reduced-motion:no-preference){[data-dt-toast][data-ready=true]:hover,[data-dt-toast][data-ready=true][data-exiting=true]{will-change:transform,opacity,height}}@media(prefers-reduced-motion:reduce){[data-dt-viewport],[data-dt-viewport] *,[data-dt-viewport] *:before,[data-dt-viewport] *:after{animation-duration:.01ms;animation-iteration-count:1;transition-duration:.01ms}}\n"] }]
525
+ }], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }] } });
526
+
527
+ const timeoutKey = (t) => `${t.id}:${t.instanceId}`;
528
+ let idCounter = 0;
529
+ const generateId = () => `${++idCounter}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
530
+ class DynamicToastService {
531
+ _toasts = signal([], ...(ngDevMode ? [{ debugName: "_toasts" }] : []));
532
+ toasts = this._toasts.asReadonly();
533
+ config = { position: "top-right" };
534
+ viewportRef = null;
535
+ timers = new Map();
536
+ paused = false;
537
+ isPendingCD = false;
538
+ loopCount = 0;
539
+ loopResetTimer;
540
+ appRef = inject(ApplicationRef);
541
+ envInjector = inject(EnvironmentInjector);
542
+ document = inject(DOCUMENT);
543
+ ngZone = inject(NgZone);
544
+ configure(cfg) {
545
+ this.config = { ...this.config, ...cfg };
546
+ if (this.viewportRef) {
547
+ this.viewportRef.setInput("position", this.config.position ?? "top-right");
548
+ this.viewportRef.setInput("offset", this.config.offset);
549
+ }
550
+ }
551
+ ensureViewport() {
552
+ if (this.viewportRef)
553
+ return;
554
+ const ref = createComponent(DynamicToastViewportComponent, {
555
+ environmentInjector: this.envInjector,
556
+ });
557
+ ref.setInput("position", this.config.position ?? "top-right");
558
+ ref.setInput("offset", this.config.offset);
559
+ const el = ref.location.nativeElement;
560
+ el.setAttribute("data-dt-root", "");
561
+ this.appRef.attachView(ref.hostView);
562
+ this.document.body.appendChild(el);
563
+ this.viewportRef = ref;
564
+ }
565
+ resolveAutopilot(opts, duration) {
566
+ if (opts.autopilot === false || !duration || duration <= 0)
567
+ return {};
568
+ const cfg = typeof opts.autopilot === "object" ? opts.autopilot : undefined;
569
+ const clamp = (v) => Math.min(duration, Math.max(0, v));
570
+ return {
571
+ expandDelayMs: clamp(cfg?.expand ?? AUTO_EXPAND_DELAY),
572
+ collapseDelayMs: clamp(cfg?.collapse ?? AUTO_COLLAPSE_DELAY),
573
+ };
574
+ }
575
+ mergeOptions(options) {
576
+ return {
577
+ ...(this.config.options ?? {}),
578
+ ...options,
579
+ styles: { ...(this.config.options?.styles ?? {}), ...(options.styles ?? {}) },
580
+ };
581
+ }
582
+ buildItem(merged, id, state, fallbackPosition) {
583
+ const duration = merged.duration ?? DEFAULT_TOAST_DURATION;
584
+ const auto = this.resolveAutopilot(merged, duration);
585
+ return {
586
+ ...merged,
587
+ id,
588
+ instanceId: generateId(),
589
+ state,
590
+ position: merged.position ?? fallbackPosition ?? this.config.position ?? "top-right",
591
+ duration,
592
+ autoExpandDelayMs: auto.expandDelayMs,
593
+ autoCollapseDelayMs: auto.collapseDelayMs,
594
+ exiting: false,
595
+ fill: merged.fill ?? "#151515",
596
+ };
597
+ }
598
+ upsert(item) {
599
+ // console.log("[DynamicToastService] upsert", item.id, item.state);
600
+ // Circuit breaker for infinite loops
601
+ this.loopCount++;
602
+ if (this.loopCount > 50) {
603
+ console.warn("[DynamicToast] Loop detected (50+ updates/sec). Blocking update.");
604
+ return;
605
+ }
606
+ if (!this.loopResetTimer) {
607
+ this.loopResetTimer = setTimeout(() => {
608
+ this.loopCount = 0;
609
+ this.loopResetTimer = null;
610
+ }, 1000);
611
+ }
612
+ // Optimization: check if item really changed before anything else
613
+ const currentList = this._toasts();
614
+ const existing = currentList.find((t) => t.id === item.id);
615
+ if (existing && JSON.stringify(existing) === JSON.stringify(item)) {
616
+ return;
617
+ }
618
+ this.ensureViewport();
619
+ // Update state outside of Angular Zone to prevent change detection loops
620
+ // We will manually trigger CD only when necessary
621
+ this.ngZone.runOutsideAngular(() => {
622
+ this._toasts.update((prev) => {
623
+ const live = prev.filter((t) => !t.exiting);
624
+ const exist = live.find((t) => t.id === item.id);
625
+ if (exist) {
626
+ return prev.map((t) => (t.id === item.id ? { ...item } : t));
627
+ }
628
+ return [...prev.filter((t) => t.id !== item.id), item];
629
+ });
630
+ });
631
+ // Coalesce CD updates to one per frame
632
+ if (!this.isPendingCD) {
633
+ this.isPendingCD = true;
634
+ this.ngZone.runOutsideAngular(() => {
635
+ requestAnimationFrame(() => {
636
+ this.isPendingCD = false;
637
+ // Only re-enter zone for CD if really needed, or run detectChanges directly
638
+ this.viewportRef?.changeDetectorRef.detectChanges();
639
+ });
640
+ });
641
+ }
642
+ this.scheduleAll();
643
+ }
644
+ show(options) {
645
+ const merged = this.mergeOptions(options);
646
+ const id = merged.id ?? "dynamicToast-default";
647
+ const prev = this._toasts().find((t) => t.id === id && !t.exiting);
648
+ const item = this.buildItem(merged, id, options.state, prev?.position);
649
+ this.upsert(item);
650
+ return id;
651
+ }
652
+ info(a, b) {
653
+ const opts = typeof a === "string" ? { ...(b ?? {}), title: a } : a;
654
+ return this.show({ ...opts, state: "info" });
655
+ }
656
+ success(a, b) {
657
+ const opts = typeof a === "string" ? { ...(b ?? {}), title: a } : a;
658
+ return this.show({ ...opts, state: "success" });
659
+ }
660
+ warning(a, b) {
661
+ const opts = typeof a === "string" ? { ...(b ?? {}), title: a } : a;
662
+ return this.show({ ...opts, state: "warning" });
663
+ }
664
+ error(a, b) {
665
+ const opts = typeof a === "string" ? { ...(b ?? {}), title: a } : a;
666
+ return this.show({ ...opts, state: "error" });
667
+ }
668
+ loading(a, b) {
669
+ const opts = typeof a === "string" ? { ...(b ?? {}), title: a } : a;
670
+ return this.show({ ...opts, state: "loading", duration: null });
671
+ }
672
+ action(a, b) {
673
+ const opts = typeof a === "string" ? { ...(b ?? {}), title: a } : a;
674
+ return this.show({ ...opts, state: "action", duration: null });
675
+ }
676
+ update(id, patch) {
677
+ const existing = this._toasts().find((t) => t.id === id);
678
+ if (!existing)
679
+ return;
680
+ const merged = this.mergeOptions({ ...existing, ...patch, id });
681
+ const state = patch.state ?? existing.state;
682
+ const item = this.buildItem(merged, id, state, existing.position);
683
+ this.upsert(item);
684
+ }
685
+ promise(promise, opts) {
686
+ const id = this.show({
687
+ ...opts.loading,
688
+ state: "loading",
689
+ duration: null,
690
+ position: opts.position,
691
+ });
692
+ const p = typeof promise === "function" ? promise() : promise;
693
+ p.then((data) => {
694
+ if (opts.action) {
695
+ const actionOpts = typeof opts.action === "function" ? opts.action(data) : opts.action;
696
+ this.update(id, { ...actionOpts, state: "action", id });
697
+ }
698
+ else {
699
+ const successOpts = typeof opts.success === "function" ? opts.success(data) : opts.success;
700
+ this.update(id, { ...successOpts, state: "success", id });
701
+ }
702
+ }).catch((err) => {
703
+ const errorOpts = typeof opts.error === "function" ? opts.error(err) : opts.error;
704
+ this.update(id, { ...errorOpts, state: "error", id });
705
+ });
706
+ return p;
707
+ }
708
+ dismiss(id) {
709
+ const item = this._toasts().find((t) => t.id === id);
710
+ if (!item || item.exiting)
711
+ return;
712
+ this.ngZone.runOutsideAngular(() => {
713
+ this._toasts.update((prev) => prev.map((t) => (t.id === id ? { ...t, exiting: true } : t)));
714
+ });
715
+ this.viewportRef?.changeDetectorRef.detectChanges();
716
+ this.ngZone.runOutsideAngular(() => {
717
+ window.setTimeout(() => {
718
+ this._toasts.update((prev) => prev.filter((t) => t.id !== id));
719
+ this.clearTimers();
720
+ this.scheduleAll();
721
+ this.viewportRef?.changeDetectorRef.detectChanges();
722
+ }, EXIT_DURATION);
723
+ });
724
+ }
725
+ clear(position) {
726
+ this._toasts.update((prev) => position ? prev.filter((t) => t.position !== position) : []);
727
+ this.clearTimers();
728
+ }
729
+ pauseTimers() {
730
+ if (this.paused)
731
+ return;
732
+ this.paused = true;
733
+ this.clearTimers();
734
+ }
735
+ resumeTimers() {
736
+ if (!this.paused)
737
+ return;
738
+ this.paused = false;
739
+ this.scheduleAll();
740
+ }
741
+ clearTimers() {
742
+ for (const t of this.timers.values())
743
+ window.clearTimeout(t);
744
+ this.timers.clear();
745
+ }
746
+ scheduleAll() {
747
+ if (this.paused)
748
+ return;
749
+ this.ngZone.runOutsideAngular(() => {
750
+ const items = this._toasts();
751
+ for (const item of items) {
752
+ if (item.exiting)
753
+ continue;
754
+ const key = timeoutKey(item);
755
+ if (this.timers.has(key))
756
+ continue;
757
+ const dur = item.duration ?? DEFAULT_TOAST_DURATION;
758
+ if (dur === null || dur <= 0)
759
+ continue;
760
+ this.timers.set(key, window.setTimeout(() => {
761
+ // Re-enter zone only if needed, but dismiss handles zone internally now
762
+ this.dismiss(item.id);
763
+ }, dur));
764
+ }
765
+ const alive = new Set(items.map(timeoutKey));
766
+ for (const [key, timer] of this.timers) {
767
+ if (!alive.has(key)) {
768
+ window.clearTimeout(timer);
769
+ this.timers.delete(key);
770
+ }
771
+ }
772
+ });
773
+ }
774
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: DynamicToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
775
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: DynamicToastService, providedIn: "root" });
776
+ }
777
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: DynamicToastService, decorators: [{
778
+ type: Injectable,
779
+ args: [{ providedIn: "root" }]
780
+ }] });
781
+
782
+ /*
783
+ * Public API Surface of ngx-dynamic-toast
784
+ */
785
+
786
+ /**
787
+ * Generated bundle index. Do not edit.
788
+ */
789
+
790
+ export { AUTO_COLLAPSE_DELAY, AUTO_EXPAND_DELAY, BLUR_RATIO, DEFAULT_ROUNDNESS, DEFAULT_TOAST_DURATION, DURATION_MS, DURATION_S, DynamicToastComponent, DynamicToastService, DynamicToastViewportComponent, EXIT_DURATION, HEADER_EXIT_MS, HEIGHT, ICONS, MIN_EXPAND_RATIO, PILL_PADDING, SWAP_COLLAPSE_MS, WIDTH };
791
+ //# sourceMappingURL=ngx-dynamic-toast.mjs.map