@cdevhub/ngx-tw 0.3.0 → 0.5.0

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,528 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, inject, Injector, ElementRef, computed, TemplateRef, untracked, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { Overlay, createGlobalPositionStrategy } from '@angular/cdk/overlay';
4
+ import { CdkPortalOutlet, ComponentPortal } from '@angular/cdk/portal';
5
+ import { NgTemplateOutlet } from '@angular/common';
6
+ import { LiveAnnouncer } from '@angular/cdk/a11y';
7
+ import { TW_TOAST_REF, TW_TOAST_DATA, ToastComponent, ToastActionDirective } from './cdevhub-ngx-tw-toast.mjs';
8
+
9
+ const POSITION_AXIS = {
10
+ 'top-right': 'right',
11
+ 'bottom-right': 'right',
12
+ 'top-left': 'left',
13
+ 'bottom-left': 'left',
14
+ 'top-center': 'top',
15
+ 'bottom-center': 'bottom',
16
+ };
17
+ const POSITION_HOST_CLASSES = {
18
+ 'top-right': 'items-end',
19
+ 'bottom-right': 'items-end',
20
+ 'top-left': 'items-start',
21
+ 'bottom-left': 'items-start',
22
+ 'top-center': 'items-center',
23
+ 'bottom-center': 'items-center',
24
+ };
25
+ const POSITION_ORDER_REVERSED = {
26
+ 'top-right': false,
27
+ 'top-left': false,
28
+ 'top-center': false,
29
+ 'bottom-right': true,
30
+ 'bottom-left': true,
31
+ 'bottom-center': true,
32
+ };
33
+ const SWIPE_DISMISS_FRACTION = 0.4;
34
+ const SWIPE_MAX_OPACITY_FADE = 0.6;
35
+ /**
36
+ * Internal flex-column host rendered inside each per-position CDK overlay.
37
+ * Stacks visible toasts via `@for`, wires pause-on-interaction, Escape
38
+ * dismissal, swipe gestures, and `LiveAnnouncer` announcements.
39
+ *
40
+ * @docs-private
41
+ */
42
+ class ToastContainerComponent {
43
+ /** Per-position stacking anchor. Mutated from {@link ToastService} via `.instance.position.set(...)`. */
44
+ position = signal('bottom-right', /* @ts-ignore */
45
+ ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
46
+ /** Accessible label applied to the `role="region"` host. Mutated from the service on init. */
47
+ regionLabel = signal('Notifications', /* @ts-ignore */
48
+ ...(ngDevMode ? [{ debugName: "regionLabel" }] : /* istanbul ignore next */ []));
49
+ /**
50
+ * Toasts currently assigned to this container. The service pushes toasts
51
+ * into this signal; the container filters by state to drive `animate.leave`.
52
+ */
53
+ visibleRefs = signal([], /* @ts-ignore */
54
+ ...(ngDevMode ? [{ debugName: "visibleRefs" }] : /* istanbul ignore next */ []));
55
+ injector = inject(Injector);
56
+ liveAnnouncer = inject(LiveAnnouncer);
57
+ host = inject((ElementRef));
58
+ swipeSessions = new WeakMap();
59
+ entries = computed(() => {
60
+ const pos = this.position();
61
+ const axis = POSITION_AXIS[pos];
62
+ const enter = `toast-enter-${axis}`;
63
+ const leave = `toast-leave-${axis}`;
64
+ const refs = this.visibleRefs().filter((ref) => {
65
+ const s = ref.state();
66
+ return s === 'entering' || s === 'visible' || s === 'paused';
67
+ });
68
+ return refs.map((ref) => ({
69
+ ref,
70
+ kind: resolveKind(ref.content()),
71
+ enterClass: enter,
72
+ leaveClass: leave,
73
+ }));
74
+ }, /* @ts-ignore */
75
+ ...(ngDevMode ? [{ debugName: "entries" }] : /* istanbul ignore next */ []));
76
+ orderedEntries = computed(() => {
77
+ const list = this.entries();
78
+ return POSITION_ORDER_REVERSED[this.position()] ? [...list].reverse() : list;
79
+ }, /* @ts-ignore */
80
+ ...(ngDevMode ? [{ debugName: "orderedEntries" }] : /* istanbul ignore next */ []));
81
+ hostClasses = computed(() => {
82
+ const base = 'flex flex-col gap-2 w-full max-w-sm';
83
+ const align = POSITION_HOST_CLASSES[this.position()];
84
+ return `${base} ${align}`;
85
+ }, /* @ts-ignore */
86
+ ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
87
+ /** @internal Called by the service right after attaching a new toast. Runs `LiveAnnouncer`. */
88
+ _announceOpen(ref) {
89
+ const politeness = this.resolvePoliteness(ref);
90
+ if (politeness === 'off')
91
+ return;
92
+ const msg = this.resolveAnnouncementText(ref);
93
+ if (msg)
94
+ this.liveAnnouncer.announce(msg, politeness);
95
+ }
96
+ /** @internal Called by the service when `ref.update()` fires — re-announces with the new severity / content. */
97
+ _announceUpdate(ref) {
98
+ this._announceOpen(ref);
99
+ }
100
+ /** @internal Captures the component instance after `cdkPortalOutlet` attaches. */
101
+ onPortalAttached(ref, attached) {
102
+ if (attached && 'instance' in attached) {
103
+ ref.componentInstance = attached.instance;
104
+ }
105
+ }
106
+ /** @internal Injector factory for component-class content. Provides `TW_TOAST_DATA` + `TW_TOAST_REF`. */
107
+ _createContentInjector(ref) {
108
+ return Injector.create({
109
+ parent: this.injector,
110
+ providers: [
111
+ { provide: TW_TOAST_REF, useValue: ref },
112
+ { provide: TW_TOAST_DATA, useValue: ref.data() },
113
+ ],
114
+ });
115
+ }
116
+ // ── Template helpers ──
117
+ asString(content) {
118
+ return typeof content === 'string' ? content : '';
119
+ }
120
+ asTemplate(content) {
121
+ return content instanceof TemplateRef ? content : null;
122
+ }
123
+ templateContext(ref) {
124
+ return { $implicit: ref.data(), ref };
125
+ }
126
+ panelClassFor(ref) {
127
+ const raw = ref.config.panelClass;
128
+ if (!raw)
129
+ return '';
130
+ return Array.isArray(raw) ? raw.join(' ') : raw;
131
+ }
132
+ // ── Interaction handlers ──
133
+ onPointerEnter(ref) {
134
+ ref._setHovered(true);
135
+ }
136
+ onPointerLeave(ref) {
137
+ ref._setHovered(false);
138
+ }
139
+ onFocusIn(ref) {
140
+ ref._setFocused(true);
141
+ }
142
+ onFocusOut(ref, event) {
143
+ const related = event.relatedTarget;
144
+ const target = event.currentTarget;
145
+ if (related && target && target.contains(related))
146
+ return;
147
+ ref._setFocused(false);
148
+ }
149
+ onEscape(ref, event) {
150
+ event.stopPropagation();
151
+ event.preventDefault();
152
+ ref._dismissWith('manual');
153
+ }
154
+ onSwipeStart(ref, event, el) {
155
+ if (!ref.config.swipeToDismiss)
156
+ return;
157
+ if (event.button !== 0)
158
+ return;
159
+ const target = event.target;
160
+ if (target?.closest('button, a, input, select, textarea, [role="button"]'))
161
+ return;
162
+ const width = el.getBoundingClientRect().width;
163
+ this.swipeSessions.set(ref, {
164
+ pointerId: event.pointerId,
165
+ startX: event.clientX,
166
+ width,
167
+ active: false,
168
+ });
169
+ el.setPointerCapture(event.pointerId);
170
+ const onMove = (e) => this.onSwipeMove(ref, e, el);
171
+ const onUp = (e) => this.onSwipeEnd(ref, e, el, onMove, onUp);
172
+ el.addEventListener('pointermove', onMove);
173
+ el.addEventListener('pointerup', onUp);
174
+ el.addEventListener('pointercancel', onUp);
175
+ }
176
+ onSwipeMove(ref, event, _el) {
177
+ const session = this.swipeSessions.get(ref);
178
+ if (!session || event.pointerId !== session.pointerId)
179
+ return;
180
+ const dx = event.clientX - session.startX;
181
+ if (!session.active && Math.abs(dx) < 6)
182
+ return;
183
+ session.active = true;
184
+ ref.swipeTransform.set(`translate3d(${dx}px, 0, 0)`);
185
+ const fade = 1 - Math.min(Math.abs(dx) / session.width, 1) * SWIPE_MAX_OPACITY_FADE;
186
+ ref.swipeOpacity.set(fade);
187
+ }
188
+ onSwipeEnd(ref, event, el, onMove, onUp) {
189
+ const session = this.swipeSessions.get(ref);
190
+ el.removeEventListener('pointermove', onMove);
191
+ el.removeEventListener('pointerup', onUp);
192
+ el.removeEventListener('pointercancel', onUp);
193
+ if (!session || event.pointerId !== session.pointerId)
194
+ return;
195
+ try {
196
+ el.releasePointerCapture(session.pointerId);
197
+ }
198
+ catch {
199
+ /* no-op */
200
+ }
201
+ this.swipeSessions.delete(ref);
202
+ if (!session.active)
203
+ return;
204
+ const dx = event.clientX - session.startX;
205
+ const threshold = session.width * SWIPE_DISMISS_FRACTION;
206
+ const allowed = this.swipeDirectionAllowed(dx);
207
+ if (Math.abs(dx) >= threshold && allowed) {
208
+ untracked(() => {
209
+ ref.swipeTransform.set(`translate3d(${Math.sign(dx) * session.width * 1.2}px, 0, 0)`);
210
+ ref.swipeOpacity.set(0);
211
+ ref.leaveAnimationOverride.set('fade-out');
212
+ });
213
+ ref._dismissWith('swipe');
214
+ }
215
+ else {
216
+ ref.swipeTransform.set(null);
217
+ ref.swipeOpacity.set(null);
218
+ }
219
+ }
220
+ swipeDirectionAllowed(dx) {
221
+ const pos = this.position();
222
+ if (pos === 'top-right' || pos === 'bottom-right')
223
+ return dx > 0;
224
+ if (pos === 'top-left' || pos === 'bottom-left')
225
+ return dx < 0;
226
+ return true;
227
+ }
228
+ resolvePoliteness(ref) {
229
+ if (ref.config.politeness)
230
+ return ref.config.politeness;
231
+ return ref.severity() === 'error' ? 'assertive' : 'polite';
232
+ }
233
+ resolveAnnouncementText(ref) {
234
+ const explicit = ref.ariaLabel();
235
+ if (explicit)
236
+ return explicit;
237
+ const content = ref.content();
238
+ if (typeof content === 'string')
239
+ return content;
240
+ const host = this.host.nativeElement.querySelector(`[data-toast-id="${ref.id}"]`);
241
+ if (host)
242
+ return host.textContent?.trim() ?? '';
243
+ return this.host.nativeElement.textContent?.trim() ?? '';
244
+ }
245
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: ToastContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
246
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: ToastContainerComponent, isStandalone: true, selector: "tw-toast-container", host: { attributes: { "role": "region" }, properties: { "class": "hostClasses()", "attr.aria-label": "regionLabel()", "attr.data-position": "position()" } }, ngImport: i0, template: `
247
+ @for (entry of orderedEntries(); track entry.ref.id) {
248
+ <!-- Toast entry wrapper; the projected <tw-toast> is the focusable affordance.
249
+ This element only forwards pointer/focus events so the container can
250
+ pause auto-dismiss while the user is interacting. -->
251
+ <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->
252
+ <div
253
+ class="pointer-events-auto w-full max-w-sm"
254
+ [attr.data-toast-id]="entry.ref.id"
255
+ [style.transform]="entry.ref.swipeTransform() || null"
256
+ [style.opacity]="entry.ref.swipeOpacity() ?? null"
257
+ [style.touch-action]="'pan-y'"
258
+ [animate.enter]="entry.enterClass"
259
+ [animate.leave]="entry.ref.leaveAnimationOverride() ?? entry.leaveClass"
260
+ (pointerenter)="onPointerEnter(entry.ref)"
261
+ (pointerleave)="onPointerLeave(entry.ref)"
262
+ (focusin)="onFocusIn(entry.ref)"
263
+ (focusout)="onFocusOut(entry.ref, $event)"
264
+ (keydown.escape)="onEscape(entry.ref, $event)"
265
+ (pointerdown)="onSwipeStart(entry.ref, $event, swipeEl)"
266
+ #swipeEl
267
+ >
268
+ @switch (entry.kind) {
269
+ @case ('string') {
270
+ <tw-toast
271
+ [severity]="entry.ref.severity()"
272
+ [dismissible]="entry.ref.dismissible()"
273
+ [icon]="entry.ref.icon()"
274
+ [ariaLabel]="entry.ref.ariaLabel()"
275
+ [class]="panelClassFor(entry.ref)"
276
+ (dismissed)="entry.ref._dismissWith('manual')"
277
+ (actionClicked)="entry.ref.triggerAction()"
278
+ >
279
+ {{ asString(entry.ref.content()) }}
280
+ @if (entry.ref.action(); as action) {
281
+ <button twToastAction>{{ action.label }}</button>
282
+ }
283
+ </tw-toast>
284
+ }
285
+ @case ('template') {
286
+ <tw-toast
287
+ [severity]="entry.ref.severity()"
288
+ [dismissible]="entry.ref.dismissible()"
289
+ [icon]="entry.ref.icon()"
290
+ [ariaLabel]="entry.ref.ariaLabel()"
291
+ [class]="panelClassFor(entry.ref)"
292
+ (dismissed)="entry.ref._dismissWith('manual')"
293
+ (actionClicked)="entry.ref.triggerAction()"
294
+ >
295
+ <ng-container
296
+ [ngTemplateOutlet]="asTemplate(entry.ref.content())"
297
+ [ngTemplateOutletContext]="templateContext(entry.ref)"
298
+ />
299
+ @if (entry.ref.action(); as action) {
300
+ <button twToastAction>{{ action.label }}</button>
301
+ }
302
+ </tw-toast>
303
+ }
304
+ @case ('component') {
305
+ <ng-template
306
+ [cdkPortalOutlet]="entry.ref._portal"
307
+ (attached)="onPortalAttached(entry.ref, $event)"
308
+ />
309
+ }
310
+ }
311
+ </div>
312
+ }
313
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { kind: "component", type: ToastComponent, selector: "tw-toast", inputs: ["severity", "dismissible", "icon", "ariaLabel"], outputs: ["dismissed", "actionClicked"] }, { kind: "directive", type: ToastActionDirective, selector: "[twToastAction]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
314
+ }
315
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: ToastContainerComponent, decorators: [{
316
+ type: Component,
317
+ args: [{
318
+ selector: 'tw-toast-container',
319
+ changeDetection: ChangeDetectionStrategy.OnPush,
320
+ encapsulation: ViewEncapsulation.None,
321
+ imports: [NgTemplateOutlet, CdkPortalOutlet, ToastComponent, ToastActionDirective],
322
+ host: {
323
+ role: 'region',
324
+ '[class]': 'hostClasses()',
325
+ '[attr.aria-label]': 'regionLabel()',
326
+ '[attr.data-position]': 'position()',
327
+ },
328
+ template: `
329
+ @for (entry of orderedEntries(); track entry.ref.id) {
330
+ <!-- Toast entry wrapper; the projected <tw-toast> is the focusable affordance.
331
+ This element only forwards pointer/focus events so the container can
332
+ pause auto-dismiss while the user is interacting. -->
333
+ <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->
334
+ <div
335
+ class="pointer-events-auto w-full max-w-sm"
336
+ [attr.data-toast-id]="entry.ref.id"
337
+ [style.transform]="entry.ref.swipeTransform() || null"
338
+ [style.opacity]="entry.ref.swipeOpacity() ?? null"
339
+ [style.touch-action]="'pan-y'"
340
+ [animate.enter]="entry.enterClass"
341
+ [animate.leave]="entry.ref.leaveAnimationOverride() ?? entry.leaveClass"
342
+ (pointerenter)="onPointerEnter(entry.ref)"
343
+ (pointerleave)="onPointerLeave(entry.ref)"
344
+ (focusin)="onFocusIn(entry.ref)"
345
+ (focusout)="onFocusOut(entry.ref, $event)"
346
+ (keydown.escape)="onEscape(entry.ref, $event)"
347
+ (pointerdown)="onSwipeStart(entry.ref, $event, swipeEl)"
348
+ #swipeEl
349
+ >
350
+ @switch (entry.kind) {
351
+ @case ('string') {
352
+ <tw-toast
353
+ [severity]="entry.ref.severity()"
354
+ [dismissible]="entry.ref.dismissible()"
355
+ [icon]="entry.ref.icon()"
356
+ [ariaLabel]="entry.ref.ariaLabel()"
357
+ [class]="panelClassFor(entry.ref)"
358
+ (dismissed)="entry.ref._dismissWith('manual')"
359
+ (actionClicked)="entry.ref.triggerAction()"
360
+ >
361
+ {{ asString(entry.ref.content()) }}
362
+ @if (entry.ref.action(); as action) {
363
+ <button twToastAction>{{ action.label }}</button>
364
+ }
365
+ </tw-toast>
366
+ }
367
+ @case ('template') {
368
+ <tw-toast
369
+ [severity]="entry.ref.severity()"
370
+ [dismissible]="entry.ref.dismissible()"
371
+ [icon]="entry.ref.icon()"
372
+ [ariaLabel]="entry.ref.ariaLabel()"
373
+ [class]="panelClassFor(entry.ref)"
374
+ (dismissed)="entry.ref._dismissWith('manual')"
375
+ (actionClicked)="entry.ref.triggerAction()"
376
+ >
377
+ <ng-container
378
+ [ngTemplateOutlet]="asTemplate(entry.ref.content())"
379
+ [ngTemplateOutletContext]="templateContext(entry.ref)"
380
+ />
381
+ @if (entry.ref.action(); as action) {
382
+ <button twToastAction>{{ action.label }}</button>
383
+ }
384
+ </tw-toast>
385
+ }
386
+ @case ('component') {
387
+ <ng-template
388
+ [cdkPortalOutlet]="entry.ref._portal"
389
+ (attached)="onPortalAttached(entry.ref, $event)"
390
+ />
391
+ }
392
+ }
393
+ </div>
394
+ }
395
+ `,
396
+ }]
397
+ }] });
398
+ function resolveKind(content) {
399
+ if (typeof content === 'string')
400
+ return 'string';
401
+ if (content instanceof TemplateRef)
402
+ return 'template';
403
+ return 'component';
404
+ }
405
+
406
+ const OVERLAY_EDGE_OFFSET = '1rem';
407
+ /**
408
+ * Rendering half of the toast feature: owns the CDK overlays, the per-position
409
+ * {@link ToastContainerComponent} instances, and every `LiveAnnouncer` call.
410
+ *
411
+ * This module is reached only through a dynamic `import()` in `ToastService`,
412
+ * which is what keeps `@angular/cdk/overlay`, the toast components, and
413
+ * `tailwind-variants` out of a consumer's initial bundle. Nothing here may be
414
+ * imported statically from `toast.ts` — a value import (as opposed to a
415
+ * `import type`) would pull the whole graph back into the eager chunk and
416
+ * silently undo the split. See `toast.spec.ts` for the guard test.
417
+ *
418
+ * @docs-private
419
+ */
420
+ class ToastRenderer {
421
+ injector;
422
+ regionAriaLabel;
423
+ overlay;
424
+ positionOverlays = new Map();
425
+ disposed = false;
426
+ constructor(injector, regionAriaLabel) {
427
+ this.injector = injector;
428
+ this.regionAriaLabel = regionAriaLabel;
429
+ // Resolved here rather than injected into `ToastService`, so the `Overlay`
430
+ // symbol lives in this lazily-loaded chunk. It is `providedIn: 'root'`, so
431
+ // no eager provider is required.
432
+ this.overlay = injector.get(Overlay);
433
+ }
434
+ /**
435
+ * Render a toast into its position container, creating the overlay on first
436
+ * use. Returns `false` if the renderer has already been disposed.
437
+ */
438
+ attach(ref, position) {
439
+ if (this.disposed)
440
+ return false;
441
+ const entry = this.getContainerForPosition(position);
442
+ const instance = entry.containerRef.instance;
443
+ // Component-class content needs an injector built from the container, so
444
+ // the portal cannot be created until the container exists.
445
+ const content = ref.content();
446
+ if (isComponentConstructor(content)) {
447
+ ref._portal = new ComponentPortal(content, null, instance._createContentInjector(ref));
448
+ }
449
+ instance.visibleRefs.update((list) => [...list, ref]);
450
+ ref._overlayPanelElement = entry.overlayRef.overlayElement;
451
+ return true;
452
+ }
453
+ /** Announce a freshly attached toast to assistive technology. */
454
+ announceOpen(ref) {
455
+ this.containerFor(ref)?._announceOpen(ref);
456
+ }
457
+ /** Re-announce a toast whose content or severity changed via `update()`. */
458
+ announceUpdate(ref) {
459
+ this.containerFor(ref)?._announceUpdate(ref);
460
+ }
461
+ /** Drop a dismissed toast from its container's render list. */
462
+ detach(ref) {
463
+ const instance = this.containerFor(ref);
464
+ if (!instance)
465
+ return;
466
+ instance.visibleRefs.update((list) => list.filter((r) => r !== ref));
467
+ }
468
+ /** Tear down every overlay this renderer created. */
469
+ dispose() {
470
+ this.disposed = true;
471
+ for (const { overlayRef } of this.positionOverlays.values()) {
472
+ overlayRef.dispose();
473
+ }
474
+ this.positionOverlays.clear();
475
+ }
476
+ containerFor(ref) {
477
+ return this.positionOverlays.get(ref.config.position ?? 'bottom-right')?.containerRef
478
+ .instance;
479
+ }
480
+ getContainerForPosition(position) {
481
+ const existing = this.positionOverlays.get(position);
482
+ if (existing)
483
+ return existing;
484
+ const overlayRef = this.overlay.create({
485
+ positionStrategy: this.buildPositionStrategy(position),
486
+ scrollStrategy: this.overlay.scrollStrategies.noop(),
487
+ hasBackdrop: false,
488
+ panelClass: ['tw-toast-overlay', `tw-toast-overlay-${position}`],
489
+ });
490
+ const containerPortal = new ComponentPortal(ToastContainerComponent, null, this.injector);
491
+ const containerRef = overlayRef.attach(containerPortal);
492
+ containerRef.instance.position.set(position);
493
+ containerRef.instance.regionLabel.set(this.regionAriaLabel);
494
+ const entry = { overlayRef, containerRef };
495
+ this.positionOverlays.set(position, entry);
496
+ return entry;
497
+ }
498
+ buildPositionStrategy(position) {
499
+ const strategy = createGlobalPositionStrategy(this.injector);
500
+ switch (position) {
501
+ case 'top-right':
502
+ strategy.top(OVERLAY_EDGE_OFFSET).right(OVERLAY_EDGE_OFFSET);
503
+ break;
504
+ case 'top-left':
505
+ strategy.top(OVERLAY_EDGE_OFFSET).left(OVERLAY_EDGE_OFFSET);
506
+ break;
507
+ case 'top-center':
508
+ strategy.top(OVERLAY_EDGE_OFFSET).centerHorizontally();
509
+ break;
510
+ case 'bottom-right':
511
+ strategy.bottom(OVERLAY_EDGE_OFFSET).right(OVERLAY_EDGE_OFFSET);
512
+ break;
513
+ case 'bottom-left':
514
+ strategy.bottom(OVERLAY_EDGE_OFFSET).left(OVERLAY_EDGE_OFFSET);
515
+ break;
516
+ case 'bottom-center':
517
+ strategy.bottom(OVERLAY_EDGE_OFFSET).centerHorizontally();
518
+ break;
519
+ }
520
+ return strategy;
521
+ }
522
+ }
523
+ function isComponentConstructor(value) {
524
+ return typeof value === 'function' && !(value instanceof TemplateRef);
525
+ }
526
+
527
+ export { ToastRenderer };
528
+ //# sourceMappingURL=cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs","sources":["../../../projects/ngx-tw/toast/toast-container.ts","../../../projects/ngx-tw/toast/toast-renderer.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n type ComponentRef,\n Component,\n computed,\n ElementRef,\n Injector,\n TemplateRef,\n ViewEncapsulation,\n inject,\n signal,\n untracked,\n} from '@angular/core';\nimport {\n CdkPortalOutlet,\n type CdkPortalOutletAttachedRef,\n} from '@angular/cdk/portal';\nimport { LiveAnnouncer } from '@angular/cdk/a11y';\nimport { ToastActionDirective, ToastComponent } from './toast-component';\nimport {\n TW_TOAST_DATA,\n TW_TOAST_REF,\n type ToastPosition,\n type ToastTemplateContext,\n} from './toast-config';\nimport type { ToastRef } from './toast-ref';\n\ntype ToastKind = 'string' | 'template' | 'component';\n\ninterface Entry {\n ref: ToastRef;\n kind: ToastKind;\n enterClass: string;\n leaveClass: string;\n}\n\nconst POSITION_AXIS: Record<ToastPosition, 'right' | 'left' | 'top' | 'bottom'> = {\n 'top-right': 'right',\n 'bottom-right': 'right',\n 'top-left': 'left',\n 'bottom-left': 'left',\n 'top-center': 'top',\n 'bottom-center': 'bottom',\n};\n\nconst POSITION_HOST_CLASSES: Record<ToastPosition, string> = {\n 'top-right': 'items-end',\n 'bottom-right': 'items-end',\n 'top-left': 'items-start',\n 'bottom-left': 'items-start',\n 'top-center': 'items-center',\n 'bottom-center': 'items-center',\n};\n\nconst POSITION_ORDER_REVERSED: Record<ToastPosition, boolean> = {\n 'top-right': false,\n 'top-left': false,\n 'top-center': false,\n 'bottom-right': true,\n 'bottom-left': true,\n 'bottom-center': true,\n};\n\nconst SWIPE_DISMISS_FRACTION = 0.4;\nconst SWIPE_MAX_OPACITY_FADE = 0.6;\n\n/**\n * Internal flex-column host rendered inside each per-position CDK overlay.\n * Stacks visible toasts via `@for`, wires pause-on-interaction, Escape\n * dismissal, swipe gestures, and `LiveAnnouncer` announcements.\n *\n * @docs-private\n */\n@Component({\n selector: 'tw-toast-container',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [NgTemplateOutlet, CdkPortalOutlet, ToastComponent, ToastActionDirective],\n host: {\n role: 'region',\n '[class]': 'hostClasses()',\n '[attr.aria-label]': 'regionLabel()',\n '[attr.data-position]': 'position()',\n },\n template: `\n @for (entry of orderedEntries(); track entry.ref.id) {\n <!-- Toast entry wrapper; the projected <tw-toast> is the focusable affordance.\n This element only forwards pointer/focus events so the container can\n pause auto-dismiss while the user is interacting. -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"pointer-events-auto w-full max-w-sm\"\n [attr.data-toast-id]=\"entry.ref.id\"\n [style.transform]=\"entry.ref.swipeTransform() || null\"\n [style.opacity]=\"entry.ref.swipeOpacity() ?? null\"\n [style.touch-action]=\"'pan-y'\"\n [animate.enter]=\"entry.enterClass\"\n [animate.leave]=\"entry.ref.leaveAnimationOverride() ?? entry.leaveClass\"\n (pointerenter)=\"onPointerEnter(entry.ref)\"\n (pointerleave)=\"onPointerLeave(entry.ref)\"\n (focusin)=\"onFocusIn(entry.ref)\"\n (focusout)=\"onFocusOut(entry.ref, $event)\"\n (keydown.escape)=\"onEscape(entry.ref, $event)\"\n (pointerdown)=\"onSwipeStart(entry.ref, $event, swipeEl)\"\n #swipeEl\n >\n @switch (entry.kind) {\n @case ('string') {\n <tw-toast\n [severity]=\"entry.ref.severity()\"\n [dismissible]=\"entry.ref.dismissible()\"\n [icon]=\"entry.ref.icon()\"\n [ariaLabel]=\"entry.ref.ariaLabel()\"\n [class]=\"panelClassFor(entry.ref)\"\n (dismissed)=\"entry.ref._dismissWith('manual')\"\n (actionClicked)=\"entry.ref.triggerAction()\"\n >\n {{ asString(entry.ref.content()) }}\n @if (entry.ref.action(); as action) {\n <button twToastAction>{{ action.label }}</button>\n }\n </tw-toast>\n }\n @case ('template') {\n <tw-toast\n [severity]=\"entry.ref.severity()\"\n [dismissible]=\"entry.ref.dismissible()\"\n [icon]=\"entry.ref.icon()\"\n [ariaLabel]=\"entry.ref.ariaLabel()\"\n [class]=\"panelClassFor(entry.ref)\"\n (dismissed)=\"entry.ref._dismissWith('manual')\"\n (actionClicked)=\"entry.ref.triggerAction()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"asTemplate(entry.ref.content())\"\n [ngTemplateOutletContext]=\"templateContext(entry.ref)\"\n />\n @if (entry.ref.action(); as action) {\n <button twToastAction>{{ action.label }}</button>\n }\n </tw-toast>\n }\n @case ('component') {\n <ng-template\n [cdkPortalOutlet]=\"entry.ref._portal\"\n (attached)=\"onPortalAttached(entry.ref, $event)\"\n />\n }\n }\n </div>\n }\n `,\n})\nexport class ToastContainerComponent {\n /** Per-position stacking anchor. Mutated from {@link ToastService} via `.instance.position.set(...)`. */\n readonly position = signal<ToastPosition>('bottom-right');\n\n /** Accessible label applied to the `role=\"region\"` host. Mutated from the service on init. */\n readonly regionLabel = signal<string>('Notifications');\n\n /**\n * Toasts currently assigned to this container. The service pushes toasts\n * into this signal; the container filters by state to drive `animate.leave`.\n */\n readonly visibleRefs = signal<readonly ToastRef[]>([]);\n\n private readonly injector = inject(Injector);\n private readonly liveAnnouncer = inject(LiveAnnouncer);\n private readonly host = inject(ElementRef<HTMLElement>);\n\n private readonly swipeSessions = new WeakMap<\n ToastRef,\n { pointerId: number; startX: number; width: number; active: boolean }\n >();\n\n private readonly entries = computed<readonly Entry[]>(() => {\n const pos = this.position();\n const axis = POSITION_AXIS[pos];\n const enter = `toast-enter-${axis}`;\n const leave = `toast-leave-${axis}`;\n const refs = this.visibleRefs().filter((ref) => {\n const s = ref.state();\n return s === 'entering' || s === 'visible' || s === 'paused';\n });\n return refs.map((ref) => ({\n ref,\n kind: resolveKind(ref.content()),\n enterClass: enter,\n leaveClass: leave,\n }));\n });\n\n protected readonly orderedEntries = computed(() => {\n const list = this.entries();\n return POSITION_ORDER_REVERSED[this.position()] ? [...list].reverse() : list;\n });\n\n protected readonly hostClasses = computed(() => {\n const base = 'flex flex-col gap-2 w-full max-w-sm';\n const align = POSITION_HOST_CLASSES[this.position()];\n return `${base} ${align}`;\n });\n\n /** @internal Called by the service right after attaching a new toast. Runs `LiveAnnouncer`. */\n _announceOpen(ref: ToastRef): void {\n const politeness = this.resolvePoliteness(ref);\n if (politeness === 'off') return;\n const msg = this.resolveAnnouncementText(ref);\n if (msg) this.liveAnnouncer.announce(msg, politeness);\n }\n\n /** @internal Called by the service when `ref.update()` fires — re-announces with the new severity / content. */\n _announceUpdate(ref: ToastRef): void {\n this._announceOpen(ref);\n }\n\n /** @internal Captures the component instance after `cdkPortalOutlet` attaches. */\n protected onPortalAttached(ref: ToastRef, attached: CdkPortalOutletAttachedRef): void {\n if (attached && 'instance' in attached) {\n ref.componentInstance = (attached as ComponentRef<unknown>).instance;\n }\n }\n\n /** @internal Injector factory for component-class content. Provides `TW_TOAST_DATA` + `TW_TOAST_REF`. */\n _createContentInjector(ref: ToastRef): Injector {\n return Injector.create({\n parent: this.injector,\n providers: [\n { provide: TW_TOAST_REF, useValue: ref },\n { provide: TW_TOAST_DATA, useValue: ref.data() },\n ],\n });\n }\n\n // ── Template helpers ──\n\n protected asString(content: unknown): string {\n return typeof content === 'string' ? content : '';\n }\n\n protected asTemplate(content: unknown): TemplateRef<ToastTemplateContext> | null {\n return content instanceof TemplateRef ? (content as TemplateRef<ToastTemplateContext>) : null;\n }\n\n protected templateContext(ref: ToastRef): ToastTemplateContext {\n return { $implicit: ref.data() as never, ref };\n }\n\n protected panelClassFor(ref: ToastRef): string {\n const raw = ref.config.panelClass;\n if (!raw) return '';\n return Array.isArray(raw) ? raw.join(' ') : raw;\n }\n\n // ── Interaction handlers ──\n\n protected onPointerEnter(ref: ToastRef): void {\n ref._setHovered(true);\n }\n\n protected onPointerLeave(ref: ToastRef): void {\n ref._setHovered(false);\n }\n\n protected onFocusIn(ref: ToastRef): void {\n ref._setFocused(true);\n }\n\n protected onFocusOut(ref: ToastRef, event: FocusEvent): void {\n const related = event.relatedTarget as Node | null;\n const target = event.currentTarget as Node | null;\n if (related && target && target.contains(related)) return;\n ref._setFocused(false);\n }\n\n protected onEscape(ref: ToastRef, event: Event): void {\n event.stopPropagation();\n event.preventDefault();\n ref._dismissWith('manual');\n }\n\n protected onSwipeStart(ref: ToastRef, event: PointerEvent, el: HTMLElement): void {\n if (!ref.config.swipeToDismiss) return;\n if (event.button !== 0) return;\n const target = event.target as HTMLElement | null;\n if (target?.closest('button, a, input, select, textarea, [role=\"button\"]')) return;\n\n const width = el.getBoundingClientRect().width;\n this.swipeSessions.set(ref, {\n pointerId: event.pointerId,\n startX: event.clientX,\n width,\n active: false,\n });\n el.setPointerCapture(event.pointerId);\n\n const onMove = (e: PointerEvent) => this.onSwipeMove(ref, e, el);\n const onUp = (e: PointerEvent) => this.onSwipeEnd(ref, e, el, onMove, onUp);\n el.addEventListener('pointermove', onMove);\n el.addEventListener('pointerup', onUp);\n el.addEventListener('pointercancel', onUp);\n }\n\n private onSwipeMove(ref: ToastRef, event: PointerEvent, _el: HTMLElement): void {\n const session = this.swipeSessions.get(ref);\n if (!session || event.pointerId !== session.pointerId) return;\n const dx = event.clientX - session.startX;\n if (!session.active && Math.abs(dx) < 6) return;\n session.active = true;\n ref.swipeTransform.set(`translate3d(${dx}px, 0, 0)`);\n const fade = 1 - Math.min(Math.abs(dx) / session.width, 1) * SWIPE_MAX_OPACITY_FADE;\n ref.swipeOpacity.set(fade);\n }\n\n private onSwipeEnd(\n ref: ToastRef,\n event: PointerEvent,\n el: HTMLElement,\n onMove: (e: PointerEvent) => void,\n onUp: (e: PointerEvent) => void,\n ): void {\n const session = this.swipeSessions.get(ref);\n el.removeEventListener('pointermove', onMove);\n el.removeEventListener('pointerup', onUp);\n el.removeEventListener('pointercancel', onUp);\n if (!session || event.pointerId !== session.pointerId) return;\n try {\n el.releasePointerCapture(session.pointerId);\n } catch {\n /* no-op */\n }\n this.swipeSessions.delete(ref);\n\n if (!session.active) return;\n const dx = event.clientX - session.startX;\n const threshold = session.width * SWIPE_DISMISS_FRACTION;\n const allowed = this.swipeDirectionAllowed(dx);\n if (Math.abs(dx) >= threshold && allowed) {\n untracked(() => {\n ref.swipeTransform.set(`translate3d(${Math.sign(dx) * session.width * 1.2}px, 0, 0)`);\n ref.swipeOpacity.set(0);\n ref.leaveAnimationOverride.set('fade-out');\n });\n ref._dismissWith('swipe');\n } else {\n ref.swipeTransform.set(null);\n ref.swipeOpacity.set(null);\n }\n }\n\n private swipeDirectionAllowed(dx: number): boolean {\n const pos = this.position();\n if (pos === 'top-right' || pos === 'bottom-right') return dx > 0;\n if (pos === 'top-left' || pos === 'bottom-left') return dx < 0;\n return true;\n }\n\n private resolvePoliteness(ref: ToastRef): 'polite' | 'assertive' | 'off' {\n if (ref.config.politeness) return ref.config.politeness;\n return ref.severity() === 'error' ? 'assertive' : 'polite';\n }\n\n private resolveAnnouncementText(ref: ToastRef): string {\n const explicit = ref.ariaLabel();\n if (explicit) return explicit;\n const content = ref.content();\n if (typeof content === 'string') return content;\n const host = this.host.nativeElement.querySelector(\n `[data-toast-id=\"${ref.id}\"]`,\n ) as HTMLElement | null;\n if (host) return host.textContent?.trim() ?? '';\n return this.host.nativeElement.textContent?.trim() ?? '';\n }\n}\n\nfunction resolveKind(content: unknown): ToastKind {\n if (typeof content === 'string') return 'string';\n if (content instanceof TemplateRef) return 'template';\n return 'component';\n}\n\n","import { type ComponentRef, type Injector, TemplateRef, type Type } from '@angular/core';\nimport {\n createGlobalPositionStrategy,\n Overlay,\n type OverlayRef,\n} from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { type ToastPosition } from './toast-config';\nimport { ToastContainerComponent } from './toast-container';\nimport type { ToastRef } from './toast-ref';\n\nconst OVERLAY_EDGE_OFFSET = '1rem';\n\ninterface PositionOverlay {\n overlayRef: OverlayRef;\n containerRef: ComponentRef<ToastContainerComponent>;\n}\n\n/**\n * Rendering half of the toast feature: owns the CDK overlays, the per-position\n * {@link ToastContainerComponent} instances, and every `LiveAnnouncer` call.\n *\n * This module is reached only through a dynamic `import()` in `ToastService`,\n * which is what keeps `@angular/cdk/overlay`, the toast components, and\n * `tailwind-variants` out of a consumer's initial bundle. Nothing here may be\n * imported statically from `toast.ts` — a value import (as opposed to a\n * `import type`) would pull the whole graph back into the eager chunk and\n * silently undo the split. See `toast.spec.ts` for the guard test.\n *\n * @docs-private\n */\nexport class ToastRenderer {\n private readonly overlay: Overlay;\n private readonly positionOverlays = new Map<ToastPosition, PositionOverlay>();\n private disposed = false;\n\n constructor(\n private readonly injector: Injector,\n private readonly regionAriaLabel: string,\n ) {\n // Resolved here rather than injected into `ToastService`, so the `Overlay`\n // symbol lives in this lazily-loaded chunk. It is `providedIn: 'root'`, so\n // no eager provider is required.\n this.overlay = injector.get(Overlay);\n }\n\n /**\n * Render a toast into its position container, creating the overlay on first\n * use. Returns `false` if the renderer has already been disposed.\n */\n attach(ref: ToastRef, position: ToastPosition): boolean {\n if (this.disposed) return false;\n const entry = this.getContainerForPosition(position);\n const instance = entry.containerRef.instance;\n\n // Component-class content needs an injector built from the container, so\n // the portal cannot be created until the container exists.\n const content = ref.content();\n if (isComponentConstructor(content)) {\n ref._portal = new ComponentPortal(content, null, instance._createContentInjector(ref));\n }\n\n instance.visibleRefs.update((list) => [...list, ref]);\n ref._overlayPanelElement = entry.overlayRef.overlayElement;\n return true;\n }\n\n /** Announce a freshly attached toast to assistive technology. */\n announceOpen(ref: ToastRef): void {\n this.containerFor(ref)?._announceOpen(ref);\n }\n\n /** Re-announce a toast whose content or severity changed via `update()`. */\n announceUpdate(ref: ToastRef): void {\n this.containerFor(ref)?._announceUpdate(ref);\n }\n\n /** Drop a dismissed toast from its container's render list. */\n detach(ref: ToastRef): void {\n const instance = this.containerFor(ref);\n if (!instance) return;\n instance.visibleRefs.update((list) => list.filter((r) => r !== ref));\n }\n\n /** Tear down every overlay this renderer created. */\n dispose(): void {\n this.disposed = true;\n for (const { overlayRef } of this.positionOverlays.values()) {\n overlayRef.dispose();\n }\n this.positionOverlays.clear();\n }\n\n private containerFor(ref: ToastRef): ToastContainerComponent | undefined {\n return this.positionOverlays.get(ref.config.position ?? 'bottom-right')?.containerRef\n .instance;\n }\n\n private getContainerForPosition(position: ToastPosition): PositionOverlay {\n const existing = this.positionOverlays.get(position);\n if (existing) return existing;\n\n const overlayRef = this.overlay.create({\n positionStrategy: this.buildPositionStrategy(position),\n scrollStrategy: this.overlay.scrollStrategies.noop(),\n hasBackdrop: false,\n panelClass: ['tw-toast-overlay', `tw-toast-overlay-${position}`],\n });\n\n const containerPortal = new ComponentPortal(\n ToastContainerComponent,\n null,\n this.injector,\n );\n const containerRef = overlayRef.attach(containerPortal);\n containerRef.instance.position.set(position);\n containerRef.instance.regionLabel.set(this.regionAriaLabel);\n\n const entry: PositionOverlay = { overlayRef, containerRef };\n this.positionOverlays.set(position, entry);\n return entry;\n }\n\n private buildPositionStrategy(position: ToastPosition) {\n const strategy = createGlobalPositionStrategy(this.injector);\n switch (position) {\n case 'top-right':\n strategy.top(OVERLAY_EDGE_OFFSET).right(OVERLAY_EDGE_OFFSET);\n break;\n case 'top-left':\n strategy.top(OVERLAY_EDGE_OFFSET).left(OVERLAY_EDGE_OFFSET);\n break;\n case 'top-center':\n strategy.top(OVERLAY_EDGE_OFFSET).centerHorizontally();\n break;\n case 'bottom-right':\n strategy.bottom(OVERLAY_EDGE_OFFSET).right(OVERLAY_EDGE_OFFSET);\n break;\n case 'bottom-left':\n strategy.bottom(OVERLAY_EDGE_OFFSET).left(OVERLAY_EDGE_OFFSET);\n break;\n case 'bottom-center':\n strategy.bottom(OVERLAY_EDGE_OFFSET).centerHorizontally();\n break;\n }\n return strategy;\n }\n\n}\n\nfunction isComponentConstructor(value: unknown): value is Type<unknown> {\n return typeof value === 'function' && !(value instanceof TemplateRef);\n}\n"],"names":[],"mappings":"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"}