ngwr 7.3.0 → 8.0.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.
Files changed (261) hide show
  1. package/README.md +5 -4
  2. package/alert/styles/_index.scss +44 -17
  3. package/avatar/styles/_index.scss +2 -2
  4. package/badge/styles/_index.scss +11 -7
  5. package/badge/styles/_tag.scss +1 -1
  6. package/bar-chart/styles/_index.scss +1 -2
  7. package/breadcrumbs/styles/_index.scss +4 -2
  8. package/burger/styles/_index.scss +2 -2
  9. package/button/styles/_index.scss +30 -20
  10. package/calendar/styles/_index.scss +11 -9
  11. package/calendar-heatmap/styles/_index.scss +2 -0
  12. package/card/styles/_index.scss +1 -1
  13. package/carousel/styles/_index.scss +1 -1
  14. package/cascader/styles/_index.scss +54 -14
  15. package/checkbox/styles/_index.scss +21 -4
  16. package/collapse/styles/_index.scss +1 -1
  17. package/color-picker/styles/_index.scss +11 -12
  18. package/command-palette/styles/_index.scss +3 -3
  19. package/compare/styles/_index.scss +3 -3
  20. package/context-menu/styles/_index.scss +1 -1
  21. package/date-picker/styles/_index.scss +5 -6
  22. package/density/styles/_index.scss +3 -3
  23. package/dialog/styles/_index.scss +3 -3
  24. package/divider/styles/_index.scss +1 -1
  25. package/drawer/styles/_index.scss +11 -11
  26. package/dropdown/styles/_index.scss +2 -2
  27. package/fesm2022/ngwr-affix.mjs +3 -3
  28. package/fesm2022/ngwr-alert.mjs +22 -10
  29. package/fesm2022/ngwr-alert.mjs.map +1 -1
  30. package/fesm2022/ngwr-anchor.mjs +3 -3
  31. package/fesm2022/ngwr-aurora.mjs +3 -3
  32. package/fesm2022/ngwr-avatar.mjs +3 -3
  33. package/fesm2022/ngwr-back-top.mjs +3 -3
  34. package/fesm2022/ngwr-badge.mjs +6 -6
  35. package/fesm2022/ngwr-bar-chart.mjs +3 -3
  36. package/fesm2022/ngwr-blur-text.mjs +3 -3
  37. package/fesm2022/ngwr-border-glow.mjs +3 -3
  38. package/fesm2022/ngwr-breadcrumbs.mjs +7 -7
  39. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  40. package/fesm2022/ngwr-burger.mjs +3 -3
  41. package/fesm2022/ngwr-button.mjs +6 -6
  42. package/fesm2022/ngwr-calendar-heatmap.mjs +3 -3
  43. package/fesm2022/ngwr-calendar.mjs +4 -4
  44. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  45. package/fesm2022/ngwr-card.mjs +10 -10
  46. package/fesm2022/ngwr-card.mjs.map +1 -1
  47. package/fesm2022/ngwr-carousel.mjs +6 -6
  48. package/fesm2022/ngwr-cascader.mjs +12 -35
  49. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  50. package/fesm2022/ngwr-checkbox.mjs +13 -30
  51. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  52. package/fesm2022/ngwr-circular-text.mjs +3 -3
  53. package/fesm2022/ngwr-click-spark.mjs +25 -6
  54. package/fesm2022/ngwr-click-spark.mjs.map +1 -1
  55. package/fesm2022/ngwr-clipboard.mjs +27 -6
  56. package/fesm2022/ngwr-clipboard.mjs.map +1 -1
  57. package/fesm2022/ngwr-collapse.mjs +9 -9
  58. package/fesm2022/ngwr-color-picker.mjs +7 -7
  59. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  60. package/fesm2022/ngwr-command-palette.mjs +3 -3
  61. package/fesm2022/ngwr-compare.mjs +3 -3
  62. package/fesm2022/ngwr-confetti.mjs +3 -3
  63. package/fesm2022/ngwr-context-menu.mjs +40 -88
  64. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  65. package/fesm2022/ngwr-cookie.mjs +3 -3
  66. package/fesm2022/ngwr-counter.mjs +12 -8
  67. package/fesm2022/ngwr-counter.mjs.map +1 -1
  68. package/fesm2022/ngwr-date-adapter-fns.mjs +3 -3
  69. package/fesm2022/ngwr-date-adapter-luxon.mjs +3 -3
  70. package/fesm2022/ngwr-date-adapter.mjs +3 -3
  71. package/fesm2022/ngwr-date-picker.mjs +25 -11
  72. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  73. package/fesm2022/ngwr-decrypt-text.mjs +3 -3
  74. package/fesm2022/ngwr-density.mjs +14 -14
  75. package/fesm2022/ngwr-density.mjs.map +1 -1
  76. package/fesm2022/ngwr-descriptions.mjs +6 -6
  77. package/fesm2022/ngwr-dialog.mjs +15 -15
  78. package/fesm2022/ngwr-directives.mjs +15 -87
  79. package/fesm2022/ngwr-directives.mjs.map +1 -1
  80. package/fesm2022/ngwr-divider.mjs +3 -3
  81. package/fesm2022/ngwr-donut-chart.mjs +10 -4
  82. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  83. package/fesm2022/ngwr-drag-drop.mjs +6 -6
  84. package/fesm2022/ngwr-drawer.mjs +15 -15
  85. package/fesm2022/ngwr-dropdown.mjs +9 -9
  86. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  87. package/fesm2022/ngwr-empty.mjs +3 -3
  88. package/fesm2022/ngwr-falling-text.mjs +3 -3
  89. package/fesm2022/ngwr-file-upload.mjs +3 -3
  90. package/fesm2022/ngwr-form.mjs +9 -9
  91. package/fesm2022/ngwr-fuzzy-text.mjs +8 -7
  92. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  93. package/fesm2022/ngwr-gauge.mjs +3 -3
  94. package/fesm2022/ngwr-glitch-text.mjs +15 -7
  95. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  96. package/fesm2022/ngwr-gradient-text.mjs +3 -3
  97. package/fesm2022/ngwr-hotkey.mjs +6 -6
  98. package/fesm2022/ngwr-i18n.mjs +9 -9
  99. package/fesm2022/ngwr-icon.mjs +3 -3
  100. package/fesm2022/ngwr-image-cropper.mjs +3 -3
  101. package/fesm2022/ngwr-input-number.mjs +4 -4
  102. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  103. package/fesm2022/ngwr-input-otp.mjs +10 -4
  104. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  105. package/fesm2022/ngwr-input.mjs +25 -16
  106. package/fesm2022/ngwr-input.mjs.map +1 -1
  107. package/fesm2022/ngwr-keyboard.mjs +3 -3
  108. package/fesm2022/ngwr-knob.mjs +3 -3
  109. package/fesm2022/ngwr-layout.mjs +15 -15
  110. package/fesm2022/ngwr-lightbox.mjs +17 -5
  111. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  112. package/fesm2022/ngwr-line-chart.mjs +3 -3
  113. package/fesm2022/ngwr-list.mjs +7 -7
  114. package/fesm2022/ngwr-list.mjs.map +1 -1
  115. package/fesm2022/ngwr-loading-bar.mjs +6 -6
  116. package/fesm2022/ngwr-marquee.mjs +3 -3
  117. package/fesm2022/ngwr-media.mjs +3 -3
  118. package/fesm2022/ngwr-mention.mjs +6 -6
  119. package/fesm2022/ngwr-meta.mjs +6 -6
  120. package/fesm2022/ngwr-meter-group.mjs +3 -3
  121. package/fesm2022/ngwr-overlay.mjs +3 -3
  122. package/fesm2022/ngwr-page-header.mjs +3 -3
  123. package/fesm2022/ngwr-pagination.mjs +5 -15
  124. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  125. package/fesm2022/ngwr-pipes.mjs +21 -21
  126. package/fesm2022/ngwr-platform.mjs +3 -3
  127. package/fesm2022/ngwr-popconfirm.mjs +6 -6
  128. package/fesm2022/ngwr-popover.mjs +6 -6
  129. package/fesm2022/ngwr-progress.mjs +3 -3
  130. package/fesm2022/ngwr-qr.mjs +3 -3
  131. package/fesm2022/ngwr-radio.mjs +28 -26
  132. package/fesm2022/ngwr-radio.mjs.map +1 -1
  133. package/fesm2022/ngwr-rating.mjs +12 -23
  134. package/fesm2022/ngwr-rating.mjs.map +1 -1
  135. package/fesm2022/ngwr-result.mjs +12 -12
  136. package/fesm2022/ngwr-rotating-text.mjs +3 -3
  137. package/fesm2022/ngwr-scroll.mjs +3 -3
  138. package/fesm2022/ngwr-segmented.mjs +10 -22
  139. package/fesm2022/ngwr-segmented.mjs.map +1 -1
  140. package/fesm2022/ngwr-select.mjs +26 -13
  141. package/fesm2022/ngwr-select.mjs.map +1 -1
  142. package/fesm2022/ngwr-shiny-text.mjs +6 -6
  143. package/fesm2022/ngwr-sidebar.mjs +3 -3
  144. package/fesm2022/ngwr-skeleton.mjs +3 -3
  145. package/fesm2022/ngwr-slider.mjs +3 -3
  146. package/fesm2022/ngwr-sparkline.mjs +3 -3
  147. package/fesm2022/ngwr-speed-dial.mjs +3 -3
  148. package/fesm2022/ngwr-spinner.mjs +3 -3
  149. package/fesm2022/ngwr-splash-cursor.mjs +3 -3
  150. package/fesm2022/ngwr-split-text.mjs +3 -3
  151. package/fesm2022/ngwr-splitter.mjs +3 -3
  152. package/fesm2022/ngwr-spotlight-card.mjs +8 -8
  153. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  154. package/fesm2022/ngwr-squircle.mjs +6 -6
  155. package/fesm2022/ngwr-star-border.mjs +3 -3
  156. package/fesm2022/ngwr-statistic.mjs +79 -10
  157. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  158. package/fesm2022/ngwr-stepper.mjs +6 -6
  159. package/fesm2022/ngwr-storage.mjs +3 -3
  160. package/fesm2022/ngwr-switch.mjs +10 -14
  161. package/fesm2022/ngwr-switch.mjs.map +1 -1
  162. package/fesm2022/ngwr-table.mjs +12 -12
  163. package/fesm2022/ngwr-tabs.mjs +8 -6
  164. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  165. package/fesm2022/ngwr-textarea.mjs +84 -25
  166. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  167. package/fesm2022/ngwr-theme.mjs +3 -3
  168. package/fesm2022/ngwr-tilt-card.mjs +6 -6
  169. package/fesm2022/ngwr-timeline.mjs +6 -6
  170. package/fesm2022/ngwr-toast.mjs +46 -24
  171. package/fesm2022/ngwr-toast.mjs.map +1 -1
  172. package/fesm2022/ngwr-toolbar.mjs +3 -3
  173. package/fesm2022/ngwr-tree.mjs +3 -3
  174. package/fesm2022/ngwr-typewriter.mjs +3 -3
  175. package/fesm2022/ngwr-typography.mjs +3 -3
  176. package/fesm2022/ngwr-validators.mjs +41 -3
  177. package/fesm2022/ngwr-validators.mjs.map +1 -1
  178. package/fesm2022/ngwr-version.mjs +1 -1
  179. package/fesm2022/ngwr-version.mjs.map +1 -1
  180. package/fesm2022/ngwr-virtual-scroll.mjs +3 -3
  181. package/fesm2022/ngwr-waves.mjs +3 -3
  182. package/fesm2022/ngwr-window.mjs +12 -12
  183. package/file-upload/styles/_index.scss +3 -3
  184. package/form/styles/_index.scss +5 -5
  185. package/glitch-text/styles/_index.scss +3 -6
  186. package/image-cropper/styles/_index.scss +3 -3
  187. package/input/styles/_index.scss +26 -7
  188. package/input-otp/styles/_index.scss +23 -5
  189. package/keyboard/styles/_index.scss +6 -4
  190. package/knob/styles/_index.scss +1 -1
  191. package/lightbox/styles/_index.scss +29 -10
  192. package/list/styles/_index.scss +3 -3
  193. package/llms-full.txt +14 -19
  194. package/mention/styles/_index.scss +2 -2
  195. package/overlay/styles/_index.scss +1 -1
  196. package/package.json +1 -6
  197. package/pagination/styles/_index.scss +3 -26
  198. package/popconfirm/styles/_index.scss +1 -1
  199. package/popover/styles/_index.scss +2 -2
  200. package/radio/styles/_index.scss +20 -5
  201. package/rating/styles/_index.scss +12 -1
  202. package/schematics/migrations/v8/index.js +122 -0
  203. package/schematics/migrations.json +5 -0
  204. package/schematics/ng-add/index.js +3 -3
  205. package/schematics/ng-add/schema.json +6 -6
  206. package/schematics/provider/schema.json +1 -1
  207. package/schematics/use/symbol-map.json +11 -2
  208. package/segmented/styles/_index.scss +31 -8
  209. package/select/styles/_index.scss +73 -25
  210. package/sidebar/styles/_index.scss +3 -3
  211. package/slider/styles/_index.scss +2 -3
  212. package/speed-dial/styles/_index.scss +1 -0
  213. package/splitter/styles/_index.scss +4 -4
  214. package/spotlight-card/styles/_index.scss +8 -4
  215. package/stepper/styles/_index.scss +4 -4
  216. package/styles/_animations.scss +0 -23
  217. package/styles.scss +0 -1
  218. package/switch/styles/_index.scss +25 -6
  219. package/table/styles/_index.scss +9 -9
  220. package/tabs/styles/_index.scss +22 -3
  221. package/textarea/styles/_index.scss +59 -4
  222. package/theme/styles/_colors.scss +57 -0
  223. package/theme/styles/_dark.scss +22 -8
  224. package/theme/styles/_focus.scss +5 -0
  225. package/theme/styles/_variables.scss +24 -0
  226. package/timeline/styles/_index.scss +11 -2
  227. package/toast/styles/_index.scss +13 -5
  228. package/toolbar/styles/_index.scss +1 -1
  229. package/tree/styles/_index.scss +18 -17
  230. package/types/ngwr-alert.d.ts +16 -6
  231. package/types/ngwr-cascader.d.ts +5 -2
  232. package/types/ngwr-checkbox.d.ts +5 -2
  233. package/types/ngwr-click-spark.d.ts +13 -1
  234. package/types/ngwr-clipboard.d.ts +12 -1
  235. package/types/ngwr-context-menu.d.ts +20 -25
  236. package/types/ngwr-date-picker.d.ts +3 -0
  237. package/types/ngwr-density.d.ts +7 -7
  238. package/types/ngwr-directives.d.ts +17 -49
  239. package/types/ngwr-fuzzy-text.d.ts +1 -1
  240. package/types/ngwr-glitch-text.d.ts +9 -3
  241. package/types/ngwr-input-otp.d.ts +6 -2
  242. package/types/ngwr-input.d.ts +27 -13
  243. package/types/ngwr-lightbox.d.ts +9 -1
  244. package/types/ngwr-pagination.d.ts +3 -9
  245. package/types/ngwr-radio.d.ts +14 -3
  246. package/types/ngwr-rating.d.ts +5 -1
  247. package/types/ngwr-segmented.d.ts +5 -2
  248. package/types/ngwr-select.d.ts +6 -2
  249. package/types/ngwr-spotlight-card.d.ts +1 -1
  250. package/types/ngwr-statistic.d.ts +35 -1
  251. package/types/ngwr-switch.d.ts +5 -1
  252. package/types/ngwr-textarea.d.ts +25 -3
  253. package/types/ngwr-toast.d.ts +7 -1
  254. package/types/ngwr-validators.d.ts +3 -1
  255. package/types/ngwr-version.d.ts +1 -1
  256. package/window/styles/_index.scss +8 -8
  257. package/fesm2022/ngwr-scramble-text.mjs +0 -165
  258. package/fesm2022/ngwr-scramble-text.mjs.map +0 -1
  259. package/scramble-text/scramble-text.scss +0 -1
  260. package/scramble-text/styles/_index.scss +0 -8
  261. package/types/ngwr-scramble-text.d.ts +0 -49
@@ -1,7 +1,7 @@
1
1
  import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion';
2
2
  import { isPlatformBrowser } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { input, signal, computed, viewChild, inject, PLATFORM_ID, effect, forwardRef, ViewEncapsulation, Component } from '@angular/core';
4
+ import { input, signal, computed, viewChild, inject, PLATFORM_ID, ElementRef, effect, forwardRef, ViewEncapsulation, Component } from '@angular/core';
5
5
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
6
6
  import { noop } from 'ngwr/utils';
7
7
 
@@ -11,28 +11,20 @@ import { noop } from 'ngwr/utils';
11
11
  * Use of this source code is governed by an MIT-style license that can be
12
12
  * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
13
13
  */
14
- /**
15
- * Multi-line text input.
16
- *
17
- * Implements `ControlValueAccessor`. Optional `autosize` grows the
18
- * textarea with its content, capped at `maxRows` if provided.
19
- *
20
- * @example
21
- * ```html
22
- * <wr-textarea placeholder="Notes" [(ngModel)]="text" />
23
- * <wr-textarea autosize [maxRows]="6" [(ngModel)]="text" />
24
- * ```
25
- *
26
- * @see https://ngwr.dev/components/textarea
27
- */
28
14
  class WrTextarea {
29
15
  /** Native placeholder text. @default '' */
30
16
  placeholder = input('', /* @ts-ignore */
31
17
  ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
18
+ /** Control size — shares the `--wr-control-*` contract. @default 'md' */
19
+ size = input('md', /* @ts-ignore */
20
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
32
21
  /** Visible row count. @default 3 */
33
22
  rows = input(3, { ...(ngDevMode ? { debugName: "rows" } : /* istanbul ignore next */ {}), transform: (v) => coerceNumberProperty(v, 3) });
34
- /** Allow user resize via the native handle. @default true */
23
+ /** Allow user resize via the corner grip. @default true */
35
24
  resizable = input(true, { ...(ngDevMode ? { debugName: "resizable" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
25
+ /** Resize direction of the corner grip (the grip icon adapts). @default 'vertical' */
26
+ resize = input('vertical', /* @ts-ignore */
27
+ ...(ngDevMode ? [{ debugName: "resize" }] : /* istanbul ignore next */ []));
36
28
  /** Read-only state. @default false */
37
29
  readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
38
30
  /** Grow the textarea to fit its content. @default false */
@@ -55,10 +47,19 @@ class WrTextarea {
55
47
  effectiveDisabled = computed(() => this.disabled() || this.disabledFromCva(), /* @ts-ignore */
56
48
  ...(ngDevMode ? [{ debugName: "effectiveDisabled" }] : /* istanbul ignore next */ []));
57
49
  native = viewChild.required('native');
50
+ /** Resize direction, gated by `resizable` (false → 'none'). */
51
+ effectiveResize = computed(() => (this.resizable() ? this.resize() : 'none'), /* @ts-ignore */
52
+ ...(ngDevMode ? [{ debugName: "effectiveResize" }] : /* istanbul ignore next */ []));
58
53
  classes = computed(() => {
59
54
  const parts = ['wr-textarea'];
60
- if (!this.resizable() || this.autosize())
55
+ const size = this.size();
56
+ if (size !== 'md')
57
+ parts.push(`wr-textarea--${size}`);
58
+ if (this.autosize())
61
59
  parts.push('wr-textarea--no-resize');
60
+ const resize = this.effectiveResize();
61
+ if (resize === 'horizontal' || resize === 'both')
62
+ parts.push('wr-textarea--resize-x');
62
63
  if (this.focused())
63
64
  parts.push('wr-textarea--focused');
64
65
  if (this.effectiveDisabled())
@@ -66,10 +67,22 @@ class WrTextarea {
66
67
  return parts.join(' ');
67
68
  }, /* @ts-ignore */
68
69
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
70
+ /** Show the corner grip (hidden when direction is 'none' / autosize / disabled). */
71
+ showHandle = computed(() => this.effectiveResize() !== 'none' && !this.autosize() && !this.effectiveDisabled(), /* @ts-ignore */
72
+ ...(ngDevMode ? [{ debugName: "showHandle" }] : /* istanbul ignore next */ []));
69
73
  platformId = inject(PLATFORM_ID);
70
74
  isBrowser = isPlatformBrowser(this.platformId);
75
+ hostEl = inject(ElementRef);
71
76
  onChange = noop;
72
77
  onTouched = noop;
78
+ // Custom resize-grip drag state (replaces the native corner handle).
79
+ resizing = false;
80
+ resizeStartY = 0;
81
+ resizeStartX = 0;
82
+ resizeStartHeight = 0;
83
+ resizeStartWidth = 0;
84
+ resizeMinHeight = 36;
85
+ resizeMaxWidth = Number.POSITIVE_INFINITY;
73
86
  constructor() {
74
87
  // Autosize: re-fit whenever value or autosize toggles.
75
88
  effect(() => {
@@ -77,7 +90,7 @@ class WrTextarea {
77
90
  return;
78
91
  // Read `value` to register dependency
79
92
  this.value();
80
- requestAnimationFrame(() => this.resize());
93
+ requestAnimationFrame(() => this.autofit());
81
94
  });
82
95
  }
83
96
  // ControlValueAccessor
@@ -103,7 +116,53 @@ class WrTextarea {
103
116
  this.focused.set(false);
104
117
  this.onTouched();
105
118
  }
106
- resize() {
119
+ // Custom resize — drag the corner grip; direction comes from `effectiveResize`.
120
+ // Pointer capture keeps move/up on the grip even when the cursor leaves it.
121
+ startResize(event) {
122
+ const el = this.native()?.nativeElement;
123
+ if (!el)
124
+ return;
125
+ const host = this.hostEl.nativeElement;
126
+ this.resizing = true;
127
+ this.resizeStartY = event.clientY;
128
+ this.resizeStartX = event.clientX;
129
+ this.resizeStartHeight = el.offsetHeight;
130
+ this.resizeStartWidth = host.offsetWidth;
131
+ // Height floor = fits the current content, so shrinking never opens an
132
+ // overflow scrollbar. Measured once, synchronously (no paint between).
133
+ const borderY = el.offsetHeight - el.clientHeight;
134
+ const prevHeight = el.style.height;
135
+ el.style.height = 'auto';
136
+ this.resizeMinHeight = el.scrollHeight + borderY;
137
+ el.style.height = prevHeight;
138
+ // Width ceiling = parent inner width, so horizontal drag can't overflow.
139
+ this.resizeMaxWidth = host.parentElement?.clientWidth ?? Number.POSITIVE_INFINITY;
140
+ event.target.setPointerCapture(event.pointerId);
141
+ event.preventDefault();
142
+ }
143
+ onResize(event) {
144
+ if (!this.resizing)
145
+ return;
146
+ const el = this.native()?.nativeElement;
147
+ if (!el)
148
+ return;
149
+ const dir = this.effectiveResize();
150
+ if (dir === 'vertical' || dir === 'both') {
151
+ const h = Math.max(this.resizeMinHeight, this.resizeStartHeight + (event.clientY - this.resizeStartY));
152
+ el.style.height = `${h}px`;
153
+ }
154
+ if (dir === 'horizontal' || dir === 'both') {
155
+ const w = Math.min(this.resizeMaxWidth, Math.max(64, this.resizeStartWidth + (event.clientX - this.resizeStartX)));
156
+ this.hostEl.nativeElement.style.width = `${w}px`;
157
+ }
158
+ }
159
+ endResize(event) {
160
+ if (!this.resizing)
161
+ return;
162
+ this.resizing = false;
163
+ event.target.releasePointerCapture(event.pointerId);
164
+ }
165
+ autofit() {
107
166
  const el = this.native()?.nativeElement;
108
167
  if (!el)
109
168
  return;
@@ -122,17 +181,17 @@ class WrTextarea {
122
181
  el.style.overflowY = 'hidden';
123
182
  }
124
183
  }
125
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
126
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.2", type: WrTextarea, isStandalone: true, selector: "wr-textarea", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, autosize: { classPropertyName: "autosize", publicName: "autosize", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, providers: [
184
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
185
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: WrTextarea, isStandalone: true, selector: "wr-textarea", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, resize: { classPropertyName: "resize", publicName: "resize", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, autosize: { classPropertyName: "autosize", publicName: "autosize", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, providers: [
127
186
  {
128
187
  provide: NG_VALUE_ACCESSOR,
129
188
  // eslint-disable-next-line @angular-eslint/no-forward-ref
130
189
  useExisting: forwardRef(() => WrTextarea),
131
190
  multi: true,
132
191
  },
133
- ], viewQueries: [{ propertyName: "native", first: true, predicate: ["native"], descendants: true, isSignal: true }], ngImport: i0, template: "<textarea\n #native\n class=\"wr-textarea__native\"\n [placeholder]=\"placeholder()\"\n [rows]=\"rows()\"\n [readonly]=\"readonly()\"\n [disabled]=\"effectiveDisabled()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\"\n></textarea>\n", encapsulation: i0.ViewEncapsulation.None });
192
+ ], viewQueries: [{ propertyName: "native", first: true, predicate: ["native"], descendants: true, isSignal: true }], ngImport: i0, template: "<textarea\n #native\n class=\"wr-textarea__native\"\n [placeholder]=\"placeholder()\"\n [rows]=\"rows()\"\n [readonly]=\"readonly()\"\n [disabled]=\"effectiveDisabled()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\"\n></textarea>\n\n@if (showHandle()) {\n <!-- Custom corner grip \u2014 the lucide icon + cursor follow the `resize`\n direction. Icons inlined so no icon registration is required. -->\n <span\n [class]=\"`wr-textarea__resize wr-textarea__resize--${effectiveResize()}`\"\n aria-hidden=\"true\"\n (pointerdown)=\"startResize($event)\"\n (pointermove)=\"onResize($event)\"\n (pointerup)=\"endResize($event)\"\n (pointercancel)=\"endResize($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n @switch (effectiveResize()) {\n @case ('vertical') {\n <path d=\"M12 2v20\" />\n <path d=\"m8 18 4 4 4-4\" />\n <path d=\"m8 6 4-4 4 4\" />\n }\n @case ('horizontal') {\n <path d=\"M2 12h20\" />\n <path d=\"m18 8 4 4-4 4\" />\n <path d=\"m6 8-4 4 4 4\" />\n }\n @default {\n <path d=\"M19 13v6h-6\" />\n <path d=\"M5 11V5h6\" />\n <path d=\"m5 5 14 14\" />\n }\n }\n </svg>\n </span>\n}\n", encapsulation: i0.ViewEncapsulation.None });
134
193
  }
135
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTextarea, decorators: [{
194
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTextarea, decorators: [{
136
195
  type: Component,
137
196
  args: [{ selector: 'wr-textarea', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, providers: [
138
197
  {
@@ -141,8 +200,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
141
200
  useExisting: forwardRef(() => WrTextarea),
142
201
  multi: true,
143
202
  },
144
- ], template: "<textarea\n #native\n class=\"wr-textarea__native\"\n [placeholder]=\"placeholder()\"\n [rows]=\"rows()\"\n [readonly]=\"readonly()\"\n [disabled]=\"effectiveDisabled()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\"\n></textarea>\n" }]
145
- }], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], resizable: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizable", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], autosize: [{ type: i0.Input, args: [{ isSignal: true, alias: "autosize", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], native: [{ type: i0.ViewChild, args: ['native', { isSignal: true }] }] } });
203
+ ], template: "<textarea\n #native\n class=\"wr-textarea__native\"\n [placeholder]=\"placeholder()\"\n [rows]=\"rows()\"\n [readonly]=\"readonly()\"\n [disabled]=\"effectiveDisabled()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\"\n></textarea>\n\n@if (showHandle()) {\n <!-- Custom corner grip \u2014 the lucide icon + cursor follow the `resize`\n direction. Icons inlined so no icon registration is required. -->\n <span\n [class]=\"`wr-textarea__resize wr-textarea__resize--${effectiveResize()}`\"\n aria-hidden=\"true\"\n (pointerdown)=\"startResize($event)\"\n (pointermove)=\"onResize($event)\"\n (pointerup)=\"endResize($event)\"\n (pointercancel)=\"endResize($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n @switch (effectiveResize()) {\n @case ('vertical') {\n <path d=\"M12 2v20\" />\n <path d=\"m8 18 4 4 4-4\" />\n <path d=\"m8 6 4-4 4 4\" />\n }\n @case ('horizontal') {\n <path d=\"M2 12h20\" />\n <path d=\"m18 8 4 4-4 4\" />\n <path d=\"m6 8-4 4 4 4\" />\n }\n @default {\n <path d=\"M19 13v6h-6\" />\n <path d=\"M5 11V5h6\" />\n <path d=\"m5 5 14 14\" />\n }\n }\n </svg>\n </span>\n}\n" }]
204
+ }], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], resizable: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizable", required: false }] }], resize: [{ type: i0.Input, args: [{ isSignal: true, alias: "resize", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], autosize: [{ type: i0.Input, args: [{ isSignal: true, alias: "autosize", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], native: [{ type: i0.ViewChild, args: ['native', { isSignal: true }] }] } });
146
205
 
147
206
  /**
148
207
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-textarea.mjs","sources":["../../../projects/lib/textarea/textarea.ts","../../../projects/lib/textarea/textarea.html","../../../projects/lib/textarea/ngwr-textarea.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport type { ElementRef } from '@angular/core';\nimport {\n Component,\n PLATFORM_ID,\n ViewEncapsulation,\n computed,\n effect,\n forwardRef,\n inject,\n input,\n signal,\n viewChild,\n} from '@angular/core';\nimport { type ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\nimport { noop } from 'ngwr/utils';\n\n/**\n * Multi-line text input.\n *\n * Implements `ControlValueAccessor`. Optional `autosize` grows the\n * textarea with its content, capped at `maxRows` if provided.\n *\n * @example\n * ```html\n * <wr-textarea placeholder=\"Notes\" [(ngModel)]=\"text\" />\n * <wr-textarea autosize [maxRows]=\"6\" [(ngModel)]=\"text\" />\n * ```\n *\n * @see https://ngwr.dev/components/textarea\n */\n@Component({\n selector: 'wr-textarea',\n templateUrl: './textarea.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n // eslint-disable-next-line @angular-eslint/no-forward-ref\n useExisting: forwardRef(() => WrTextarea),\n multi: true,\n },\n ],\n})\nexport class WrTextarea implements ControlValueAccessor {\n /** Native placeholder text. @default '' */\n readonly placeholder = input<string>('');\n\n /** Visible row count. @default 3 */\n readonly rows = input(3, { transform: (v: unknown): number => coerceNumberProperty(v, 3) });\n\n /** Allow user resize via the native handle. @default true */\n readonly resizable = input(true, { transform: coerceBooleanProperty });\n\n /** Read-only state. @default false */\n readonly readonly = input(false, { transform: coerceBooleanProperty });\n\n /** Grow the textarea to fit its content. @default false */\n readonly autosize = input(false, { transform: coerceBooleanProperty });\n\n /** Cap autosize at this many rows. Ignored when `autosize` is false. */\n readonly maxRows = input<number | null>(null);\n\n /**\n * Disable the textarea. Also set by Angular forms via `setDisabledState`.\n *\n * @default false\n */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n protected readonly value = signal<string>('');\n protected readonly disabledFromCva = signal(false);\n protected readonly focused = signal(false);\n\n protected readonly effectiveDisabled = computed(() => this.disabled() || this.disabledFromCva());\n\n protected readonly native = viewChild.required<ElementRef<HTMLTextAreaElement>>('native');\n\n protected readonly classes = computed(() => {\n const parts = ['wr-textarea'];\n if (!this.resizable() || this.autosize()) parts.push('wr-textarea--no-resize');\n if (this.focused()) parts.push('wr-textarea--focused');\n if (this.effectiveDisabled()) parts.push('wr-textarea--disabled');\n return parts.join(' ');\n });\n\n private readonly platformId = inject(PLATFORM_ID);\n private readonly isBrowser = isPlatformBrowser(this.platformId);\n\n private onChange: (value: string) => void = noop;\n private onTouched: () => void = noop;\n\n constructor() {\n // Autosize: re-fit whenever value or autosize toggles.\n effect(() => {\n if (!this.autosize() || !this.isBrowser) return;\n // Read `value` to register dependency\n this.value();\n requestAnimationFrame(() => this.resize());\n });\n }\n\n // ControlValueAccessor\n\n writeValue(value: string | null): void {\n this.value.set(value ?? '');\n }\n\n registerOnChange(fn: (value: string) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.disabledFromCva.set(isDisabled);\n }\n\n // Template handlers\n\n protected onInput(event: Event): void {\n const next = (event.target as HTMLTextAreaElement).value;\n this.value.set(next);\n this.onChange(next);\n }\n\n protected onBlur(): void {\n this.focused.set(false);\n this.onTouched();\n }\n\n private resize(): void {\n const el = this.native()?.nativeElement;\n if (!el) return;\n\n el.style.height = 'auto';\n\n const maxRows = this.maxRows();\n if (maxRows && maxRows > 0) {\n const cs = getComputedStyle(el);\n const lineHeight = parseFloat(cs.lineHeight) || parseFloat(cs.fontSize) * 1.2;\n const cap = lineHeight * maxRows;\n const next = Math.min(el.scrollHeight, cap);\n el.style.height = `${next}px`;\n el.style.overflowY = el.scrollHeight > cap ? 'auto' : 'hidden';\n } else {\n el.style.height = `${el.scrollHeight}px`;\n el.style.overflowY = 'hidden';\n }\n }\n}\n","<textarea\n #native\n class=\"wr-textarea__native\"\n [placeholder]=\"placeholder()\"\n [rows]=\"rows()\"\n [readonly]=\"readonly()\"\n [disabled]=\"effectiveDisabled()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\"\n></textarea>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngwr-textarea.mjs","sources":["../../../projects/lib/textarea/textarea.ts","../../../projects/lib/textarea/textarea.html","../../../projects/lib/textarea/ngwr-textarea.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n ElementRef,\n PLATFORM_ID,\n ViewEncapsulation,\n computed,\n effect,\n forwardRef,\n inject,\n input,\n signal,\n viewChild,\n} from '@angular/core';\nimport { type ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\nimport { noop } from 'ngwr/utils';\n\n/**\n * Multi-line text input.\n *\n * Implements `ControlValueAccessor`. Optional `autosize` grows the\n * textarea with its content, capped at `maxRows` if provided.\n *\n * @example\n * ```html\n * <wr-textarea placeholder=\"Notes\" [(ngModel)]=\"text\" />\n * <wr-textarea autosize [maxRows]=\"6\" [(ngModel)]=\"text\" />\n * ```\n *\n * @see https://ngwr.dev/components/textarea\n */\nexport type WrTextareaSize = 'sm' | 'md' | 'lg';\n\nexport type WrTextareaResize = 'none' | 'vertical' | 'horizontal' | 'both';\n\n@Component({\n selector: 'wr-textarea',\n templateUrl: './textarea.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n // eslint-disable-next-line @angular-eslint/no-forward-ref\n useExisting: forwardRef(() => WrTextarea),\n multi: true,\n },\n ],\n})\nexport class WrTextarea implements ControlValueAccessor {\n /** Native placeholder text. @default '' */\n readonly placeholder = input<string>('');\n\n /** Control size — shares the `--wr-control-*` contract. @default 'md' */\n readonly size = input<WrTextareaSize>('md');\n\n /** Visible row count. @default 3 */\n readonly rows = input(3, { transform: (v: unknown): number => coerceNumberProperty(v, 3) });\n\n /** Allow user resize via the corner grip. @default true */\n readonly resizable = input(true, { transform: coerceBooleanProperty });\n\n /** Resize direction of the corner grip (the grip icon adapts). @default 'vertical' */\n readonly resize = input<WrTextareaResize>('vertical');\n\n /** Read-only state. @default false */\n readonly readonly = input(false, { transform: coerceBooleanProperty });\n\n /** Grow the textarea to fit its content. @default false */\n readonly autosize = input(false, { transform: coerceBooleanProperty });\n\n /** Cap autosize at this many rows. Ignored when `autosize` is false. */\n readonly maxRows = input<number | null>(null);\n\n /**\n * Disable the textarea. Also set by Angular forms via `setDisabledState`.\n *\n * @default false\n */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n protected readonly value = signal<string>('');\n protected readonly disabledFromCva = signal(false);\n protected readonly focused = signal(false);\n\n protected readonly effectiveDisabled = computed(() => this.disabled() || this.disabledFromCva());\n\n protected readonly native = viewChild.required<ElementRef<HTMLTextAreaElement>>('native');\n\n /** Resize direction, gated by `resizable` (false → 'none'). */\n protected readonly effectiveResize = computed<WrTextareaResize>(() => (this.resizable() ? this.resize() : 'none'));\n\n protected readonly classes = computed(() => {\n const parts = ['wr-textarea'];\n const size = this.size();\n if (size !== 'md') parts.push(`wr-textarea--${size}`);\n if (this.autosize()) parts.push('wr-textarea--no-resize');\n const resize = this.effectiveResize();\n if (resize === 'horizontal' || resize === 'both') parts.push('wr-textarea--resize-x');\n if (this.focused()) parts.push('wr-textarea--focused');\n if (this.effectiveDisabled()) parts.push('wr-textarea--disabled');\n return parts.join(' ');\n });\n\n /** Show the corner grip (hidden when direction is 'none' / autosize / disabled). */\n protected readonly showHandle = computed(\n () => this.effectiveResize() !== 'none' && !this.autosize() && !this.effectiveDisabled()\n );\n\n private readonly platformId = inject(PLATFORM_ID);\n private readonly isBrowser = isPlatformBrowser(this.platformId);\n private readonly hostEl = inject<ElementRef<HTMLElement>>(ElementRef);\n\n private onChange: (value: string) => void = noop;\n private onTouched: () => void = noop;\n\n // Custom resize-grip drag state (replaces the native corner handle).\n private resizing = false;\n private resizeStartY = 0;\n private resizeStartX = 0;\n private resizeStartHeight = 0;\n private resizeStartWidth = 0;\n private resizeMinHeight = 36;\n private resizeMaxWidth = Number.POSITIVE_INFINITY;\n\n constructor() {\n // Autosize: re-fit whenever value or autosize toggles.\n effect(() => {\n if (!this.autosize() || !this.isBrowser) return;\n // Read `value` to register dependency\n this.value();\n requestAnimationFrame(() => this.autofit());\n });\n }\n\n // ControlValueAccessor\n\n writeValue(value: string | null): void {\n this.value.set(value ?? '');\n }\n\n registerOnChange(fn: (value: string) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.disabledFromCva.set(isDisabled);\n }\n\n // Template handlers\n\n protected onInput(event: Event): void {\n const next = (event.target as HTMLTextAreaElement).value;\n this.value.set(next);\n this.onChange(next);\n }\n\n protected onBlur(): void {\n this.focused.set(false);\n this.onTouched();\n }\n\n // Custom resize — drag the corner grip; direction comes from `effectiveResize`.\n // Pointer capture keeps move/up on the grip even when the cursor leaves it.\n protected startResize(event: PointerEvent): void {\n const el = this.native()?.nativeElement;\n if (!el) return;\n const host = this.hostEl.nativeElement;\n this.resizing = true;\n this.resizeStartY = event.clientY;\n this.resizeStartX = event.clientX;\n this.resizeStartHeight = el.offsetHeight;\n this.resizeStartWidth = host.offsetWidth;\n // Height floor = fits the current content, so shrinking never opens an\n // overflow scrollbar. Measured once, synchronously (no paint between).\n const borderY = el.offsetHeight - el.clientHeight;\n const prevHeight = el.style.height;\n el.style.height = 'auto';\n this.resizeMinHeight = el.scrollHeight + borderY;\n el.style.height = prevHeight;\n // Width ceiling = parent inner width, so horizontal drag can't overflow.\n this.resizeMaxWidth = host.parentElement?.clientWidth ?? Number.POSITIVE_INFINITY;\n (event.target as HTMLElement).setPointerCapture(event.pointerId);\n event.preventDefault();\n }\n\n protected onResize(event: PointerEvent): void {\n if (!this.resizing) return;\n const el = this.native()?.nativeElement;\n if (!el) return;\n const dir = this.effectiveResize();\n if (dir === 'vertical' || dir === 'both') {\n const h = Math.max(this.resizeMinHeight, this.resizeStartHeight + (event.clientY - this.resizeStartY));\n el.style.height = `${h}px`;\n }\n if (dir === 'horizontal' || dir === 'both') {\n const w = Math.min(\n this.resizeMaxWidth,\n Math.max(64, this.resizeStartWidth + (event.clientX - this.resizeStartX))\n );\n this.hostEl.nativeElement.style.width = `${w}px`;\n }\n }\n\n protected endResize(event: PointerEvent): void {\n if (!this.resizing) return;\n this.resizing = false;\n (event.target as HTMLElement).releasePointerCapture(event.pointerId);\n }\n\n private autofit(): void {\n const el = this.native()?.nativeElement;\n if (!el) return;\n\n el.style.height = 'auto';\n\n const maxRows = this.maxRows();\n if (maxRows && maxRows > 0) {\n const cs = getComputedStyle(el);\n const lineHeight = parseFloat(cs.lineHeight) || parseFloat(cs.fontSize) * 1.2;\n const cap = lineHeight * maxRows;\n const next = Math.min(el.scrollHeight, cap);\n el.style.height = `${next}px`;\n el.style.overflowY = el.scrollHeight > cap ? 'auto' : 'hidden';\n } else {\n el.style.height = `${el.scrollHeight}px`;\n el.style.overflowY = 'hidden';\n }\n }\n}\n","<textarea\n #native\n class=\"wr-textarea__native\"\n [placeholder]=\"placeholder()\"\n [rows]=\"rows()\"\n [readonly]=\"readonly()\"\n [disabled]=\"effectiveDisabled()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n (focus)=\"focused.set(true)\"\n (blur)=\"onBlur()\"\n></textarea>\n\n@if (showHandle()) {\n <!-- Custom corner grip — the lucide icon + cursor follow the `resize`\n direction. Icons inlined so no icon registration is required. -->\n <span\n [class]=\"`wr-textarea__resize wr-textarea__resize--${effectiveResize()}`\"\n aria-hidden=\"true\"\n (pointerdown)=\"startResize($event)\"\n (pointermove)=\"onResize($event)\"\n (pointerup)=\"endResize($event)\"\n (pointercancel)=\"endResize($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n @switch (effectiveResize()) {\n @case ('vertical') {\n <path d=\"M12 2v20\" />\n <path d=\"m8 18 4 4 4-4\" />\n <path d=\"m8 6 4-4 4 4\" />\n }\n @case ('horizontal') {\n <path d=\"M2 12h20\" />\n <path d=\"m18 8 4 4-4 4\" />\n <path d=\"m6 8-4 4 4 4\" />\n }\n @default {\n <path d=\"M19 13v6h-6\" />\n <path d=\"M5 11V5h6\" />\n <path d=\"m5 5 14 14\" />\n }\n }\n </svg>\n </span>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -118,10 +118,10 @@ class WrTheme {
118
118
  return;
119
119
  this.storage.set(this.config.storageKey, mode);
120
120
  }
121
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTheme, deps: [], target: i0.ɵɵFactoryTarget.Service });
122
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.2", ngImport: i0, type: WrTheme });
121
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTheme, deps: [], target: i0.ɵɵFactoryTarget.Service });
122
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.4", ngImport: i0, type: WrTheme });
123
123
  }
124
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTheme, decorators: [{
124
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTheme, decorators: [{
125
125
  type: Service
126
126
  }], ctorParameters: () => [] });
127
127
 
@@ -76,10 +76,10 @@ class WrTilt {
76
76
  host.appendChild(glare);
77
77
  this.destroyRef.onDestroy(() => glare.remove());
78
78
  }
79
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTilt, deps: [], target: i0.ɵɵFactoryTarget.Directive });
80
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: WrTilt, isStandalone: true, selector: "[wrTilt]", inputs: { maxTilt: { classPropertyName: "maxTilt", publicName: "maxTilt", isSignal: true, isRequired: false, transformFunction: null }, perspective: { classPropertyName: "perspective", publicName: "perspective", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, glare: { classPropertyName: "glare", publicName: "glare", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "pointermove": "onMove($event)", "pointerleave": "onLeave()" } }, ngImport: i0 });
79
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTilt, deps: [], target: i0.ɵɵFactoryTarget.Directive });
80
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.4", type: WrTilt, isStandalone: true, selector: "[wrTilt]", inputs: { maxTilt: { classPropertyName: "maxTilt", publicName: "maxTilt", isSignal: true, isRequired: false, transformFunction: null }, perspective: { classPropertyName: "perspective", publicName: "perspective", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, glare: { classPropertyName: "glare", publicName: "glare", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "pointermove": "onMove($event)", "pointerleave": "onLeave()" } }, ngImport: i0 });
81
81
  }
82
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTilt, decorators: [{
82
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTilt, decorators: [{
83
83
  type: Directive,
84
84
  args: [{
85
85
  selector: '[wrTilt]',
@@ -116,10 +116,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
116
116
  * ```
117
117
  */
118
118
  class WrTiltCard {
119
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTiltCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
120
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.2", type: WrTiltCard, isStandalone: true, selector: "wr-tilt-card", host: { classAttribute: "wr-tilt-card" }, hostDirectives: [{ directive: WrTilt, inputs: ["maxTilt", "maxTilt", "perspective", "perspective", "scale", "scale", "glare", "glare"] }], ngImport: i0, template: '<ng-content />', isInline: true, styles: [".wr-tilt-card{display:block;position:relative;padding:1.5rem;border-radius:.75rem;border:1px solid var(--wr-color-light);background:var(--wr-color-white);color:var(--wr-color-dark);box-shadow:0 1px 2px rgba(var(--wr-color-backdrop-rgb),.06);transform-style:preserve-3d;transition:transform .15s ease-out}.wr-tilt-glare{position:absolute;inset:0;pointer-events:none;background:radial-gradient(circle at var(--wr-tilt-glare-x, 50%) var(--wr-tilt-glare-y, 50%),var(--wr-tilt-glare-color, rgba(var(--wr-color-dark-rgb), .12)),transparent 60%);mix-blend-mode:multiply}[data-theme=dark] .wr-tilt-glare{--wr-tilt-glare-color: rgb(255 255 255 / 25%);mix-blend-mode:overlay}\n"], encapsulation: i0.ViewEncapsulation.None });
119
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTiltCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
120
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.4", type: WrTiltCard, isStandalone: true, selector: "wr-tilt-card", host: { classAttribute: "wr-tilt-card" }, hostDirectives: [{ directive: WrTilt, inputs: ["maxTilt", "maxTilt", "perspective", "perspective", "scale", "scale", "glare", "glare"] }], ngImport: i0, template: '<ng-content />', isInline: true, styles: [".wr-tilt-card{display:block;position:relative;padding:1.5rem;border-radius:.75rem;border:1px solid var(--wr-color-light);background:var(--wr-color-white);color:var(--wr-color-dark);box-shadow:0 1px 2px rgba(var(--wr-color-backdrop-rgb),.06);transform-style:preserve-3d;transition:transform .15s ease-out}.wr-tilt-glare{position:absolute;inset:0;pointer-events:none;background:radial-gradient(circle at var(--wr-tilt-glare-x, 50%) var(--wr-tilt-glare-y, 50%),var(--wr-tilt-glare-color, rgba(var(--wr-color-dark-rgb), .12)),transparent 60%);mix-blend-mode:multiply}[data-theme=dark] .wr-tilt-glare{--wr-tilt-glare-color: rgb(255 255 255 / 25%);mix-blend-mode:overlay}\n"], encapsulation: i0.ViewEncapsulation.None });
121
121
  }
122
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTiltCard, decorators: [{
122
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTiltCard, decorators: [{
123
123
  type: Component,
124
124
  args: [{ selector: 'wr-tilt-card', template: '<ng-content />', encapsulation: ViewEncapsulation.None, hostDirectives: [
125
125
  {
@@ -25,10 +25,10 @@ class WrTimeline {
25
25
  ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
26
26
  classes = computed(() => `wr-timeline wr-timeline--${this.orientation()}`, /* @ts-ignore */
27
27
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
28
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTimeline, deps: [], target: i0.ɵɵFactoryTarget.Component });
29
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: WrTimeline, isStandalone: true, selector: "wr-timeline", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: '<ng-content />', isInline: true, encapsulation: i0.ViewEncapsulation.None });
28
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTimeline, deps: [], target: i0.ɵɵFactoryTarget.Component });
29
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.4", type: WrTimeline, isStandalone: true, selector: "wr-timeline", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: '<ng-content />', isInline: true, encapsulation: i0.ViewEncapsulation.None });
30
30
  }
31
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTimeline, decorators: [{
31
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTimeline, decorators: [{
32
32
  type: Component,
33
33
  args: [{
34
34
  selector: 'wr-timeline',
@@ -57,10 +57,10 @@ class WrTimelineItem {
57
57
  ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
58
58
  classes = computed(() => `wr-timeline-item wr-timeline-item--${this.color()}`, /* @ts-ignore */
59
59
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
60
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTimelineItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
61
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: WrTimelineItem, isStandalone: true, selector: "wr-timeline-item", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, time: { classPropertyName: "time", publicName: "time", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: "<span class=\"wr-timeline-item__dot\" aria-hidden=\"true\"></span>\n<div class=\"wr-timeline-item__body\">\n @if (time()) {\n <div class=\"wr-timeline-item__time\">{{ time() }}</div>\n }\n @if (title()) {\n <div class=\"wr-timeline-item__title\">{{ title() }}</div>\n }\n <div class=\"wr-timeline-item__content\">\n <ng-content />\n </div>\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
60
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTimelineItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
61
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: WrTimelineItem, isStandalone: true, selector: "wr-timeline-item", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, time: { classPropertyName: "time", publicName: "time", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: "<span class=\"wr-timeline-item__dot\" aria-hidden=\"true\"></span>\n<div class=\"wr-timeline-item__body\">\n @if (time()) {\n <div class=\"wr-timeline-item__time\">{{ time() }}</div>\n }\n @if (title()) {\n <div class=\"wr-timeline-item__title\">{{ title() }}</div>\n }\n <div class=\"wr-timeline-item__content\">\n <ng-content />\n </div>\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
62
62
  }
63
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrTimelineItem, decorators: [{
63
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrTimelineItem, decorators: [{
64
64
  type: Component,
65
65
  args: [{ selector: 'wr-timeline-item', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, template: "<span class=\"wr-timeline-item__dot\" aria-hidden=\"true\"></span>\n<div class=\"wr-timeline-item__body\">\n @if (time()) {\n <div class=\"wr-timeline-item__time\">{{ time() }}</div>\n }\n @if (title()) {\n <div class=\"wr-timeline-item__title\">{{ title() }}</div>\n }\n <div class=\"wr-timeline-item__content\">\n <ng-content />\n </div>\n</div>\n" }]
66
66
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], time: [{ type: i0.Input, args: [{ isSignal: true, alias: "time", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }] } });
@@ -109,10 +109,10 @@ class WrToastItem {
109
109
  this.swipeX.set(0);
110
110
  }
111
111
  }
112
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrToastItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
113
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: WrToastItem, isStandalone: true, selector: "wr-toast", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, showProgress: { classPropertyName: "showProgress", publicName: "showProgress", isSignal: true, isRequired: false, transformFunction: null }, showCopy: { classPropertyName: "showCopy", publicName: "showCopy", isSignal: true, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { dismissed: "dismissed", pauseRequested: "pauseRequested", resumeRequested: "resumeRequested" }, host: { listeners: { "mouseenter": "pauseRequested.emit()", "mouseleave": "resumeRequested.emit()", "touchstart": "onSwipeStart($event)", "touchmove": "onSwipeMove($event)", "touchend": "onSwipeEnd()", "touchcancel": "onSwipeEnd()" }, properties: { "class": "classes()", "style.--wr-toast-duration": "durationMs()", "style.transform": "swipeTransform()", "style.opacity": "swipeOpacity()", "style.transition": "swiping() ? \"none\" : null", "attr.role": "liveRole()", "attr.aria-live": "liveLevel()" } }, ngImport: i0, template: "<div class=\"wr-toast__body\">\n @if (title(); as text) {\n <p class=\"wr-toast__title\">{{ text }}</p>\n }\n <p class=\"wr-toast__message\">{{ message() }}</p>\n</div>\n\n<div class=\"wr-toast__actions\">\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"wr-toast__action\"\n [attr.aria-label]=\"justCopied() ? labels().copied : labels().copy\"\n [title]=\"justCopied() ? labels().copied : labels().copy\"\n (click)=\"onCopy()\"\n >\n @if (justCopied()) {\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n } @else {\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n }\n </button>\n }\n\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"wr-toast__action\"\n [attr.aria-label]=\"labels().close\"\n [title]=\"labels().close\"\n (click)=\"dismissed.emit()\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n }\n</div>\n\n@if (progressVisible()) {\n <span class=\"wr-toast__progress\" aria-hidden=\"true\"></span>\n}\n", encapsulation: i0.ViewEncapsulation.None });
112
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrToastItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
113
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: WrToastItem, isStandalone: true, selector: "wr-toast", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, showProgress: { classPropertyName: "showProgress", publicName: "showProgress", isSignal: true, isRequired: false, transformFunction: null }, showCopy: { classPropertyName: "showCopy", publicName: "showCopy", isSignal: true, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { dismissed: "dismissed", pauseRequested: "pauseRequested", resumeRequested: "resumeRequested" }, host: { listeners: { "mouseenter": "pauseRequested.emit()", "mouseleave": "resumeRequested.emit()", "touchstart": "onSwipeStart($event)", "touchmove": "onSwipeMove($event)", "touchend": "onSwipeEnd()", "touchcancel": "onSwipeEnd()" }, properties: { "class": "classes()", "style.--wr-toast-duration": "durationMs()", "style.transform": "swipeTransform()", "style.opacity": "swipeOpacity()", "style.transition": "swiping() ? \"none\" : null", "attr.role": "liveRole()", "attr.aria-live": "liveLevel()" } }, ngImport: i0, template: "<div class=\"wr-toast__body\">\n @if (title(); as text) {\n <p class=\"wr-toast__title\">{{ text }}</p>\n }\n <p class=\"wr-toast__message\">{{ message() }}</p>\n</div>\n\n<div class=\"wr-toast__actions\">\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"wr-toast__action\"\n [attr.aria-label]=\"justCopied() ? labels().copied : labels().copy\"\n [title]=\"justCopied() ? labels().copied : labels().copy\"\n (click)=\"onCopy()\"\n >\n @if (justCopied()) {\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n } @else {\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n }\n </button>\n }\n\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"wr-toast__action\"\n [attr.aria-label]=\"labels().close\"\n [title]=\"labels().close\"\n (click)=\"dismissed.emit()\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n }\n</div>\n\n@if (progressVisible()) {\n <span class=\"wr-toast__progress\" aria-hidden=\"true\"></span>\n}\n", encapsulation: i0.ViewEncapsulation.None });
114
114
  }
115
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrToastItem, decorators: [{
115
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrToastItem, decorators: [{
116
116
  type: Component,
117
117
  args: [{ selector: 'wr-toast', encapsulation: ViewEncapsulation.None, host: {
118
118
  '[class]': 'classes()',
@@ -182,9 +182,15 @@ class WrToastHost {
182
182
  this.collapseTimer = null;
183
183
  }
184
184
  }
185
- /** @internal — pushed by the service. */
185
+ /** @internal — pushed by the service: the rendered (capped) stack. */
186
186
  toasts = signal([], /* @ts-ignore */
187
187
  ...(ngDevMode ? [{ debugName: "toasts" }] : /* istanbul ignore next */ []));
188
+ /** @internal — pushed by the service: count still queued behind the cap. */
189
+ queued = signal(0, /* @ts-ignore */
190
+ ...(ngDevMode ? [{ debugName: "queued" }] : /* istanbul ignore next */ []));
191
+ /** Total outstanding toasts (visible + queued) — what "Close all" clears. */
192
+ totalCount = computed(() => this.toasts().length + this.queued(), /* @ts-ignore */
193
+ ...(ngDevMode ? [{ debugName: "totalCount" }] : /* istanbul ignore next */ []));
188
194
  /** @internal — service listens to update its internal state. */
189
195
  dismissed = output();
190
196
  pauseRequested = output();
@@ -218,10 +224,10 @@ class WrToastHost {
218
224
  showCopyFor(t) {
219
225
  return t.showCopy ?? this.config().showCopy;
220
226
  }
221
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrToastHost, deps: [], target: i0.ɵɵFactoryTarget.Component });
222
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: WrToastHost, isStandalone: true, selector: "wr-toast-host", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed", pauseRequested: "pauseRequested", resumeRequested: "resumeRequested", dismissAllRequested: "dismissAllRequested" }, host: { attributes: { "role": "region", "aria-label": "Notifications" }, listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" }, properties: { "class": "classes()" } }, ngImport: i0, template: "@if (closeAllVisible()) {\n <button type=\"button\" class=\"wr-toast-host__close-all\" (click)=\"dismissAllRequested.emit()\">\n {{ config().labels.closeAll }} ({{ toasts().length }})\n </button>\n}\n\n@for (toast of toasts(); track toast.id) {\n <wr-toast\n [style.--wr-toast-stack-index]=\"stackIndex($index)\"\n [type]=\"toast.type ?? 'info'\"\n [title]=\"toast.title ?? null\"\n [message]=\"toast.message\"\n [dismissible]=\"toast.dismissible ?? true\"\n [showProgress]=\"showProgressFor(toast)\"\n [showCopy]=\"showCopyFor(toast)\"\n [duration]=\"toast.resolvedDuration\"\n [labels]=\"config().labels\"\n (dismissed)=\"dismissed.emit(toast.id)\"\n (pauseRequested)=\"pauseRequested.emit(toast.id)\"\n (resumeRequested)=\"resumeRequested.emit(toast.id)\"\n />\n}\n", dependencies: [{ kind: "component", type: WrToastItem, selector: "wr-toast", inputs: ["type", "title", "message", "dismissible", "showProgress", "showCopy", "duration", "labels"], outputs: ["dismissed", "pauseRequested", "resumeRequested"] }], encapsulation: i0.ViewEncapsulation.None });
227
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrToastHost, deps: [], target: i0.ɵɵFactoryTarget.Component });
228
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: WrToastHost, isStandalone: true, selector: "wr-toast-host", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed", pauseRequested: "pauseRequested", resumeRequested: "resumeRequested", dismissAllRequested: "dismissAllRequested" }, host: { attributes: { "role": "region", "aria-label": "Notifications" }, listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" }, properties: { "class": "classes()" } }, ngImport: i0, template: "@if (closeAllVisible()) {\n <button type=\"button\" class=\"wr-toast-host__close-all\" (click)=\"dismissAllRequested.emit()\">\n {{ config().labels.closeAll }} ({{ totalCount() }})\n </button>\n}\n\n@for (toast of toasts(); track toast.id) {\n <wr-toast\n [style.--wr-toast-stack-index]=\"stackIndex($index)\"\n [type]=\"toast.type ?? 'info'\"\n [title]=\"toast.title ?? null\"\n [message]=\"toast.message\"\n [dismissible]=\"toast.dismissible ?? true\"\n [showProgress]=\"showProgressFor(toast)\"\n [showCopy]=\"showCopyFor(toast)\"\n [duration]=\"toast.resolvedDuration\"\n [labels]=\"config().labels\"\n (dismissed)=\"dismissed.emit(toast.id)\"\n (pauseRequested)=\"pauseRequested.emit(toast.id)\"\n (resumeRequested)=\"resumeRequested.emit(toast.id)\"\n />\n}\n", dependencies: [{ kind: "component", type: WrToastItem, selector: "wr-toast", inputs: ["type", "title", "message", "dismissible", "showProgress", "showCopy", "duration", "labels"], outputs: ["dismissed", "pauseRequested", "resumeRequested"] }], encapsulation: i0.ViewEncapsulation.None });
223
229
  }
224
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrToastHost, decorators: [{
230
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrToastHost, decorators: [{
225
231
  type: Component,
226
232
  args: [{ selector: 'wr-toast-host', encapsulation: ViewEncapsulation.None, host: {
227
233
  '[class]': 'classes()',
@@ -229,7 +235,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
229
235
  'aria-label': 'Notifications',
230
236
  '(mouseenter)': 'onMouseEnter()',
231
237
  '(mouseleave)': 'onMouseLeave()',
232
- }, imports: [WrToastItem], template: "@if (closeAllVisible()) {\n <button type=\"button\" class=\"wr-toast-host__close-all\" (click)=\"dismissAllRequested.emit()\">\n {{ config().labels.closeAll }} ({{ toasts().length }})\n </button>\n}\n\n@for (toast of toasts(); track toast.id) {\n <wr-toast\n [style.--wr-toast-stack-index]=\"stackIndex($index)\"\n [type]=\"toast.type ?? 'info'\"\n [title]=\"toast.title ?? null\"\n [message]=\"toast.message\"\n [dismissible]=\"toast.dismissible ?? true\"\n [showProgress]=\"showProgressFor(toast)\"\n [showCopy]=\"showCopyFor(toast)\"\n [duration]=\"toast.resolvedDuration\"\n [labels]=\"config().labels\"\n (dismissed)=\"dismissed.emit(toast.id)\"\n (pauseRequested)=\"pauseRequested.emit(toast.id)\"\n (resumeRequested)=\"resumeRequested.emit(toast.id)\"\n />\n}\n" }]
238
+ }, imports: [WrToastItem], template: "@if (closeAllVisible()) {\n <button type=\"button\" class=\"wr-toast-host__close-all\" (click)=\"dismissAllRequested.emit()\">\n {{ config().labels.closeAll }} ({{ totalCount() }})\n </button>\n}\n\n@for (toast of toasts(); track toast.id) {\n <wr-toast\n [style.--wr-toast-stack-index]=\"stackIndex($index)\"\n [type]=\"toast.type ?? 'info'\"\n [title]=\"toast.title ?? null\"\n [message]=\"toast.message\"\n [dismissible]=\"toast.dismissible ?? true\"\n [showProgress]=\"showProgressFor(toast)\"\n [showCopy]=\"showCopyFor(toast)\"\n [duration]=\"toast.resolvedDuration\"\n [labels]=\"config().labels\"\n (dismissed)=\"dismissed.emit(toast.id)\"\n (pauseRequested)=\"pauseRequested.emit(toast.id)\"\n (resumeRequested)=\"resumeRequested.emit(toast.id)\"\n />\n}\n" }]
233
239
  }], ctorParameters: () => [], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }], pauseRequested: [{ type: i0.Output, args: ["pauseRequested"] }], resumeRequested: [{ type: i0.Output, args: ["resumeRequested"] }], dismissAllRequested: [{ type: i0.Output, args: ["dismissAllRequested"] }] } });
234
240
 
235
241
  /**
@@ -328,7 +334,11 @@ class WrToast {
328
334
  currentPosition = this.config.position;
329
335
  currentMode = this.config.mode;
330
336
  nextId = 1;
337
+ /** Currently rendered toasts (capped at `config.maxStack`). */
331
338
  active = [];
339
+ /** Overflow waiting for a free slot — promoted FIFO as actives dismiss, so
340
+ * nothing is ever silently dropped. */
341
+ queue = [];
332
342
  /** Open a toast. Returns a handle you can `dismiss()` early. */
333
343
  show(options) {
334
344
  const resolvedPosition = options.position ?? this.config.position;
@@ -341,10 +351,17 @@ class WrToast {
341
351
  resolvedPosition,
342
352
  remaining: resolvedDuration,
343
353
  };
344
- this.active = [...this.active, entry];
345
- this.enforceMaxStack();
346
- this.pushToHost();
347
- this.startTimer(entry);
354
+ const max = this.config.maxStack;
355
+ if (max > 0 && this.active.length >= max) {
356
+ // Stack is full — hold this one in the queue (no timer until it's shown).
357
+ this.queue = [...this.queue, entry];
358
+ this.pushToHost();
359
+ }
360
+ else {
361
+ this.active = [...this.active, entry];
362
+ this.pushToHost();
363
+ this.startTimer(entry);
364
+ }
348
365
  return new WrToastRef(entry.id, options, id => this.dismiss(id));
349
366
  }
350
367
  /** Dismiss a single toast by id. */
@@ -353,8 +370,11 @@ class WrToast {
353
370
  if (entry?.timer)
354
371
  clearTimeout(entry.timer);
355
372
  this.active = this.active.filter(t => t.id !== id);
373
+ // A dismiss can also target a still-queued toast.
374
+ this.queue = this.queue.filter(t => t.id !== id);
375
+ this.promoteFromQueue();
356
376
  this.pushToHost();
357
- if (this.active.length === 0)
377
+ if (this.active.length === 0 && this.queue.length === 0)
358
378
  this.disposeHost();
359
379
  }
360
380
  /** Dismiss every visible toast. Wired to the host's "Close all" button. */
@@ -364,6 +384,7 @@ class WrToast {
364
384
  clearTimeout(entry.timer);
365
385
  }
366
386
  this.active = [];
387
+ this.queue = [];
367
388
  this.disposeHost();
368
389
  }
369
390
  /** Change the corner the stack opens in. Affects future toasts. */
@@ -427,19 +448,20 @@ class WrToast {
427
448
  this.startTimer(entry);
428
449
  });
429
450
  }
430
- enforceMaxStack() {
451
+ /** Fill any free stack slots from the queue (FIFO), starting each promoted
452
+ * toast's auto-dismiss timer only as it becomes visible. */
453
+ promoteFromQueue() {
431
454
  const max = this.config.maxStack;
432
- if (max <= 0 || this.active.length <= max)
433
- return;
434
- const overflow = this.active.slice(0, this.active.length - max);
435
- for (const entry of overflow) {
436
- if (entry.timer)
437
- clearTimeout(entry.timer);
455
+ while ((max <= 0 || this.active.length < max) && this.queue.length > 0) {
456
+ const [next, ...rest] = this.queue;
457
+ this.queue = rest;
458
+ this.active = [...this.active, next];
459
+ this.startTimer(next);
438
460
  }
439
- this.active = this.active.slice(this.active.length - max);
440
461
  }
441
462
  pushToHost() {
442
463
  this.hostRef?.instance.toasts.set([...this.active]);
464
+ this.hostRef?.instance.queued.set(this.queue.length);
443
465
  }
444
466
  disposeHost() {
445
467
  if (this.overlayRef) {
@@ -448,10 +470,10 @@ class WrToast {
448
470
  this.hostRef = null;
449
471
  }
450
472
  }
451
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrToast, deps: [], target: i0.ɵɵFactoryTarget.Service });
452
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.2", ngImport: i0, type: WrToast });
473
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrToast, deps: [], target: i0.ɵɵFactoryTarget.Service });
474
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.4", ngImport: i0, type: WrToast });
453
475
  }
454
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrToast, decorators: [{
476
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrToast, decorators: [{
455
477
  type: Service
456
478
  }] });
457
479