@cdevhub/ngx-tw 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/README.md +78 -15
  2. package/fesm2022/cdevhub-ngx-tw-accordion.mjs +16 -5
  3. package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -1
  4. package/fesm2022/cdevhub-ngx-tw-avatar.mjs +26 -15
  5. package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -1
  6. package/fesm2022/cdevhub-ngx-tw-badge.mjs +17 -5
  7. package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
  8. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +27 -6
  9. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -1
  10. package/fesm2022/cdevhub-ngx-tw-button.mjs +23 -11
  11. package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
  12. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +5 -5
  13. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -1
  14. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +3 -3
  15. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -1
  16. package/fesm2022/cdevhub-ngx-tw-calendar.mjs +427 -122
  17. package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -1
  18. package/fesm2022/cdevhub-ngx-tw-card.mjs +21 -11
  19. package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
  20. package/fesm2022/cdevhub-ngx-tw-carousel.mjs +215 -96
  21. package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -1
  22. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +108 -64
  23. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
  24. package/fesm2022/cdevhub-ngx-tw-code-block.mjs +18 -6
  25. package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -1
  26. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +55 -30
  27. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
  28. package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs +218 -0
  29. package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs.map +1 -0
  30. package/fesm2022/cdevhub-ngx-tw-combobox.mjs +236 -211
  31. package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
  32. package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs +200 -0
  33. package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs.map +1 -0
  34. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +34 -7
  35. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -1
  36. package/fesm2022/cdevhub-ngx-tw-core.mjs +135 -15
  37. package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -1
  38. package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs +203 -0
  39. package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs.map +1 -0
  40. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +160 -102
  41. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
  42. package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs +209 -0
  43. package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs.map +1 -0
  44. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +182 -107
  45. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
  46. package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs +122 -0
  47. package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs.map +1 -0
  48. package/fesm2022/cdevhub-ngx-tw-dialog.mjs +11 -2
  49. package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
  50. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +1 -1
  51. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
  52. package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs +149 -0
  53. package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs.map +1 -0
  54. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +57 -67
  55. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -1
  56. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +42 -24
  57. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
  58. package/fesm2022/cdevhub-ngx-tw-form-field.mjs +114 -21
  59. package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
  60. package/fesm2022/cdevhub-ngx-tw-icon.mjs +16 -6
  61. package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
  62. package/fesm2022/cdevhub-ngx-tw-input.mjs +52 -61
  63. package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
  64. package/fesm2022/cdevhub-ngx-tw-item.mjs +28 -4
  65. package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
  66. package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs +168 -0
  67. package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs.map +1 -0
  68. package/fesm2022/cdevhub-ngx-tw-menu.mjs +58 -21
  69. package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
  70. package/fesm2022/cdevhub-ngx-tw-number-input.mjs +34 -1
  71. package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -1
  72. package/fesm2022/cdevhub-ngx-tw-paginator.mjs +95 -45
  73. package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
  74. package/fesm2022/cdevhub-ngx-tw-popover.mjs +81 -32
  75. package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
  76. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +1 -1
  77. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
  78. package/fesm2022/cdevhub-ngx-tw-radio.mjs +131 -98
  79. package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
  80. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +207 -42
  81. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
  82. package/fesm2022/cdevhub-ngx-tw-select-testing.mjs +165 -0
  83. package/fesm2022/cdevhub-ngx-tw-select-testing.mjs.map +1 -0
  84. package/fesm2022/cdevhub-ngx-tw-select.mjs +386 -210
  85. package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
  86. package/fesm2022/{cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs → cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs} +3 -3
  87. package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs.map +1 -0
  88. package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs +129 -0
  89. package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs.map +1 -0
  90. package/fesm2022/cdevhub-ngx-tw-sheet.mjs +23 -7
  91. package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
  92. package/fesm2022/cdevhub-ngx-tw-slider.mjs +89 -54
  93. package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
  94. package/fesm2022/cdevhub-ngx-tw-sort.mjs +122 -17
  95. package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
  96. package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -19
  97. package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
  98. package/fesm2022/cdevhub-ngx-tw-stat.mjs +63 -25
  99. package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
  100. package/fesm2022/cdevhub-ngx-tw-stepper.mjs +35 -8
  101. package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
  102. package/fesm2022/cdevhub-ngx-tw-switch.mjs +54 -48
  103. package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
  104. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +12 -15
  105. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
  106. package/fesm2022/cdevhub-ngx-tw-table.mjs +74 -13
  107. package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
  108. package/fesm2022/cdevhub-ngx-tw-tabs.mjs +84 -30
  109. package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
  110. package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs +172 -0
  111. package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs.map +1 -0
  112. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +107 -71
  113. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -1
  114. package/fesm2022/cdevhub-ngx-tw-textarea.mjs +41 -9
  115. package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
  116. package/fesm2022/cdevhub-ngx-tw-theme.mjs +257 -45
  117. package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
  118. package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs +201 -0
  119. package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs.map +1 -0
  120. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +184 -77
  121. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
  122. package/fesm2022/cdevhub-ngx-tw-timeline.mjs +110 -27
  123. package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
  124. package/fesm2022/{cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs → cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs} +107 -19
  125. package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs.map +1 -0
  126. package/fesm2022/cdevhub-ngx-tw-toast.mjs +21 -13
  127. package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
  128. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +102 -15
  129. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
  130. package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs +219 -0
  131. package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs.map +1 -0
  132. package/fesm2022/cdevhub-ngx-tw-transfer.mjs +88 -69
  133. package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -1
  134. package/fesm2022/cdevhub-ngx-tw-tree.mjs +68 -19
  135. package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -1
  136. package/index.json +1 -1
  137. package/package.json +63 -2
  138. package/theme/_base.css +13 -0
  139. package/theme/_dark.css +111 -36
  140. package/theme/_high-contrast-dark.css +367 -0
  141. package/theme/_high-contrast.css +13 -2
  142. package/theme/_light.css +332 -0
  143. package/theme/_semantic.css +60 -26
  144. package/theme/_typography.css +17 -0
  145. package/theme/index.css +86 -7
  146. package/types/cdevhub-ngx-tw-accordion.d.ts +12 -4
  147. package/types/cdevhub-ngx-tw-avatar.d.ts +10 -3
  148. package/types/cdevhub-ngx-tw-button.d.ts +1 -0
  149. package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +2 -2
  150. package/types/cdevhub-ngx-tw-calendar-testing.d.ts +1 -1
  151. package/types/cdevhub-ngx-tw-calendar.d.ts +179 -73
  152. package/types/cdevhub-ngx-tw-card.d.ts +11 -3
  153. package/types/cdevhub-ngx-tw-carousel.d.ts +89 -20
  154. package/types/cdevhub-ngx-tw-checkbox.d.ts +40 -12
  155. package/types/cdevhub-ngx-tw-code-block.d.ts +11 -2
  156. package/types/cdevhub-ngx-tw-collapsible.d.ts +32 -5
  157. package/types/cdevhub-ngx-tw-combobox-testing.d.ts +157 -0
  158. package/types/cdevhub-ngx-tw-combobox.d.ts +94 -53
  159. package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +136 -0
  160. package/types/cdevhub-ngx-tw-command-palette.d.ts +33 -5
  161. package/types/cdevhub-ngx-tw-core.d.ts +152 -21
  162. package/types/cdevhub-ngx-tw-date-picker-testing.d.ts +141 -0
  163. package/types/cdevhub-ngx-tw-date-picker.d.ts +37 -29
  164. package/types/cdevhub-ngx-tw-date-range-picker-testing.d.ts +148 -0
  165. package/types/cdevhub-ngx-tw-date-range-picker.d.ts +36 -29
  166. package/types/cdevhub-ngx-tw-dialog-testing.d.ts +98 -0
  167. package/types/cdevhub-ngx-tw-dialog.d.ts +12 -3
  168. package/types/cdevhub-ngx-tw-file-upload-testing.d.ts +120 -0
  169. package/types/cdevhub-ngx-tw-file-upload.d.ts +8 -10
  170. package/types/cdevhub-ngx-tw-flip-card.d.ts +18 -11
  171. package/types/cdevhub-ngx-tw-form-field.d.ts +19 -2
  172. package/types/cdevhub-ngx-tw-icon.d.ts +3 -3
  173. package/types/cdevhub-ngx-tw-input.d.ts +5 -8
  174. package/types/cdevhub-ngx-tw-item.d.ts +2 -0
  175. package/types/cdevhub-ngx-tw-menu-testing.d.ts +131 -0
  176. package/types/cdevhub-ngx-tw-menu.d.ts +2 -2
  177. package/types/cdevhub-ngx-tw-number-input.d.ts +20 -0
  178. package/types/cdevhub-ngx-tw-paginator.d.ts +58 -24
  179. package/types/cdevhub-ngx-tw-popover.d.ts +41 -10
  180. package/types/cdevhub-ngx-tw-progress-bar.d.ts +1 -1
  181. package/types/cdevhub-ngx-tw-radio.d.ts +68 -25
  182. package/types/cdevhub-ngx-tw-segmented-control.d.ts +79 -16
  183. package/types/cdevhub-ngx-tw-select-testing.d.ts +114 -0
  184. package/types/cdevhub-ngx-tw-select.d.ts +104 -33
  185. package/types/cdevhub-ngx-tw-sheet-testing.d.ts +104 -0
  186. package/types/cdevhub-ngx-tw-sheet.d.ts +19 -3
  187. package/types/cdevhub-ngx-tw-slider.d.ts +79 -25
  188. package/types/cdevhub-ngx-tw-sort.d.ts +45 -4
  189. package/types/cdevhub-ngx-tw-split.d.ts +32 -2
  190. package/types/cdevhub-ngx-tw-stat.d.ts +14 -4
  191. package/types/cdevhub-ngx-tw-stepper.d.ts +16 -2
  192. package/types/cdevhub-ngx-tw-switch.d.ts +35 -13
  193. package/types/cdevhub-ngx-tw-tab-nav.d.ts +7 -6
  194. package/types/cdevhub-ngx-tw-table.d.ts +53 -10
  195. package/types/cdevhub-ngx-tw-tabs.d.ts +41 -10
  196. package/types/cdevhub-ngx-tw-tags-input-testing.d.ts +135 -0
  197. package/types/cdevhub-ngx-tw-tags-input.d.ts +26 -11
  198. package/types/cdevhub-ngx-tw-textarea.d.ts +3 -2
  199. package/types/cdevhub-ngx-tw-theme.d.ts +245 -39
  200. package/types/cdevhub-ngx-tw-time-picker-testing.d.ts +129 -0
  201. package/types/cdevhub-ngx-tw-time-picker.d.ts +76 -19
  202. package/types/cdevhub-ngx-tw-timeline.d.ts +36 -12
  203. package/types/cdevhub-ngx-tw-toast.d.ts +20 -6
  204. package/types/cdevhub-ngx-tw-tooltip.d.ts +28 -6
  205. package/types/cdevhub-ngx-tw-transfer-testing.d.ts +152 -0
  206. package/types/cdevhub-ngx-tw-transfer.d.ts +21 -8
  207. package/types/cdevhub-ngx-tw-tree.d.ts +6 -1
  208. package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs.map +0 -1
  209. package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, inject, Injector, ElementRef, computed, TemplateRef, untracked, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { signal, inject, Injector, ElementRef, DestroyRef, computed, TemplateRef, untracked, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import { Overlay, createGlobalPositionStrategy } from '@angular/cdk/overlay';
4
4
  import { CdkPortalOutlet, ComponentPortal } from '@angular/cdk/portal';
5
5
  import { NgTemplateOutlet } from '@angular/common';
@@ -55,7 +55,27 @@ class ToastContainerComponent {
55
55
  injector = inject(Injector);
56
56
  liveAnnouncer = inject(LiveAnnouncer);
57
57
  host = inject((ElementRef));
58
+ /**
59
+ * Teardown for every swipe currently in flight.
60
+ *
61
+ * `swipeSessions` is a WeakMap and the listeners are bound to the toast
62
+ * element, so neither outlives the DOM — but a swipe interrupted by destroy
63
+ * (the toast auto-dismisses mid-drag) would otherwise leave the pointer
64
+ * capture unreleased. Each entry removes its listeners and releases capture.
65
+ */
66
+ activeSwipeTeardowns = new Set();
67
+ /** Per-toast handle into {@link activeSwipeTeardowns}. */
68
+ swipeTeardowns = new WeakMap();
58
69
  swipeSessions = new WeakMap();
70
+ constructor() {
71
+ // A toast can auto-dismiss (or the whole container can be torn down) while
72
+ // a drag is still in flight, in which case `onSwipeEnd` never runs.
73
+ inject(DestroyRef).onDestroy(() => {
74
+ for (const teardown of [...this.activeSwipeTeardowns])
75
+ teardown();
76
+ this.activeSwipeTeardowns.clear();
77
+ });
78
+ }
59
79
  entries = computed(() => {
60
80
  const pos = this.position();
61
81
  const axis = POSITION_AXIS[pos];
@@ -166,12 +186,35 @@ class ToastContainerComponent {
166
186
  width,
167
187
  active: false,
168
188
  });
169
- el.setPointerCapture(event.pointerId);
189
+ try {
190
+ el.setPointerCapture(event.pointerId);
191
+ }
192
+ catch {
193
+ // setPointerCapture throws when the pointerId is no longer active, and
194
+ // is absent entirely in jsdom. The swipe still tracks via the listeners
195
+ // below — capture is an enhancement, not a prerequisite. Matches the
196
+ // guards already on both `releasePointerCapture` call sites.
197
+ }
170
198
  const onMove = (e) => this.onSwipeMove(ref, e, el);
171
199
  const onUp = (e) => this.onSwipeEnd(ref, e, el, onMove, onUp);
172
200
  el.addEventListener('pointermove', onMove);
173
201
  el.addEventListener('pointerup', onUp);
174
202
  el.addEventListener('pointercancel', onUp);
203
+ const teardown = () => {
204
+ el.removeEventListener('pointermove', onMove);
205
+ el.removeEventListener('pointerup', onUp);
206
+ el.removeEventListener('pointercancel', onUp);
207
+ try {
208
+ el.releasePointerCapture(event.pointerId);
209
+ }
210
+ catch {
211
+ /* capture already released, or the element is detached */
212
+ }
213
+ this.swipeSessions.delete(ref);
214
+ this.activeSwipeTeardowns.delete(teardown);
215
+ };
216
+ this.swipeTeardowns.set(ref, teardown);
217
+ this.activeSwipeTeardowns.add(teardown);
175
218
  }
176
219
  onSwipeMove(ref, event, _el) {
177
220
  const session = this.swipeSessions.get(ref);
@@ -190,6 +233,11 @@ class ToastContainerComponent {
190
233
  el.removeEventListener('pointermove', onMove);
191
234
  el.removeEventListener('pointerup', onUp);
192
235
  el.removeEventListener('pointercancel', onUp);
236
+ const teardown = this.swipeTeardowns.get(ref);
237
+ if (teardown) {
238
+ this.activeSwipeTeardowns.delete(teardown);
239
+ this.swipeTeardowns.delete(ref);
240
+ }
193
241
  if (!session || event.pointerId !== session.pointerId)
194
242
  return;
195
243
  try {
@@ -245,12 +293,32 @@ class ToastContainerComponent {
245
293
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: ToastContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
246
294
  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
295
  @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 -->
296
+ <!--
297
+ Toast entry wrapper. Owns the keyboard and pointer contract for one toast.
298
+
299
+ Focus policy (SC 2.2.1 Timing Adjustable, SC 2.1.1 Keyboard):
300
+
301
+ - tabindex="0" makes the wrapper itself a tab stop. Auto-dismiss pauses on
302
+ focus-within, so without this a toast whose only affordances are opted
303
+ out (dismissible false, no action) has nothing focusable at all and a
304
+ keyboard-only user can never stop its 5s clock. Radix Toast puts the tab
305
+ stop on the toast root for the same reason.
306
+ - No focus trap. A toast is not modal; trapping would strand a user who
307
+ never asked for it.
308
+ - No autofocus. Moving focus on open would yank the caret out of whatever
309
+ the user was doing, which is worse than the delay it saves.
310
+ - No summon hotkey. Deliberately deferred: a document-level key would have
311
+ to pick one of six position containers, and the region landmark already
312
+ gives screen-reader users a direct route in.
313
+ - Escape dismisses the focused toast; the browser returns focus to the
314
+ document flow position on its own once the element is removed.
315
+
316
+ Pointer and focus events are forwarded to the ref so the container can
317
+ pause the auto-dismiss timer while the user is reading or interacting.
318
+ -->
252
319
  <div
253
- class="pointer-events-auto w-full max-w-sm"
320
+ class="pointer-events-auto w-full max-w-sm rounded-lg focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500"
321
+ tabindex="0"
254
322
  [attr.data-toast-id]="entry.ref.id"
255
323
  [style.transform]="entry.ref.swipeTransform() || null"
256
324
  [style.opacity]="entry.ref.swipeOpacity() ?? null"
@@ -271,7 +339,7 @@ class ToastContainerComponent {
271
339
  [severity]="entry.ref.severity()"
272
340
  [dismissible]="entry.ref.dismissible()"
273
341
  [icon]="entry.ref.icon()"
274
- [ariaLabel]="entry.ref.ariaLabel()"
342
+ [aria-label]="entry.ref.ariaLabel()"
275
343
  [class]="panelClassFor(entry.ref)"
276
344
  (dismissed)="entry.ref._dismissWith('manual')"
277
345
  (actionClicked)="entry.ref.triggerAction()"
@@ -287,7 +355,7 @@ class ToastContainerComponent {
287
355
  [severity]="entry.ref.severity()"
288
356
  [dismissible]="entry.ref.dismissible()"
289
357
  [icon]="entry.ref.icon()"
290
- [ariaLabel]="entry.ref.ariaLabel()"
358
+ [aria-label]="entry.ref.ariaLabel()"
291
359
  [class]="panelClassFor(entry.ref)"
292
360
  (dismissed)="entry.ref._dismissWith('manual')"
293
361
  (actionClicked)="entry.ref.triggerAction()"
@@ -310,7 +378,7 @@ class ToastContainerComponent {
310
378
  }
311
379
  </div>
312
380
  }
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 });
381
+ `, 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", "aria-label"], outputs: ["dismissed", "actionClicked"] }, { kind: "directive", type: ToastActionDirective, selector: "[twToastAction]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
314
382
  }
315
383
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: ToastContainerComponent, decorators: [{
316
384
  type: Component,
@@ -327,12 +395,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
327
395
  },
328
396
  template: `
329
397
  @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 -->
398
+ <!--
399
+ Toast entry wrapper. Owns the keyboard and pointer contract for one toast.
400
+
401
+ Focus policy (SC 2.2.1 Timing Adjustable, SC 2.1.1 Keyboard):
402
+
403
+ - tabindex="0" makes the wrapper itself a tab stop. Auto-dismiss pauses on
404
+ focus-within, so without this a toast whose only affordances are opted
405
+ out (dismissible false, no action) has nothing focusable at all and a
406
+ keyboard-only user can never stop its 5s clock. Radix Toast puts the tab
407
+ stop on the toast root for the same reason.
408
+ - No focus trap. A toast is not modal; trapping would strand a user who
409
+ never asked for it.
410
+ - No autofocus. Moving focus on open would yank the caret out of whatever
411
+ the user was doing, which is worse than the delay it saves.
412
+ - No summon hotkey. Deliberately deferred: a document-level key would have
413
+ to pick one of six position containers, and the region landmark already
414
+ gives screen-reader users a direct route in.
415
+ - Escape dismisses the focused toast; the browser returns focus to the
416
+ document flow position on its own once the element is removed.
417
+
418
+ Pointer and focus events are forwarded to the ref so the container can
419
+ pause the auto-dismiss timer while the user is reading or interacting.
420
+ -->
334
421
  <div
335
- class="pointer-events-auto w-full max-w-sm"
422
+ class="pointer-events-auto w-full max-w-sm rounded-lg focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500"
423
+ tabindex="0"
336
424
  [attr.data-toast-id]="entry.ref.id"
337
425
  [style.transform]="entry.ref.swipeTransform() || null"
338
426
  [style.opacity]="entry.ref.swipeOpacity() ?? null"
@@ -353,7 +441,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
353
441
  [severity]="entry.ref.severity()"
354
442
  [dismissible]="entry.ref.dismissible()"
355
443
  [icon]="entry.ref.icon()"
356
- [ariaLabel]="entry.ref.ariaLabel()"
444
+ [aria-label]="entry.ref.ariaLabel()"
357
445
  [class]="panelClassFor(entry.ref)"
358
446
  (dismissed)="entry.ref._dismissWith('manual')"
359
447
  (actionClicked)="entry.ref.triggerAction()"
@@ -369,7 +457,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
369
457
  [severity]="entry.ref.severity()"
370
458
  [dismissible]="entry.ref.dismissible()"
371
459
  [icon]="entry.ref.icon()"
372
- [ariaLabel]="entry.ref.ariaLabel()"
460
+ [aria-label]="entry.ref.ariaLabel()"
373
461
  [class]="panelClassFor(entry.ref)"
374
462
  (dismissed)="entry.ref._dismissWith('manual')"
375
463
  (actionClicked)="entry.ref.triggerAction()"
@@ -394,7 +482,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
394
482
  }
395
483
  `,
396
484
  }]
397
- }] });
485
+ }], ctorParameters: () => [] });
398
486
  function resolveKind(content) {
399
487
  if (typeof content === 'string')
400
488
  return 'string';
@@ -525,4 +613,4 @@ function isComponentConstructor(value) {
525
613
  }
526
614
 
527
615
  export { ToastRenderer };
528
- //# sourceMappingURL=cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs.map
616
+ //# sourceMappingURL=cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.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 DestroyRef,\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 <!--\n Toast entry wrapper. Owns the keyboard and pointer contract for one toast.\n\n Focus policy (SC 2.2.1 Timing Adjustable, SC 2.1.1 Keyboard):\n\n - tabindex=\"0\" makes the wrapper itself a tab stop. Auto-dismiss pauses on\n focus-within, so without this a toast whose only affordances are opted\n out (dismissible false, no action) has nothing focusable at all and a\n keyboard-only user can never stop its 5s clock. Radix Toast puts the tab\n stop on the toast root for the same reason.\n - No focus trap. A toast is not modal; trapping would strand a user who\n never asked for it.\n - No autofocus. Moving focus on open would yank the caret out of whatever\n the user was doing, which is worse than the delay it saves.\n - No summon hotkey. Deliberately deferred: a document-level key would have\n to pick one of six position containers, and the region landmark already\n gives screen-reader users a direct route in.\n - Escape dismisses the focused toast; the browser returns focus to the\n document flow position on its own once the element is removed.\n\n Pointer and focus events are forwarded to the ref so the container can\n pause the auto-dismiss timer while the user is reading or interacting.\n -->\n <div\n class=\"pointer-events-auto w-full max-w-sm rounded-lg focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500\"\n tabindex=\"0\"\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 [aria-label]=\"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 [aria-label]=\"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 /**\n * Teardown for every swipe currently in flight.\n *\n * `swipeSessions` is a WeakMap and the listeners are bound to the toast\n * element, so neither outlives the DOM — but a swipe interrupted by destroy\n * (the toast auto-dismisses mid-drag) would otherwise leave the pointer\n * capture unreleased. Each entry removes its listeners and releases capture.\n */\n private readonly activeSwipeTeardowns = new Set<() => void>();\n\n /** Per-toast handle into {@link activeSwipeTeardowns}. */\n private readonly swipeTeardowns = new WeakMap<ToastRef, () => void>();\n\n private readonly swipeSessions = new WeakMap<\n ToastRef,\n { pointerId: number; startX: number; width: number; active: boolean }\n >();\n\n constructor() {\n // A toast can auto-dismiss (or the whole container can be torn down) while\n // a drag is still in flight, in which case `onSwipeEnd` never runs.\n inject(DestroyRef).onDestroy(() => {\n for (const teardown of [...this.activeSwipeTeardowns]) teardown();\n this.activeSwipeTeardowns.clear();\n });\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 try {\n el.setPointerCapture(event.pointerId);\n } catch {\n // setPointerCapture throws when the pointerId is no longer active, and\n // is absent entirely in jsdom. The swipe still tracks via the listeners\n // below — capture is an enhancement, not a prerequisite. Matches the\n // guards already on both `releasePointerCapture` call sites.\n }\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 const teardown = () => {\n el.removeEventListener('pointermove', onMove);\n el.removeEventListener('pointerup', onUp);\n el.removeEventListener('pointercancel', onUp);\n try {\n el.releasePointerCapture(event.pointerId);\n } catch {\n /* capture already released, or the element is detached */\n }\n this.swipeSessions.delete(ref);\n this.activeSwipeTeardowns.delete(teardown);\n };\n this.swipeTeardowns.set(ref, teardown);\n this.activeSwipeTeardowns.add(teardown);\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 const teardown = this.swipeTeardowns.get(ref);\n if (teardown) {\n this.activeSwipeTeardowns.delete(teardown);\n this.swipeTeardowns.delete(ref);\n }\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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"}
@@ -15,7 +15,16 @@ class ToastConfig {
15
15
  severity = 'info';
16
16
  /** Screen position of the toast stack. Defaults to `'bottom-right'`. */
17
17
  position = 'bottom-right';
18
- /** Auto-dismiss duration in ms. `0` disables auto-dismiss. Defaults to `5000`. */
18
+ /**
19
+ * Auto-dismiss duration in ms. `0` disables auto-dismiss. Defaults to `5000`.
20
+ *
21
+ * The duration alone would fail SC 2.2.1 (Timing Adjustable) — a time limit the
22
+ * user cannot influence. What makes 5s conformant is `pauseOnInteraction`
23
+ * (default `true`): the clock stops while the pointer is over the toast or
24
+ * focus is anywhere inside it, and resumes on leave / blur. Setting
25
+ * `pauseOnInteraction: false` alongside a non-zero duration re-introduces the
26
+ * failure, so pair it with `duration: 0`.
27
+ */
19
28
  duration = 5000;
20
29
  // Default true: toasts must offer an escape hatch — sticky / long-duration toasts
21
30
  // otherwise trap users; opt-out only for ephemeral progress markers paired with `duration`.
@@ -42,9 +51,11 @@ class ToastConfig {
42
51
  * primitives for the string-content path.
43
52
  */
44
53
  icon;
45
- // Default true: matches Material/Radix/Sonner conventions prevents a toast from
46
- // disappearing mid-read; opt-out only for fully ambient progress indicators.
47
- /** When true, pause the auto-dismiss timer while the toast is hovered or holds focus. Defaults to `true`. */
54
+ // Default true: this is what keeps a non-zero `duration` conformant with
55
+ // SC 2.2.1 (Timing Adjustable) it is the user's control over the time limit,
56
+ // not a nicety. Also matches Material/Radix/Sonner. Opt out only together with
57
+ // `duration: 0`, for fully ambient progress indicators.
58
+ /** When true, pause the auto-dismiss timer while the toast is hovered or holds focus anywhere inside it, resuming on leave / blur. Defaults to `true`. */
48
59
  pauseOnInteraction = true;
49
60
  // Default true: matches mobile-platform expectations and gives non-precise pointers
50
61
  // (touch) an easy dismiss gesture; opt-out only if the gesture conflicts with content.
@@ -557,7 +568,7 @@ class ToastService {
557
568
  /** Load (once) and instantiate the rendering layer. Resolves to `null` if the service was destroyed mid-import. */
558
569
  loadRenderer() {
559
570
  if (!this.rendererPromise) {
560
- this.rendererPromise = import('./cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs').then(({ ToastRenderer }) => {
571
+ this.rendererPromise = import('./cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs').then(({ ToastRenderer }) => {
561
572
  if (this.destroyed)
562
573
  return null;
563
574
  this.renderer = new ToastRenderer(this.injector, this.defaultOptions.regionAriaLabel ?? 'Notifications');
@@ -768,9 +779,7 @@ class ToastComponent {
768
779
  /** Severity variant. Drives color palette, default icon, and ARIA role / live politeness. Defaults to `'info'`. */
769
780
  severity = input('info', /* @ts-ignore */
770
781
  ...(ngDevMode ? [{ debugName: "severity" }] : /* istanbul ignore next */ []));
771
- // Default true: mirrors `ToastConfig.dismissible` toasts must offer an escape
772
- // hatch by default; opt-out only for ephemeral progress markers paired with `duration`.
773
- /** Whether to render the close button. Defaults to `true`. */
782
+ /** Whether to render the close button. Defaults to `true` mirroring `ToastConfig.dismissible`, toasts must offer an escape hatch; the special case is an ephemeral progress marker paired with `duration`. */
774
783
  dismissible = input(true, /* @ts-ignore */
775
784
  ...(ngDevMode ? [{ debugName: "dismissible" }] : /* istanbul ignore next */ []));
776
785
  /**
@@ -782,9 +791,8 @@ class ToastComponent {
782
791
  */
783
792
  icon = input(undefined, /* @ts-ignore */
784
793
  ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
785
- /** Explicit aria-label for the toast wrapper. When omitted, text content is used by assistive tech. */
786
- ariaLabel = input(undefined, /* @ts-ignore */
787
- ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
794
+ /** Explicit aria-label for the toast wrapper. Mirrored to `aria-label`. When omitted, text content is used by assistive tech. Defaults to `undefined`. */
795
+ ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
788
796
  /** Fires when the close button is clicked. */
789
797
  dismissed = output();
790
798
  /** Fires when a `[twToastAction]` button is clicked. */
@@ -828,7 +836,7 @@ class ToastComponent {
828
836
  ariaLiveAttr = computed(() => this.severity() === 'error' ? 'assertive' : 'polite', /* @ts-ignore */
829
837
  ...(ngDevMode ? [{ debugName: "ariaLiveAttr" }] : /* istanbul ignore next */ []));
830
838
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: ToastComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
831
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: ToastComponent, isStandalone: true, selector: "tw-toast", inputs: { severity: { classPropertyName: "severity", publicName: "severity", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed", actionClicked: "actionClicked" }, host: { attributes: { "aria-atomic": "true" }, properties: { "class": "rootClasses()", "attr.role": "roleAttr()", "attr.aria-live": "ariaLiveAttr()", "attr.aria-label": "ariaLabel() || null", "attr.data-severity": "severity()" } }, queries: [{ propertyName: "projectedIcon", first: true, predicate: ToastIconDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
839
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: ToastComponent, isStandalone: true, selector: "tw-toast", inputs: { severity: { classPropertyName: "severity", publicName: "severity", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed", actionClicked: "actionClicked" }, host: { attributes: { "aria-atomic": "true" }, properties: { "class": "rootClasses()", "attr.role": "roleAttr()", "attr.aria-live": "ariaLiveAttr()", "attr.aria-label": "ariaLabel() || null", "attr.data-severity": "severity()" } }, queries: [{ propertyName: "projectedIcon", first: true, predicate: ToastIconDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
832
840
  @if (hasProjectedIcon()) {
833
841
  <ng-content select="[twToastIcon]" />
834
842
  } @else if (icon() !== false) {
@@ -949,7 +957,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
949
957
  }
950
958
  `,
951
959
  }]
952
- }], propDecorators: { severity: [{ type: i0.Input, args: [{ isSignal: true, alias: "severity", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }], actionClicked: [{ type: i0.Output, args: ["actionClicked"] }], projectedIcon: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ToastIconDirective), { isSignal: true }] }] } });
960
+ }], propDecorators: { severity: [{ type: i0.Input, args: [{ isSignal: true, alias: "severity", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }], actionClicked: [{ type: i0.Output, args: ["actionClicked"] }], projectedIcon: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ToastIconDirective), { isSignal: true }] }] } });
953
961
 
954
962
  /**
955
963
  * Generated bundle index. Do not edit.