ngx-dynamic-toast 0.0.4 → 0.0.5

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,664 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, Injectable, input, output, inject, ElementRef, NgZone, ChangeDetectorRef, computed, effect, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { NgTemplateOutlet } from '@angular/common';
4
+ import { DomSanitizer } from '@angular/platform-browser';
5
+
6
+ class DynamicToastService {
7
+ _toasts = signal([], ...(ngDevMode ? [{ debugName: "_toasts" }] : /* istanbul ignore next */ []));
8
+ toasts = this._toasts.asReadonly();
9
+ _config = {
10
+ position: "top-right",
11
+ options: {
12
+ duration: 4000,
13
+ },
14
+ };
15
+ timers = new Map();
16
+ paused = false;
17
+ configure(config) {
18
+ this._config = {
19
+ ...this._config,
20
+ ...config,
21
+ options: { ...this._config.options, ...config.options },
22
+ };
23
+ }
24
+ show(opts) {
25
+ const id = opts.id || Math.random().toString(36).substring(2, 9);
26
+ const toast = {
27
+ ...this._config.options,
28
+ ...opts,
29
+ id,
30
+ instanceId: Math.random().toString(36).substring(2, 9),
31
+ position: opts.position || this._config.position,
32
+ };
33
+ this._toasts.update((current) => [...current, toast]);
34
+ if (toast.duration !== null && !this.paused) {
35
+ this.startTimer(id, toast.duration ?? 4000);
36
+ }
37
+ return id;
38
+ }
39
+ success(opts) {
40
+ return this.show(this.normalizeOptions(opts, "success"));
41
+ }
42
+ error(opts) {
43
+ return this.show(this.normalizeOptions(opts, "error"));
44
+ }
45
+ warning(opts) {
46
+ return this.show(this.normalizeOptions(opts, "warning"));
47
+ }
48
+ info(opts) {
49
+ return this.show(this.normalizeOptions(opts, "info"));
50
+ }
51
+ loading(opts) {
52
+ return this.show(this.normalizeOptions(opts, "loading"));
53
+ }
54
+ action(opts) {
55
+ return this.show(this.normalizeOptions(opts, "action"));
56
+ }
57
+ promise(promise, opts) {
58
+ const id = this.loading({
59
+ ...opts.loading,
60
+ position: opts.position,
61
+ });
62
+ const p = typeof promise === "function" ? promise() : promise;
63
+ p.then((data) => {
64
+ const successOpts = typeof opts.success === "function" ? opts.success(data) : opts.success;
65
+ this.update(id, { ...successOpts, state: "success" });
66
+ }).catch((err) => {
67
+ const errorOpts = typeof opts.error === "function" ? opts.error(err) : opts.error;
68
+ this.update(id, { ...errorOpts, state: "error" });
69
+ });
70
+ return id;
71
+ }
72
+ update(id, opts) {
73
+ this._toasts.update((current) => current.map((t) => (t.id === id ? { ...t, ...opts } : t)));
74
+ // If it's now a final state and has a duration, start timer
75
+ const toast = this._toasts().find((t) => t.id === id);
76
+ if (toast && toast.state !== "loading" && toast.duration !== null) {
77
+ this.clearTimer(id);
78
+ this.startTimer(id, toast.duration ?? 4000);
79
+ }
80
+ }
81
+ dismiss(id) {
82
+ this.update(id, { exiting: true });
83
+ setTimeout(() => {
84
+ this._toasts.update((current) => current.filter((t) => t.id !== id));
85
+ this.clearTimer(id);
86
+ }, 400); // Wait for exit animation
87
+ }
88
+ clear(pos) {
89
+ const toDismiss = pos
90
+ ? this._toasts().filter((t) => t.position === pos)
91
+ : this._toasts();
92
+ toDismiss.forEach((t) => this.dismiss(t.id));
93
+ }
94
+ pauseTimers() {
95
+ this.paused = true;
96
+ this.timers.forEach((timer) => clearTimeout(timer));
97
+ this.timers.clear();
98
+ }
99
+ resumeTimers() {
100
+ this.paused = false;
101
+ this._toasts().forEach((t) => {
102
+ if (t.duration !== null && t.state !== "loading") {
103
+ this.startTimer(t.id, t.duration ?? 4000);
104
+ }
105
+ });
106
+ }
107
+ normalizeOptions(opts, state) {
108
+ if (typeof opts === "string") {
109
+ return { title: opts, state };
110
+ }
111
+ return { ...opts, state };
112
+ }
113
+ startTimer(id, duration) {
114
+ this.clearTimer(id);
115
+ const timer = setTimeout(() => this.dismiss(id), duration);
116
+ this.timers.set(id, timer);
117
+ }
118
+ clearTimer(id) {
119
+ if (this.timers.has(id)) {
120
+ clearTimeout(this.timers.get(id));
121
+ this.timers.delete(id);
122
+ }
123
+ }
124
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DynamicToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
125
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DynamicToastService, providedIn: "root" });
126
+ }
127
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DynamicToastService, decorators: [{
128
+ type: Injectable,
129
+ args: [{
130
+ providedIn: "root",
131
+ }]
132
+ }] });
133
+
134
+ const HEIGHT = 40;
135
+ const WIDTH = 350;
136
+ const DEFAULT_ROUNDNESS = 16;
137
+ const DURATION_MS = 600;
138
+ const DURATION_S = DURATION_MS / 1000;
139
+ const DEFAULT_TOAST_DURATION = 6000;
140
+ const EXIT_DURATION = DEFAULT_TOAST_DURATION * 0.1;
141
+ const AUTO_EXPAND_DELAY = DEFAULT_TOAST_DURATION * 0.025;
142
+ const AUTO_COLLAPSE_DELAY = DEFAULT_TOAST_DURATION - 2000;
143
+ const BLUR_RATIO = 0.5;
144
+ const PILL_PADDING = 10;
145
+ const MIN_EXPAND_RATIO = 2.25;
146
+ const SWAP_COLLAPSE_MS = 200;
147
+ const HEADER_EXIT_MS = DURATION_MS * 0.7;
148
+
149
+ 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>`;
150
+ const ICONS = {
151
+ arrowRight: baseSvg("Arrow Right", `<path d="M5 12h14" /><path d="m12 5 7 7-7 7" />`),
152
+ 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" />`),
153
+ loaderCircle: (extra) => baseSvg("Loader Circle", `<path d="M21 12a9 9 0 1 1-6.219-8.56" />`, extra),
154
+ x: baseSvg("X", `<path d="M18 6 6 18" /><path d="m6 6 12 12" />`),
155
+ 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" />`),
156
+ check: baseSvg("Check", `<path d="M20 6 9 17l-5-5" />`),
157
+ };
158
+
159
+ class DynamicToastComponent {
160
+ toast = input.required(...(ngDevMode ? [{ debugName: "toast" }] : /* istanbul ignore next */ []));
161
+ pillAlign = input("left", ...(ngDevMode ? [{ debugName: "pillAlign" }] : /* istanbul ignore next */ []));
162
+ expandEdge = input("bottom", ...(ngDevMode ? [{ debugName: "expandEdge" }] : /* istanbul ignore next */ []));
163
+ canExpand = input(true, ...(ngDevMode ? [{ debugName: "canExpand" }] : /* istanbul ignore next */ []));
164
+ interruptKey = input(undefined, ...(ngDevMode ? [{ debugName: "interruptKey" }] : /* istanbul ignore next */ []));
165
+ dismissed = output();
166
+ entered = output();
167
+ left = output();
168
+ HEIGHT = HEIGHT;
169
+ WIDTH = WIDTH;
170
+ sanitizer = inject(DomSanitizer);
171
+ hostEl = inject(ElementRef);
172
+ ngZone = inject(NgZone);
173
+ cdr = inject(ChangeDetectorRef);
174
+ hasMeasured = false;
175
+ roHeader = null;
176
+ roContent = null;
177
+ headerExitTimer = null;
178
+ autoExpandTimer = null;
179
+ autoCollapseTimer = null;
180
+ swapTimer = null;
181
+ lastRefreshKey;
182
+ pendingSwap = null;
183
+ pointerStartY = null;
184
+ ready = signal(false, ...(ngDevMode ? [{ debugName: "ready" }] : /* istanbul ignore next */ []));
185
+ isExpanded = signal(true, ...(ngDevMode ? [{ debugName: "isExpanded" }] : /* istanbul ignore next */ [])); // Default to expanded if description exists
186
+ pillWidth = signal(0, ...(ngDevMode ? [{ debugName: "pillWidth" }] : /* istanbul ignore next */ []));
187
+ contentHeight = signal(0, ...(ngDevMode ? [{ debugName: "contentHeight" }] : /* istanbul ignore next */ []));
188
+ // view = signal<View>({
189
+ // title: "",
190
+ // description: "",
191
+ // state: "success",
192
+ // iconSvg: null,
193
+ // fill: "#FFFFFF",
194
+ // });
195
+ // Use a default toast state to avoid NG0950 during initialization
196
+ view = computed(() => {
197
+ try {
198
+ const t = this.toast();
199
+ return {
200
+ title: t.title,
201
+ description: t.description,
202
+ contentTemplate: t.contentTemplate,
203
+ state: t.state,
204
+ iconSvg: t.iconSvg,
205
+ styles: t.styles,
206
+ button: t.button,
207
+ fill: t.fill ?? "#151515",
208
+ };
209
+ }
210
+ catch (e) {
211
+ // Return safe default if input is not yet bound
212
+ return {
213
+ title: "",
214
+ state: "info",
215
+ fill: "#151515",
216
+ };
217
+ }
218
+ }, ...(ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []));
219
+ // headerLayerCurrent = signal<HeaderLayer>({
220
+ // key: "",
221
+ // view: this.view(),
222
+ // });
223
+ // headerLayerPrev = signal<HeaderLayer | null>(null);
224
+ filterId = `dt-gooey-${Math.random().toString(36).slice(2, 8)}`;
225
+ hasDesc = computed(() => {
226
+ const v = this.view();
227
+ return (Boolean(v.description) || Boolean(v.contentTemplate) || Boolean(v.button));
228
+ }, ...(ngDevMode ? [{ debugName: "hasDesc" }] : /* istanbul ignore next */ []));
229
+ isLoading = computed(() => this.view().state === "loading", ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
230
+ allowExpand = computed(() => {
231
+ if (this.isLoading())
232
+ return false;
233
+ const interrupt = this.interruptKey();
234
+ const id = this.toast().id;
235
+ return this.canExpand() ?? (!interrupt || interrupt === id);
236
+ }, ...(ngDevMode ? [{ debugName: "allowExpand" }] : /* istanbul ignore next */ []));
237
+ open = computed(() => this.hasDesc() && this.isExpanded() && !this.isLoading(), ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
238
+ resolvedRoundness = computed(() => {
239
+ try {
240
+ return Math.max(0, this.toast().roundness ?? DEFAULT_ROUNDNESS);
241
+ }
242
+ catch {
243
+ return DEFAULT_ROUNDNESS;
244
+ }
245
+ }, ...(ngDevMode ? [{ debugName: "resolvedRoundness" }] : /* istanbul ignore next */ []));
246
+ blur = computed(() => this.resolvedRoundness() * BLUR_RATIO, ...(ngDevMode ? [{ debugName: "blur" }] : /* istanbul ignore next */ []));
247
+ minExpanded = computed(() => HEIGHT * MIN_EXPAND_RATIO, ...(ngDevMode ? [{ debugName: "minExpanded" }] : /* istanbul ignore next */ []));
248
+ rawExpanded = computed(() => {
249
+ const min = this.minExpanded();
250
+ try {
251
+ if (!this.hasDesc())
252
+ return min;
253
+ return Math.max(min, HEIGHT + this.contentHeight());
254
+ }
255
+ catch {
256
+ return min;
257
+ }
258
+ }, ...(ngDevMode ? [{ debugName: "rawExpanded" }] : /* istanbul ignore next */ []));
259
+ frozenExpanded = signal(HEIGHT * MIN_EXPAND_RATIO, ...(ngDevMode ? [{ debugName: "frozenExpanded" }] : /* istanbul ignore next */ []));
260
+ expanded = computed(() => this.open() ? this.rawExpanded() : this.frozenExpanded(), ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
261
+ svgHeight = computed(() => this.hasDesc() ? Math.max(this.expanded(), this.minExpanded()) : HEIGHT, ...(ngDevMode ? [{ debugName: "svgHeight" }] : /* istanbul ignore next */ []));
262
+ expandedContent = computed(() => Math.max(0, this.expanded() - HEIGHT), ...(ngDevMode ? [{ debugName: "expandedContent" }] : /* istanbul ignore next */ []));
263
+ resolvedPillWidth = computed(() => Math.max(this.pillWidth() || HEIGHT, HEIGHT), ...(ngDevMode ? [{ debugName: "resolvedPillWidth" }] : /* istanbul ignore next */ []));
264
+ pillHeight = computed(() => HEIGHT + this.blur() * 3, ...(ngDevMode ? [{ debugName: "pillHeight" }] : /* istanbul ignore next */ []));
265
+ pillX = computed(() => {
266
+ const w = this.resolvedPillWidth();
267
+ const pos = this.pillAlign();
268
+ if (pos === "right")
269
+ return WIDTH - w;
270
+ if (pos === "center")
271
+ return (WIDTH - w) / 2;
272
+ return 0;
273
+ }, ...(ngDevMode ? [{ debugName: "pillX" }] : /* istanbul ignore next */ []));
274
+ pillPath = computed(() => {
275
+ const w = this.resolvedPillWidth();
276
+ const h = HEIGHT;
277
+ const r = this.resolvedRoundness();
278
+ const align = this.pillAlign();
279
+ const open = this.open();
280
+ const x = this.pillX();
281
+ // Helper for rounded corner arc relative
282
+ const arc = (dx, dy) => `a ${r} ${r} 0 0 1 ${dx} ${dy}`;
283
+ let d = "";
284
+ // Start at Top-Left of the pill (relative to x)
285
+ // We'll draw in absolute coordinates or relative? Path commands usually absolute M x y is easiest.
286
+ // Top Left Corner
287
+ d += `M ${x} ${h - r}`; // Start before top-left corner? No, let's start top-left.
288
+ // Actually, standard rect path:
289
+ // Move to x, y+r
290
+ // Arc to x+r, y
291
+ // Line to x+w-r, y
292
+ // Arc to x+w, y+r
293
+ // Line to x+w, y+h-r
294
+ // Arc to x+w-r, y+h
295
+ // Line to x+r, y+h
296
+ // Arc to x, y+h-r
297
+ // Close
298
+ // Top Left
299
+ d += `M ${x} ${r} ${arc(r, -r)}`;
300
+ // Top Right
301
+ d += `L ${x + w - r} 0 ${arc(r, r)}`;
302
+ // Bottom Right
303
+ if (open && align === "right") {
304
+ d += `L ${x + w} ${h}`; // Sharp corner
305
+ }
306
+ else {
307
+ d += `L ${x + w} ${h - r} ${arc(-r, r)}`; // Rounded
308
+ }
309
+ // Bottom Left
310
+ if (open && align === "left") {
311
+ d += `L ${x} ${h}`; // Sharp corner
312
+ }
313
+ else {
314
+ d += `L ${x + r} ${h} ${arc(-r, -r)}`; // Rounded
315
+ }
316
+ d += "Z";
317
+ return d;
318
+ }, ...(ngDevMode ? [{ debugName: "pillPath" }] : /* istanbul ignore next */ []));
319
+ headerTransform = computed(() => {
320
+ const open = this.open();
321
+ const expand = this.expandEdge();
322
+ const ty = open ? (expand === "bottom" ? 3 : -3) : 0;
323
+ const scale = open ? 0.9 : 1;
324
+ return `translateY(${ty}px) scale(${scale})`;
325
+ }, ...(ngDevMode ? [{ debugName: "headerTransform" }] : /* istanbul ignore next */ []));
326
+ bodyPath = computed(() => {
327
+ const w = WIDTH;
328
+ const h = this.open() ? this.expandedContent() : 0;
329
+ const r = this.resolvedRoundness();
330
+ const y = HEIGHT - 1; // 1px overlap to ensure connection
331
+ const align = this.pillAlign();
332
+ if (h <= 0)
333
+ return "";
334
+ // Helper for rounded corner arc
335
+ // A rx ry x-axis-rotation large-arc-flag sweep-flag x y
336
+ const arc = (dx, dy) => `a ${r} ${r} 0 0 1 ${dx} ${dy}`;
337
+ let d = "";
338
+ // Top Left
339
+ if (align === "left") {
340
+ d += `M 0 ${y}`; // Sharp corner
341
+ }
342
+ else {
343
+ d += `M 0 ${y + r} ${arc(r, -r)}`; // Rounded start
344
+ }
345
+ // Top Right
346
+ if (align === "right") {
347
+ d += `L ${w} ${y}`; // Sharp line to corner
348
+ }
349
+ else {
350
+ d += `L ${w - r} ${y} ${arc(r, r)}`; // Line then rounded
351
+ }
352
+ // Bottom Right (Always rounded)
353
+ d += `L ${w} ${y + h - r} ${arc(-r, r)}`;
354
+ // Bottom Left (Always rounded)
355
+ d += `L ${r} ${y + h} ${arc(-r, -r)}`;
356
+ // Close path
357
+ d += "Z";
358
+ return d;
359
+ }, ...(ngDevMode ? [{ debugName: "bodyPath" }] : /* istanbul ignore next */ []));
360
+ constructor() {
361
+ // If no description, collapse immediately
362
+ effect(() => {
363
+ if (!this.hasDesc()) {
364
+ this.isExpanded.set(false);
365
+ }
366
+ else {
367
+ // If has description, start expanded by default
368
+ // But we might want to respect auto-collapse later
369
+ this.isExpanded.set(true);
370
+ }
371
+ }, { allowSignalWrites: true });
372
+ queueMicrotask(() => {
373
+ this.ready.set(true);
374
+ this.ensureMeasurements();
375
+ });
376
+ }
377
+ // private applyView(next: View) {
378
+ // const prev = this.view();
379
+ // const headerKey = `${next.state}-${next.title}`;
380
+ // const prevKey = `${prev.state}-${prev.title}`;
381
+ // this.view.set(next);
382
+ // if (headerKey !== prevKey) {
383
+ // const currentLayer: HeaderLayer = { key: headerKey, view: next };
384
+ // const prevLayer: HeaderLayer = { key: prevKey, view: prev };
385
+ // this.headerLayerPrev.set(prevLayer);
386
+ // this.headerLayerCurrent.set(currentLayer);
387
+ // if (this.headerExitTimer) window.clearTimeout(this.headerExitTimer);
388
+ // this.headerExitTimer = window.setTimeout(() => {
389
+ // this.headerExitTimer = null;
390
+ // this.headerLayerPrev.set(null);
391
+ // }, HEADER_EXIT_MS);
392
+ // } else {
393
+ // this.headerLayerCurrent.set({ key: headerKey, view: next });
394
+ // }
395
+ // }
396
+ ngOnDestroy() {
397
+ this.roHeader?.disconnect();
398
+ this.roContent?.disconnect();
399
+ if (this.headerExitTimer)
400
+ window.clearTimeout(this.headerExitTimer);
401
+ if (this.autoExpandTimer)
402
+ window.clearTimeout(this.autoExpandTimer);
403
+ if (this.autoCollapseTimer)
404
+ window.clearTimeout(this.autoCollapseTimer);
405
+ if (this.swapTimer)
406
+ window.clearTimeout(this.swapTimer);
407
+ }
408
+ ensureMeasurements() {
409
+ if (this.hasMeasured)
410
+ return;
411
+ this.hasMeasured = true;
412
+ const root = this.hostEl.nativeElement;
413
+ const inner = root.querySelector("[data-dt-header-inner][data-layer='current']");
414
+ const header = root.querySelector("[data-dt-header]");
415
+ const content = root.querySelector("[data-dt-description]");
416
+ if (!inner || !header)
417
+ return;
418
+ // Throttled measurement
419
+ let rafHeader = null;
420
+ const measureHeader = () => {
421
+ if (rafHeader)
422
+ return;
423
+ // Run outside angular to avoid infinite CD loops from RO
424
+ this.ngZone.runOutsideAngular(() => {
425
+ rafHeader = requestAnimationFrame(() => {
426
+ rafHeader = null;
427
+ const cs = getComputedStyle(header);
428
+ const pad = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight);
429
+ const w = inner.scrollWidth + pad + PILL_PADDING;
430
+ // Only update if difference is significant to stop 1px loops
431
+ if (Math.abs(w - this.pillWidth()) > 1.5) {
432
+ this.pillWidth.set(w);
433
+ this.cdr.detectChanges(); // Local detect changes only
434
+ }
435
+ });
436
+ });
437
+ };
438
+ let rafContent = null;
439
+ const measureContent = () => {
440
+ const el = root.querySelector("[data-dt-description]");
441
+ if (!el)
442
+ return;
443
+ if (rafContent)
444
+ return;
445
+ this.ngZone.runOutsideAngular(() => {
446
+ rafContent = requestAnimationFrame(() => {
447
+ rafContent = null;
448
+ if (Math.abs(el.scrollHeight - this.contentHeight()) > 1.5) {
449
+ this.contentHeight.set(el.scrollHeight);
450
+ this.cdr.detectChanges();
451
+ }
452
+ });
453
+ });
454
+ };
455
+ measureHeader();
456
+ measureContent();
457
+ this.roHeader = new ResizeObserver(() => measureHeader());
458
+ this.roHeader.observe(inner);
459
+ if (content) {
460
+ this.roContent = new ResizeObserver(() => measureContent());
461
+ this.roContent.observe(content);
462
+ }
463
+ }
464
+ resolvedIcon(v) {
465
+ const icon = v.iconSvg ??
466
+ (v.state === "success"
467
+ ? ICONS.check
468
+ : v.state === "loading"
469
+ ? ICONS.loaderCircle('data-dt-icon="spin" aria-hidden="true"')
470
+ : v.state === "error"
471
+ ? ICONS.x
472
+ : v.state === "warning"
473
+ ? ICONS.circleAlert
474
+ : v.state === "info"
475
+ ? ICONS.lifeBuoy
476
+ : ICONS.arrowRight);
477
+ return this.sanitizer.bypassSecurityTrustHtml(icon);
478
+ }
479
+ handleEnter() {
480
+ this.entered.emit(this.toast().id);
481
+ if (this.hasDesc())
482
+ this.isExpanded.set(true);
483
+ }
484
+ handleLeave() {
485
+ this.left.emit(this.toast().id);
486
+ this.isExpanded.set(false);
487
+ }
488
+ handleTransitionEnd(e) {
489
+ if (e.propertyName !== "height" && e.propertyName !== "transform")
490
+ return;
491
+ if (this.open())
492
+ return;
493
+ const pending = this.pendingSwap;
494
+ if (!pending)
495
+ return;
496
+ if (this.swapTimer) {
497
+ window.clearTimeout(this.swapTimer);
498
+ this.swapTimer = null;
499
+ }
500
+ // this.applyView(pending.payload);
501
+ this.pendingSwap = null;
502
+ }
503
+ handleButtonClick(e) {
504
+ e.preventDefault();
505
+ e.stopPropagation();
506
+ this.view().button?.onClick();
507
+ }
508
+ handlePointerDown(e) {
509
+ if (this.toast().exiting)
510
+ return;
511
+ const target = e.target;
512
+ if (target.closest("[data-dt-button]"))
513
+ return;
514
+ this.pointerStartY = e.clientY;
515
+ const el = e.currentTarget;
516
+ const SWIPE_DISMISS = 30;
517
+ const SWIPE_MAX = 20;
518
+ const onMove = (ev) => {
519
+ if (this.pointerStartY == null)
520
+ return;
521
+ const dy = ev.clientY - this.pointerStartY;
522
+ const sign = dy > 0 ? 1 : -1;
523
+ const clamped = Math.min(Math.abs(dy), SWIPE_MAX) * sign;
524
+ el.style.transform = `translateY(${clamped}px)`;
525
+ };
526
+ const onUp = (ev) => {
527
+ if (this.pointerStartY == null)
528
+ return;
529
+ const dy = ev.clientY - this.pointerStartY;
530
+ this.pointerStartY = null;
531
+ el.style.transform = "";
532
+ el.removeEventListener("pointermove", onMove);
533
+ el.removeEventListener("pointerup", onUp);
534
+ if (Math.abs(dy) > SWIPE_DISMISS) {
535
+ this.dismissed.emit(this.toast().id);
536
+ }
537
+ else if (Math.abs(dy) < 5) {
538
+ // It's a tap
539
+ this.handleTap();
540
+ }
541
+ };
542
+ el.setPointerCapture(e.pointerId);
543
+ el.addEventListener("pointermove", onMove, { passive: true });
544
+ el.addEventListener("pointerup", onUp, { passive: true });
545
+ }
546
+ handleTap() {
547
+ if (this.hasDesc()) {
548
+ if (this.isExpanded()) {
549
+ // 1 click to collapse if it has description and is open
550
+ this.isExpanded.set(false);
551
+ }
552
+ else {
553
+ // If already collapsed, another click closes the toast
554
+ this.dismissed.emit(this.toast().id);
555
+ }
556
+ }
557
+ else {
558
+ // If no description, a click simply closes it
559
+ this.dismissed.emit(this.toast().id);
560
+ }
561
+ }
562
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DynamicToastComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
563
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.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\"\n [attr.data-state]=\"view().state\"\n (mouseenter)=\"handleEnter()\"\n (mouseleave)=\"handleLeave()\"\n>\n <!-- El Canvas contiene el filtro Gooey -->\n <div data-dt-canvas [style.filter]=\"'url(#' + filterId + ')'\">\n <svg [attr.width]=\"WIDTH\" [attr.height]=\"800\" style=\"overflow: visible\">\n <defs>\n <filter [id]=\"filterId\" color-interpolation-filters=\"sRGB\">\n <feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"8\" result=\"blur\" />\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 19 -9\"\n result=\"goo\"\n />\n <feComposite in=\"SourceGraphic\" in2=\"goo\" operator=\"atop\" />\n </filter>\n </defs>\n\n <!-- Pill superior -->\n <path #pillPath [attr.fill]=\"view().fill\" />\n\n <!-- Body expansible -->\n <path #bodyPath [attr.fill]=\"view().fill\" />\n </svg>\n </div>\n\n <!-- Capa de contenido (Header) -->\n <div data-dt-header>\n <div data-dt-header-inner>\n <div data-dt-badge [innerHTML]=\"resolvedIcon(view())\"></div>\n <span data-dt-title>{{ view().title }}</span>\n </div>\n </div>\n\n <!-- Capa de contenido (Descripci\u00F3n) -->\n <div data-dt-content [style.opacity]=\"open() ? 1 : 0\">\n <div #contentRef data-dt-description>\n @if (view().description) {\n <span>{{ view().description }}</span>\n }\n @if (view().button) {\n <button (click)=\"handleButtonClick($event)\" data-dt-button>\n {{ view().button?.title }}\n </button>\n }\n </div>\n </div>\n</button>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
564
+ }
565
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DynamicToastComponent, decorators: [{
566
+ type: Component,
567
+ 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\"\n [attr.data-state]=\"view().state\"\n (mouseenter)=\"handleEnter()\"\n (mouseleave)=\"handleLeave()\"\n>\n <!-- El Canvas contiene el filtro Gooey -->\n <div data-dt-canvas [style.filter]=\"'url(#' + filterId + ')'\">\n <svg [attr.width]=\"WIDTH\" [attr.height]=\"800\" style=\"overflow: visible\">\n <defs>\n <filter [id]=\"filterId\" color-interpolation-filters=\"sRGB\">\n <feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"8\" result=\"blur\" />\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 19 -9\"\n result=\"goo\"\n />\n <feComposite in=\"SourceGraphic\" in2=\"goo\" operator=\"atop\" />\n </filter>\n </defs>\n\n <!-- Pill superior -->\n <path #pillPath [attr.fill]=\"view().fill\" />\n\n <!-- Body expansible -->\n <path #bodyPath [attr.fill]=\"view().fill\" />\n </svg>\n </div>\n\n <!-- Capa de contenido (Header) -->\n <div data-dt-header>\n <div data-dt-header-inner>\n <div data-dt-badge [innerHTML]=\"resolvedIcon(view())\"></div>\n <span data-dt-title>{{ view().title }}</span>\n </div>\n </div>\n\n <!-- Capa de contenido (Descripci\u00F3n) -->\n <div data-dt-content [style.opacity]=\"open() ? 1 : 0\">\n <div #contentRef data-dt-description>\n @if (view().description) {\n <span>{{ view().description }}</span>\n }\n @if (view().button) {\n <button (click)=\"handleButtonClick($event)\" data-dt-button>\n {{ view().button?.title }}\n </button>\n }\n </div>\n </div>\n</button>\n" }]
568
+ }], 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"] }] } });
569
+
570
+ const pillAlign = (pos) => pos.includes("right") ? "right" : pos.includes("center") ? "center" : "left";
571
+ const expandDir = (pos) => pos.startsWith("top") ? "bottom" : "top";
572
+ class DynamicToastViewportComponent {
573
+ position = input("top-right", ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
574
+ offset = input(undefined, ...(ngDevMode ? [{ debugName: "offset" }] : /* istanbul ignore next */ []));
575
+ service = inject(DynamicToastService);
576
+ hovering = signal(new Set(), ...(ngDevMode ? [{ debugName: "hovering" }] : /* istanbul ignore next */ []));
577
+ activeId = signal(undefined, ...(ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []));
578
+ latestId = computed(() => {
579
+ const list = this.service.toasts();
580
+ for (let i = list.length - 1; i >= 0; i--) {
581
+ if (!list[i].exiting)
582
+ return list[i].id;
583
+ }
584
+ return undefined;
585
+ }, ...(ngDevMode ? [{ debugName: "latestId" }] : /* istanbul ignore next */ []));
586
+ groups = computed(() => {
587
+ const toasts = this.service.toasts();
588
+ const byPos = new Map();
589
+ for (const t of toasts) {
590
+ const p = (t.position ?? this.position());
591
+ const arr = byPos.get(p);
592
+ if (arr)
593
+ arr.push(t);
594
+ else
595
+ byPos.set(p, [t]);
596
+ }
597
+ const offset = this.offset();
598
+ const off = offset === undefined
599
+ ? undefined
600
+ : typeof offset === "object"
601
+ ? offset
602
+ : { top: offset, right: offset, bottom: offset, left: offset };
603
+ const px = (v) => v === undefined ? undefined : typeof v === "number" ? `${v}px` : v;
604
+ const res = [];
605
+ for (const [pos, items] of byPos) {
606
+ const style = {};
607
+ if (off) {
608
+ if (pos.startsWith("top") && off.top !== undefined)
609
+ style.top = px(off.top);
610
+ if (pos.startsWith("bottom") && off.bottom !== undefined)
611
+ style.bottom = px(off.bottom);
612
+ if (pos.endsWith("left") && off.left !== undefined)
613
+ style.left = px(off.left);
614
+ if (pos.endsWith("right") && off.right !== undefined)
615
+ style.right = px(off.right);
616
+ }
617
+ res.push({
618
+ pos,
619
+ items,
620
+ pill: pillAlign(pos),
621
+ expand: expandDir(pos),
622
+ style: off ? style : undefined,
623
+ });
624
+ }
625
+ return res;
626
+ }, ...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
627
+ onToastEnter(id) {
628
+ const next = new Set(this.hovering());
629
+ next.add(id);
630
+ this.hovering.set(next);
631
+ this.activeId.set(id);
632
+ this.service.pauseTimers();
633
+ }
634
+ onToastLeave(id) {
635
+ const next = new Set(this.hovering());
636
+ next.delete(id);
637
+ this.hovering.set(next);
638
+ if (next.size > 0)
639
+ return;
640
+ queueMicrotask(() => {
641
+ if (this.hovering().size > 0)
642
+ return;
643
+ this.activeId.set(this.latestId());
644
+ this.service.resumeTimers();
645
+ });
646
+ }
647
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DynamicToastViewportComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
648
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.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 });
649
+ }
650
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DynamicToastViewportComponent, decorators: [{
651
+ type: Component,
652
+ 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"] }]
653
+ }], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }] } });
654
+
655
+ /*
656
+ * Public API Surface of ngx-dynamic-toast
657
+ */
658
+
659
+ /**
660
+ * Generated bundle index. Do not edit.
661
+ */
662
+
663
+ 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 };
664
+ //# sourceMappingURL=ngx-dynamic-toast.mjs.map