ngwr 7.2.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 (275) hide show
  1. package/README.md +8 -7
  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 +3 -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 +18 -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 +13 -3
  23. package/dialog/styles/_index.scss +3 -3
  24. package/divider/styles/_index.scss +1 -1
  25. package/drawer/styles/_index.scss +13 -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 +50 -9
  48. package/fesm2022/ngwr-carousel.mjs.map +1 -1
  49. package/fesm2022/ngwr-cascader.mjs +12 -35
  50. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  51. package/fesm2022/ngwr-checkbox.mjs +13 -30
  52. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  53. package/fesm2022/ngwr-circular-text.mjs +3 -3
  54. package/fesm2022/ngwr-click-spark.mjs +25 -6
  55. package/fesm2022/ngwr-click-spark.mjs.map +1 -1
  56. package/fesm2022/ngwr-clipboard.mjs +27 -6
  57. package/fesm2022/ngwr-clipboard.mjs.map +1 -1
  58. package/fesm2022/ngwr-collapse.mjs +9 -9
  59. package/fesm2022/ngwr-color-picker.mjs +7 -7
  60. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  61. package/fesm2022/ngwr-command-palette.mjs +3 -3
  62. package/fesm2022/ngwr-compare.mjs +3 -3
  63. package/fesm2022/ngwr-confetti.mjs +3 -3
  64. package/fesm2022/ngwr-context-menu.mjs +39 -15
  65. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  66. package/fesm2022/ngwr-cookie.mjs +3 -3
  67. package/fesm2022/ngwr-counter.mjs +12 -8
  68. package/fesm2022/ngwr-counter.mjs.map +1 -1
  69. package/fesm2022/ngwr-date-adapter-fns.mjs +3 -3
  70. package/fesm2022/ngwr-date-adapter-luxon.mjs +3 -3
  71. package/fesm2022/ngwr-date-adapter.mjs +3 -3
  72. package/fesm2022/ngwr-date-picker.mjs +25 -11
  73. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  74. package/fesm2022/ngwr-decrypt-text.mjs +3 -3
  75. package/fesm2022/ngwr-density.mjs +14 -14
  76. package/fesm2022/ngwr-density.mjs.map +1 -1
  77. package/fesm2022/ngwr-descriptions.mjs +6 -6
  78. package/fesm2022/ngwr-dialog.mjs +15 -15
  79. package/fesm2022/ngwr-directives.mjs +15 -87
  80. package/fesm2022/ngwr-directives.mjs.map +1 -1
  81. package/fesm2022/ngwr-divider.mjs +3 -3
  82. package/fesm2022/ngwr-donut-chart.mjs +10 -4
  83. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  84. package/fesm2022/ngwr-drag-drop.mjs +18 -8
  85. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  86. package/fesm2022/ngwr-drawer.mjs +80 -19
  87. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  88. package/fesm2022/ngwr-dropdown.mjs +9 -9
  89. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  90. package/fesm2022/ngwr-empty.mjs +3 -3
  91. package/fesm2022/ngwr-falling-text.mjs +3 -3
  92. package/fesm2022/ngwr-file-upload.mjs +3 -3
  93. package/fesm2022/ngwr-form.mjs +9 -9
  94. package/fesm2022/ngwr-fuzzy-text.mjs +8 -7
  95. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  96. package/fesm2022/ngwr-gauge.mjs +3 -3
  97. package/fesm2022/ngwr-glitch-text.mjs +15 -7
  98. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  99. package/fesm2022/ngwr-gradient-text.mjs +3 -3
  100. package/fesm2022/ngwr-hotkey.mjs +6 -6
  101. package/fesm2022/ngwr-i18n.mjs +9 -9
  102. package/fesm2022/ngwr-icon.mjs +3 -3
  103. package/fesm2022/ngwr-image-cropper.mjs +3 -3
  104. package/fesm2022/ngwr-input-number.mjs +4 -4
  105. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  106. package/fesm2022/ngwr-input-otp.mjs +10 -4
  107. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  108. package/fesm2022/ngwr-input.mjs +25 -16
  109. package/fesm2022/ngwr-input.mjs.map +1 -1
  110. package/fesm2022/ngwr-keyboard.mjs +3 -3
  111. package/fesm2022/ngwr-knob.mjs +3 -3
  112. package/fesm2022/ngwr-layout.mjs +15 -15
  113. package/fesm2022/ngwr-lightbox.mjs +60 -5
  114. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  115. package/fesm2022/ngwr-line-chart.mjs +3 -3
  116. package/fesm2022/ngwr-list.mjs +7 -7
  117. package/fesm2022/ngwr-list.mjs.map +1 -1
  118. package/fesm2022/ngwr-loading-bar.mjs +6 -6
  119. package/fesm2022/ngwr-marquee.mjs +3 -3
  120. package/fesm2022/ngwr-media.mjs +3 -3
  121. package/fesm2022/ngwr-mention.mjs +6 -6
  122. package/fesm2022/ngwr-meta.mjs +6 -6
  123. package/fesm2022/ngwr-meter-group.mjs +3 -3
  124. package/fesm2022/ngwr-overlay.mjs +3 -3
  125. package/fesm2022/ngwr-page-header.mjs +3 -3
  126. package/fesm2022/ngwr-pagination.mjs +14 -16
  127. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  128. package/fesm2022/ngwr-pipes.mjs +21 -21
  129. package/fesm2022/ngwr-platform.mjs +3 -3
  130. package/fesm2022/ngwr-popconfirm.mjs +6 -6
  131. package/fesm2022/ngwr-popover.mjs +6 -6
  132. package/fesm2022/ngwr-progress.mjs +3 -3
  133. package/fesm2022/ngwr-qr.mjs +3 -3
  134. package/fesm2022/ngwr-radio.mjs +28 -26
  135. package/fesm2022/ngwr-radio.mjs.map +1 -1
  136. package/fesm2022/ngwr-rating.mjs +12 -23
  137. package/fesm2022/ngwr-rating.mjs.map +1 -1
  138. package/fesm2022/ngwr-result.mjs +12 -12
  139. package/fesm2022/ngwr-rotating-text.mjs +18 -7
  140. package/fesm2022/ngwr-rotating-text.mjs.map +1 -1
  141. package/fesm2022/ngwr-scroll.mjs +3 -3
  142. package/fesm2022/ngwr-segmented.mjs +10 -22
  143. package/fesm2022/ngwr-segmented.mjs.map +1 -1
  144. package/fesm2022/ngwr-select.mjs +26 -13
  145. package/fesm2022/ngwr-select.mjs.map +1 -1
  146. package/fesm2022/ngwr-shiny-text.mjs +6 -6
  147. package/fesm2022/ngwr-sidebar.mjs +3 -3
  148. package/fesm2022/ngwr-skeleton.mjs +3 -3
  149. package/fesm2022/ngwr-slider.mjs +3 -3
  150. package/fesm2022/ngwr-sparkline.mjs +3 -3
  151. package/fesm2022/ngwr-speed-dial.mjs +3 -3
  152. package/fesm2022/ngwr-spinner.mjs +3 -3
  153. package/fesm2022/ngwr-splash-cursor.mjs +3 -3
  154. package/fesm2022/ngwr-split-text.mjs +3 -3
  155. package/fesm2022/ngwr-splitter.mjs +3 -3
  156. package/fesm2022/ngwr-spotlight-card.mjs +8 -8
  157. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  158. package/fesm2022/ngwr-squircle.mjs +6 -6
  159. package/fesm2022/ngwr-star-border.mjs +3 -3
  160. package/fesm2022/ngwr-statistic.mjs +79 -10
  161. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  162. package/fesm2022/ngwr-stepper.mjs +6 -6
  163. package/fesm2022/ngwr-storage.mjs +3 -3
  164. package/fesm2022/ngwr-switch.mjs +10 -14
  165. package/fesm2022/ngwr-switch.mjs.map +1 -1
  166. package/fesm2022/ngwr-table.mjs +20 -14
  167. package/fesm2022/ngwr-table.mjs.map +1 -1
  168. package/fesm2022/ngwr-tabs.mjs +45 -11
  169. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  170. package/fesm2022/ngwr-textarea.mjs +84 -25
  171. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  172. package/fesm2022/ngwr-theme.mjs +3 -3
  173. package/fesm2022/ngwr-tilt-card.mjs +6 -6
  174. package/fesm2022/ngwr-timeline.mjs +6 -6
  175. package/fesm2022/ngwr-toast.mjs +99 -25
  176. package/fesm2022/ngwr-toast.mjs.map +1 -1
  177. package/fesm2022/ngwr-toolbar.mjs +13 -6
  178. package/fesm2022/ngwr-toolbar.mjs.map +1 -1
  179. package/fesm2022/ngwr-tree.mjs +3 -3
  180. package/fesm2022/ngwr-typewriter.mjs +3 -3
  181. package/fesm2022/ngwr-typography.mjs +3 -3
  182. package/fesm2022/ngwr-validators.mjs +41 -3
  183. package/fesm2022/ngwr-validators.mjs.map +1 -1
  184. package/fesm2022/ngwr-version.mjs +1 -1
  185. package/fesm2022/ngwr-version.mjs.map +1 -1
  186. package/fesm2022/ngwr-virtual-scroll.mjs +3 -3
  187. package/fesm2022/ngwr-waves.mjs +3 -3
  188. package/fesm2022/ngwr-window.mjs +12 -12
  189. package/file-upload/styles/_index.scss +3 -3
  190. package/form/styles/_index.scss +5 -5
  191. package/glitch-text/styles/_index.scss +3 -6
  192. package/image-cropper/styles/_index.scss +3 -3
  193. package/input/styles/_index.scss +26 -7
  194. package/input-otp/styles/_index.scss +23 -5
  195. package/keyboard/styles/_index.scss +6 -4
  196. package/knob/styles/_index.scss +1 -1
  197. package/lightbox/styles/_index.scss +31 -10
  198. package/list/styles/_index.scss +3 -3
  199. package/llms-full.txt +668 -0
  200. package/llms.txt +106 -0
  201. package/mention/styles/_index.scss +2 -2
  202. package/overlay/styles/_index.scss +1 -1
  203. package/package.json +1 -6
  204. package/pagination/styles/_index.scss +36 -25
  205. package/popconfirm/styles/_index.scss +1 -1
  206. package/popover/styles/_index.scss +2 -2
  207. package/radio/styles/_index.scss +20 -5
  208. package/rating/styles/_index.scss +12 -1
  209. package/schematics/migrations/v8/index.js +122 -0
  210. package/schematics/migrations.json +5 -0
  211. package/schematics/ng-add/index.js +3 -3
  212. package/schematics/ng-add/schema.json +6 -6
  213. package/schematics/provider/schema.json +1 -1
  214. package/schematics/use/symbol-map.json +11 -2
  215. package/segmented/styles/_index.scss +31 -8
  216. package/select/styles/_index.scss +73 -25
  217. package/sidebar/styles/_index.scss +3 -3
  218. package/slider/styles/_index.scss +5 -3
  219. package/speed-dial/styles/_index.scss +1 -0
  220. package/splitter/styles/_index.scss +7 -4
  221. package/spotlight-card/styles/_index.scss +8 -4
  222. package/stepper/styles/_index.scss +4 -4
  223. package/styles/_animations.scss +0 -23
  224. package/styles.scss +0 -1
  225. package/switch/styles/_index.scss +25 -6
  226. package/table/styles/_index.scss +69 -8
  227. package/tabs/styles/_index.scss +46 -3
  228. package/textarea/styles/_index.scss +59 -4
  229. package/theme/styles/_colors.scss +57 -0
  230. package/theme/styles/_dark.scss +22 -8
  231. package/theme/styles/_focus.scss +5 -0
  232. package/theme/styles/_variables.scss +24 -0
  233. package/timeline/styles/_index.scss +11 -2
  234. package/toast/styles/_index.scss +15 -5
  235. package/toolbar/styles/_index.scss +30 -1
  236. package/tree/styles/_index.scss +18 -17
  237. package/types/ngwr-alert.d.ts +16 -6
  238. package/types/ngwr-carousel.d.ts +8 -1
  239. package/types/ngwr-cascader.d.ts +5 -2
  240. package/types/ngwr-checkbox.d.ts +5 -2
  241. package/types/ngwr-click-spark.d.ts +13 -1
  242. package/types/ngwr-clipboard.d.ts +12 -1
  243. package/types/ngwr-context-menu.d.ts +20 -3
  244. package/types/ngwr-date-picker.d.ts +3 -0
  245. package/types/ngwr-density.d.ts +7 -7
  246. package/types/ngwr-directives.d.ts +17 -49
  247. package/types/ngwr-drag-drop.d.ts +13 -1
  248. package/types/ngwr-drawer.d.ts +11 -3
  249. package/types/ngwr-fuzzy-text.d.ts +1 -1
  250. package/types/ngwr-glitch-text.d.ts +9 -3
  251. package/types/ngwr-input-otp.d.ts +6 -2
  252. package/types/ngwr-input.d.ts +27 -13
  253. package/types/ngwr-lightbox.d.ts +14 -1
  254. package/types/ngwr-pagination.d.ts +10 -10
  255. package/types/ngwr-radio.d.ts +14 -3
  256. package/types/ngwr-rating.d.ts +5 -1
  257. package/types/ngwr-rotating-text.d.ts +1 -0
  258. package/types/ngwr-segmented.d.ts +5 -2
  259. package/types/ngwr-select.d.ts +6 -2
  260. package/types/ngwr-spotlight-card.d.ts +1 -1
  261. package/types/ngwr-statistic.d.ts +35 -1
  262. package/types/ngwr-switch.d.ts +5 -1
  263. package/types/ngwr-table.d.ts +7 -1
  264. package/types/ngwr-tabs.d.ts +6 -0
  265. package/types/ngwr-textarea.d.ts +25 -3
  266. package/types/ngwr-toast.d.ts +7 -1
  267. package/types/ngwr-toolbar.d.ts +7 -1
  268. package/types/ngwr-validators.d.ts +3 -1
  269. package/types/ngwr-version.d.ts +1 -1
  270. package/window/styles/_index.scss +8 -8
  271. package/fesm2022/ngwr-scramble-text.mjs +0 -165
  272. package/fesm2022/ngwr-scramble-text.mjs.map +0 -1
  273. package/scramble-text/scramble-text.scss +0 -1
  274. package/scramble-text/styles/_index.scss +0 -8
  275. package/types/ngwr-scramble-text.d.ts +0 -49
@@ -14,6 +14,17 @@ function stringValue(control) {
14
14
  return String(v).trim();
15
15
  return '';
16
16
  }
17
+ /** Like {@link stringValue} but preserves whitespace — for checks that inspect spacing. */
18
+ function rawStringValue(control) {
19
+ const v = control.value;
20
+ if (v == null)
21
+ return '';
22
+ if (typeof v === 'string')
23
+ return v;
24
+ if (typeof v === 'number' || typeof v === 'boolean')
25
+ return String(v);
26
+ return '';
27
+ }
17
28
  /** Luhn checksum. Returns true when the digit string is a valid card number. */
18
29
  function luhn(digits) {
19
30
  let sum = 0;
@@ -86,7 +97,7 @@ const WrValidators = {
86
97
  // String shape
87
98
  /** No whitespace anywhere in the value. */
88
99
  noWhitespace: (control) => {
89
- const v = stringValue(control);
100
+ const v = rawStringValue(control);
90
101
  if (v === '')
91
102
  return null;
92
103
  return /\s/.test(v) ? { noWhitespace: true } : null;
@@ -101,10 +112,12 @@ const WrValidators = {
101
112
  // Network / payments
102
113
  /**
103
114
  * Valid URL. Accepts any scheme by default; pass `{ protocols: ['https'] }`
104
- * to restrict.
115
+ * to restrict. A scheme is required by default; pass `{ requireProtocol: false }`
116
+ * to also accept bare domains (e.g. `ngwr.dev`), assuming `https`.
105
117
  */
106
118
  url: (options = {}) => {
107
119
  const allow = options.protocols?.map(p => p.replace(/:$/, '').toLowerCase());
120
+ const requireProtocol = options.requireProtocol ?? true;
108
121
  return (control) => {
109
122
  const v = stringValue(control);
110
123
  if (v === '')
@@ -114,9 +127,34 @@ const WrValidators = {
114
127
  parsed = new URL(v);
115
128
  }
116
129
  catch {
130
+ // Bare domain support: when protocols aren't required and the input has
131
+ // no scheme, retry assuming `https://`.
132
+ if (!requireProtocol && !/^[a-z][a-z0-9+.-]*:/i.test(v)) {
133
+ let retried;
134
+ try {
135
+ retried = new URL(`https://${v}`);
136
+ }
137
+ catch {
138
+ return { url: true };
139
+ }
140
+ if (retried.host === '') {
141
+ return { url: true };
142
+ }
143
+ if (allow && !allow.includes('https')) {
144
+ return { url: { allowed: allow } };
145
+ }
146
+ return null;
147
+ }
148
+ return { url: true };
149
+ }
150
+ const protocol = parsed.protocol.replace(/:$/, '').toLowerCase();
151
+ // WHATWG auto-inserts the authority for "special" schemes, so `http:host`
152
+ // (missing `//`) still parses. Require the explicit `//` for those.
153
+ const needsAuthority = ['http', 'https', 'ws', 'wss', 'ftp', 'file'].includes(protocol);
154
+ if (needsAuthority && !/^[a-z][a-z0-9+.-]*:\/\//i.test(v)) {
117
155
  return { url: true };
118
156
  }
119
- if (allow && !allow.includes(parsed.protocol.replace(/:$/, '').toLowerCase())) {
157
+ if (allow && !allow.includes(protocol)) {
120
158
  return { url: { allowed: allow } };
121
159
  }
122
160
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-validators.mjs","sources":["../../../projects/lib/validators/wr-validators.ts","../../../projects/lib/validators/ngwr-validators.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 { type AbstractControl, type ValidationErrors, type ValidatorFn } from '@angular/forms';\n\nfunction stringValue(control: AbstractControl): string {\n const v: unknown = control.value;\n if (v == null) return '';\n if (typeof v === 'string') return v.trim();\n if (typeof v === 'number' || typeof v === 'boolean') return String(v).trim();\n return '';\n}\n\n/** Luhn checksum. Returns true when the digit string is a valid card number. */\nfunction luhn(digits: string): boolean {\n let sum = 0;\n let dbl = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = digits.charCodeAt(i) - 48;\n if (dbl) {\n d *= 2;\n if (d > 9) d -= 9;\n }\n sum += d;\n dbl = !dbl;\n }\n return sum % 10 === 0;\n}\n\n/** ISO 13616 mod-97 check for IBANs. Returns the remainder; valid IBANs yield 1. */\nfunction mod97(iban: string): number {\n // Move first 4 chars to the end + convert letters to digits (A=10..Z=35).\n const rearranged = iban.slice(4) + iban.slice(0, 4);\n let expanded = '';\n for (let i = 0; i < rearranged.length; i++) {\n const code = rearranged.charCodeAt(i);\n if (code >= 65 && code <= 90) expanded += (code - 55).toString();\n else expanded += rearranged.charAt(i);\n }\n // Apply mod 97 in chunks — BigInt isn't necessary.\n let remainder = 0;\n for (let i = 0; i < expanded.length; i += 7) {\n const slice = remainder.toString() + expanded.substring(i, i + 7);\n remainder = Number.parseInt(slice, 10) % 97;\n }\n return remainder;\n}\n\nfunction toMs(value: unknown): number {\n if (value instanceof Date) return value.getTime();\n if (typeof value === 'string' || typeof value === 'number') return new Date(value).getTime();\n return Number.NaN;\n}\n\n/**\n * Bundled `ValidatorFn`s — pure functions, no DOM, no DI. Mirrors the\n * API shape of Angular's built-in `Validators` so it composes cleanly:\n *\n * ```ts\n * import { Validators } from '@angular/forms';\n * import { WrValidators } from 'ngwr/validators';\n *\n * new FormControl('', [\n * Validators.required,\n * WrValidators.cardNumber,\n * WrValidators.cvc(3),\n * WrValidators.match('password'),\n * WrValidators.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),\n * ]);\n * ```\n *\n * Each error is keyed under the validator name (e.g. `cardNumber`,\n * `cvc`, `iban`) so consumers can branch in templates.\n *\n * Anything Angular already ships (`required`, `email`, `min`, `max`,\n * `pattern`, …) is deliberately NOT duplicated here.\n *\n * @see https://ngwr.dev/validators\n */\nexport const WrValidators = {\n // String shape\n\n /** No whitespace anywhere in the value. */\n noWhitespace: (control: AbstractControl): ValidationErrors | null => {\n const v = stringValue(control);\n if (v === '') return null;\n return /\\s/.test(v) ? { noWhitespace: true } : null;\n },\n\n /** 3, 4, 6, or 8-digit hex colour (`#abc`, `#1a2b3c`, `#1a2b3c4d`). */\n hexColor: (control: AbstractControl): ValidationErrors | null => {\n const v = stringValue(control);\n if (v === '') return null;\n return /^#([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(v) ? null : { hexColor: true };\n },\n\n // Network / payments\n\n /**\n * Valid URL. Accepts any scheme by default; pass `{ protocols: ['https'] }`\n * to restrict.\n */\n url: (options: { readonly protocols?: readonly string[] } = {}): ValidatorFn => {\n const allow = options.protocols?.map(p => p.replace(/:$/, '').toLowerCase());\n return (control: AbstractControl): ValidationErrors | null => {\n const v = stringValue(control);\n if (v === '') return null;\n let parsed: URL;\n try {\n parsed = new URL(v);\n } catch {\n return { url: true };\n }\n if (allow && !allow.includes(parsed.protocol.replace(/:$/, '').toLowerCase())) {\n return { url: { allowed: allow } };\n }\n return null;\n };\n },\n\n /** Credit card number — Luhn check + 13-19 digit length. Spaces and dashes are stripped first. */\n cardNumber: (control: AbstractControl): ValidationErrors | null => {\n const raw = stringValue(control).replace(/[\\s-]/g, '');\n if (raw === '') return null;\n if (!/^\\d{13,19}$/.test(raw)) return { cardNumber: true };\n return luhn(raw) ? null : { cardNumber: true };\n },\n\n /** CVC / CVV — N digits (default 3). Common: 3 for Visa/MC, 4 for Amex. */\n cvc: (length = 3): ValidatorFn => {\n const re = new RegExp(`^\\\\d{${length}}$`);\n return (control: AbstractControl): ValidationErrors | null => {\n const v = stringValue(control);\n if (v === '') return null;\n return re.test(v) ? null : { cvc: { length } };\n };\n },\n\n /**\n * IBAN — basic structure (CC + 2 digits + up to 30 alphanumerics) +\n * the mod-97 check. Country-length tables not enforced.\n */\n iban: (control: AbstractControl): ValidationErrors | null => {\n const raw = stringValue(control).replace(/\\s/g, '').toUpperCase();\n if (raw === '') return null;\n if (!/^[A-Z]{2}\\d{2}[A-Z0-9]{4,30}$/.test(raw)) return { iban: true };\n return mod97(raw) === 1 ? null : { iban: true };\n },\n\n // Cross-field\n\n /**\n * Value must equal a sibling control's value (e.g. confirm-password).\n * The target lookup uses `control.parent.get(name)`, so it works\n * inside `FormGroup` and nested groups.\n */\n match: (targetName: string): ValidatorFn => {\n return (control: AbstractControl): ValidationErrors | null => {\n const target = control.parent?.get(targetName);\n if (!target) return null;\n return control.value === target.value ? null : { match: { target: targetName } };\n };\n },\n\n // Choice\n\n /** Value must be one of the allowed entries (strict equality). */\n oneOf: <T>(allowed: readonly T[]): ValidatorFn => {\n return (control: AbstractControl): ValidationErrors | null => {\n const v = control.value as T;\n if (v == null || (v as unknown) === '') return null;\n return allowed.includes(v) ? null : { oneOf: { allowed } };\n };\n },\n\n // Date bounds\n\n /** Value (Date | parseable) must be ≥ `min`. */\n minDate: (min: Date | string | number): ValidatorFn => {\n const minMs = toMs(min);\n return (control: AbstractControl): ValidationErrors | null => {\n const v: unknown = control.value;\n if (v == null || v === '') return null;\n const got = toMs(v);\n if (Number.isNaN(got)) return { minDate: { min } };\n return got >= minMs ? null : { minDate: { min } };\n };\n },\n\n /** Value (Date | parseable) must be ≤ `max`. */\n maxDate: (max: Date | string | number): ValidatorFn => {\n const maxMs = toMs(max);\n return (control: AbstractControl): ValidationErrors | null => {\n const v: unknown = control.value;\n if (v == null || v === '') return null;\n const got = toMs(v);\n if (Number.isNaN(got)) return { maxDate: { max } };\n return got <= maxMs ? null : { maxDate: { max } };\n };\n },\n};\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-validators.mjs","sources":["../../../projects/lib/validators/wr-validators.ts","../../../projects/lib/validators/ngwr-validators.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 { type AbstractControl, type ValidationErrors, type ValidatorFn } from '@angular/forms';\n\nfunction stringValue(control: AbstractControl): string {\n const v: unknown = control.value;\n if (v == null) return '';\n if (typeof v === 'string') return v.trim();\n if (typeof v === 'number' || typeof v === 'boolean') return String(v).trim();\n return '';\n}\n\n/** Like {@link stringValue} but preserves whitespace — for checks that inspect spacing. */\nfunction rawStringValue(control: AbstractControl): string {\n const v: unknown = control.value;\n if (v == null) return '';\n if (typeof v === 'string') return v;\n if (typeof v === 'number' || typeof v === 'boolean') return String(v);\n return '';\n}\n\n/** Luhn checksum. Returns true when the digit string is a valid card number. */\nfunction luhn(digits: string): boolean {\n let sum = 0;\n let dbl = false;\n for (let i = digits.length - 1; i >= 0; i--) {\n let d = digits.charCodeAt(i) - 48;\n if (dbl) {\n d *= 2;\n if (d > 9) d -= 9;\n }\n sum += d;\n dbl = !dbl;\n }\n return sum % 10 === 0;\n}\n\n/** ISO 13616 mod-97 check for IBANs. Returns the remainder; valid IBANs yield 1. */\nfunction mod97(iban: string): number {\n // Move first 4 chars to the end + convert letters to digits (A=10..Z=35).\n const rearranged = iban.slice(4) + iban.slice(0, 4);\n let expanded = '';\n for (let i = 0; i < rearranged.length; i++) {\n const code = rearranged.charCodeAt(i);\n if (code >= 65 && code <= 90) expanded += (code - 55).toString();\n else expanded += rearranged.charAt(i);\n }\n // Apply mod 97 in chunks — BigInt isn't necessary.\n let remainder = 0;\n for (let i = 0; i < expanded.length; i += 7) {\n const slice = remainder.toString() + expanded.substring(i, i + 7);\n remainder = Number.parseInt(slice, 10) % 97;\n }\n return remainder;\n}\n\nfunction toMs(value: unknown): number {\n if (value instanceof Date) return value.getTime();\n if (typeof value === 'string' || typeof value === 'number') return new Date(value).getTime();\n return Number.NaN;\n}\n\n/**\n * Bundled `ValidatorFn`s — pure functions, no DOM, no DI. Mirrors the\n * API shape of Angular's built-in `Validators` so it composes cleanly:\n *\n * ```ts\n * import { Validators } from '@angular/forms';\n * import { WrValidators } from 'ngwr/validators';\n *\n * new FormControl('', [\n * Validators.required,\n * WrValidators.cardNumber,\n * WrValidators.cvc(3),\n * WrValidators.match('password'),\n * WrValidators.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),\n * ]);\n * ```\n *\n * Each error is keyed under the validator name (e.g. `cardNumber`,\n * `cvc`, `iban`) so consumers can branch in templates.\n *\n * Anything Angular already ships (`required`, `email`, `min`, `max`,\n * `pattern`, …) is deliberately NOT duplicated here.\n *\n * @see https://ngwr.dev/validators\n */\nexport const WrValidators = {\n // String shape\n\n /** No whitespace anywhere in the value. */\n noWhitespace: (control: AbstractControl): ValidationErrors | null => {\n const v = rawStringValue(control);\n if (v === '') return null;\n return /\\s/.test(v) ? { noWhitespace: true } : null;\n },\n\n /** 3, 4, 6, or 8-digit hex colour (`#abc`, `#1a2b3c`, `#1a2b3c4d`). */\n hexColor: (control: AbstractControl): ValidationErrors | null => {\n const v = stringValue(control);\n if (v === '') return null;\n return /^#([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(v) ? null : { hexColor: true };\n },\n\n // Network / payments\n\n /**\n * Valid URL. Accepts any scheme by default; pass `{ protocols: ['https'] }`\n * to restrict. A scheme is required by default; pass `{ requireProtocol: false }`\n * to also accept bare domains (e.g. `ngwr.dev`), assuming `https`.\n */\n url: (options: { readonly protocols?: readonly string[]; readonly requireProtocol?: boolean } = {}): ValidatorFn => {\n const allow = options.protocols?.map(p => p.replace(/:$/, '').toLowerCase());\n const requireProtocol = options.requireProtocol ?? true;\n return (control: AbstractControl): ValidationErrors | null => {\n const v = stringValue(control);\n if (v === '') return null;\n let parsed: URL;\n try {\n parsed = new URL(v);\n } catch {\n // Bare domain support: when protocols aren't required and the input has\n // no scheme, retry assuming `https://`.\n if (!requireProtocol && !/^[a-z][a-z0-9+.-]*:/i.test(v)) {\n let retried: URL;\n try {\n retried = new URL(`https://${v}`);\n } catch {\n return { url: true };\n }\n if (retried.host === '') {\n return { url: true };\n }\n if (allow && !allow.includes('https')) {\n return { url: { allowed: allow } };\n }\n return null;\n }\n return { url: true };\n }\n const protocol = parsed.protocol.replace(/:$/, '').toLowerCase();\n // WHATWG auto-inserts the authority for \"special\" schemes, so `http:host`\n // (missing `//`) still parses. Require the explicit `//` for those.\n const needsAuthority = ['http', 'https', 'ws', 'wss', 'ftp', 'file'].includes(protocol);\n if (needsAuthority && !/^[a-z][a-z0-9+.-]*:\\/\\//i.test(v)) {\n return { url: true };\n }\n if (allow && !allow.includes(protocol)) {\n return { url: { allowed: allow } };\n }\n return null;\n };\n },\n\n /** Credit card number — Luhn check + 13-19 digit length. Spaces and dashes are stripped first. */\n cardNumber: (control: AbstractControl): ValidationErrors | null => {\n const raw = stringValue(control).replace(/[\\s-]/g, '');\n if (raw === '') return null;\n if (!/^\\d{13,19}$/.test(raw)) return { cardNumber: true };\n return luhn(raw) ? null : { cardNumber: true };\n },\n\n /** CVC / CVV — N digits (default 3). Common: 3 for Visa/MC, 4 for Amex. */\n cvc: (length = 3): ValidatorFn => {\n const re = new RegExp(`^\\\\d{${length}}$`);\n return (control: AbstractControl): ValidationErrors | null => {\n const v = stringValue(control);\n if (v === '') return null;\n return re.test(v) ? null : { cvc: { length } };\n };\n },\n\n /**\n * IBAN — basic structure (CC + 2 digits + up to 30 alphanumerics) +\n * the mod-97 check. Country-length tables not enforced.\n */\n iban: (control: AbstractControl): ValidationErrors | null => {\n const raw = stringValue(control).replace(/\\s/g, '').toUpperCase();\n if (raw === '') return null;\n if (!/^[A-Z]{2}\\d{2}[A-Z0-9]{4,30}$/.test(raw)) return { iban: true };\n return mod97(raw) === 1 ? null : { iban: true };\n },\n\n // Cross-field\n\n /**\n * Value must equal a sibling control's value (e.g. confirm-password).\n * The target lookup uses `control.parent.get(name)`, so it works\n * inside `FormGroup` and nested groups.\n */\n match: (targetName: string): ValidatorFn => {\n return (control: AbstractControl): ValidationErrors | null => {\n const target = control.parent?.get(targetName);\n if (!target) return null;\n return control.value === target.value ? null : { match: { target: targetName } };\n };\n },\n\n // Choice\n\n /** Value must be one of the allowed entries (strict equality). */\n oneOf: <T>(allowed: readonly T[]): ValidatorFn => {\n return (control: AbstractControl): ValidationErrors | null => {\n const v = control.value as T;\n if (v == null || (v as unknown) === '') return null;\n return allowed.includes(v) ? null : { oneOf: { allowed } };\n };\n },\n\n // Date bounds\n\n /** Value (Date | parseable) must be ≥ `min`. */\n minDate: (min: Date | string | number): ValidatorFn => {\n const minMs = toMs(min);\n return (control: AbstractControl): ValidationErrors | null => {\n const v: unknown = control.value;\n if (v == null || v === '') return null;\n const got = toMs(v);\n if (Number.isNaN(got)) return { minDate: { min } };\n return got >= minMs ? null : { minDate: { min } };\n };\n },\n\n /** Value (Date | parseable) must be ≤ `max`. */\n maxDate: (max: Date | string | number): ValidatorFn => {\n const maxMs = toMs(max);\n return (control: AbstractControl): ValidationErrors | null => {\n const v: unknown = control.value;\n if (v == null || v === '') return null;\n const got = toMs(v);\n if (Number.isNaN(got)) return { maxDate: { max } };\n return got <= maxMs ? null : { maxDate: { max } };\n };\n },\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -16,7 +16,7 @@ import { InjectionToken } from '@angular/core';
16
16
  * Distinct from `Version` exported by `@angular/core`, which reports the
17
17
  * loaded Angular runtime version (e.g. `'21.2.13'`), not ngwr's.
18
18
  */
19
- const NGWR_VERSION = '7.2.0';
19
+ const NGWR_VERSION = '8.0.0';
20
20
 
21
21
  /**
22
22
  * @license
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-version.mjs","sources":["../../../projects/lib/version/version.ts","../../../projects/lib/version/version.token.ts","../../../projects/lib/version/ngwr-version.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\n/**\n * The ngwr library version string, kept in sync with\n * `projects/lib/package.json` by `scripts/release-prepare.ts`.\n *\n * Prefer this over reading `package.json` at runtime — that requires a JSON\n * import or `require`, neither of which tree-shakes well in Angular builds.\n *\n * Distinct from `Version` exported by `@angular/core`, which reports the\n * loaded Angular runtime version (e.g. `'21.2.13'`), not ngwr's.\n */\nexport const NGWR_VERSION = '7.2.0';\n","/**\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 { InjectionToken } from '@angular/core';\n\nimport { NGWR_VERSION } from './version';\n\n/**\n * Injection token holding the ngwr library version string.\n *\n * Default factory returns {@link NGWR_VERSION}. Override it in tests or in\n * apps that want to surface a custom build identifier.\n *\n * @example\n * ```ts\n * @Component({...})\n * export class FooterComponent {\n * readonly version = inject(NGWR_VERSION_TOKEN);\n * }\n * ```\n */\nexport const NGWR_VERSION_TOKEN = new InjectionToken<string>('NGWR_VERSION_TOKEN', {\n providedIn: 'root',\n factory: () => NGWR_VERSION,\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAEH;;;;;;;;;AASG;AACI,MAAM,YAAY,GAAG;;ACjB5B;;;;;AAKG;AAMH;;;;;;;;;;;;;AAaG;MACU,kBAAkB,GAAG,IAAI,cAAc,CAAS,oBAAoB,EAAE;AACjF,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAM,YAAY;AAC5B,CAAA;;AC5BD;;AAEG;;;;"}
1
+ {"version":3,"file":"ngwr-version.mjs","sources":["../../../projects/lib/version/version.ts","../../../projects/lib/version/version.token.ts","../../../projects/lib/version/ngwr-version.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\n/**\n * The ngwr library version string, kept in sync with\n * `projects/lib/package.json` by `scripts/release-prepare.ts`.\n *\n * Prefer this over reading `package.json` at runtime — that requires a JSON\n * import or `require`, neither of which tree-shakes well in Angular builds.\n *\n * Distinct from `Version` exported by `@angular/core`, which reports the\n * loaded Angular runtime version (e.g. `'21.2.13'`), not ngwr's.\n */\nexport const NGWR_VERSION = '8.0.0';\n","/**\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 { InjectionToken } from '@angular/core';\n\nimport { NGWR_VERSION } from './version';\n\n/**\n * Injection token holding the ngwr library version string.\n *\n * Default factory returns {@link NGWR_VERSION}. Override it in tests or in\n * apps that want to surface a custom build identifier.\n *\n * @example\n * ```ts\n * @Component({...})\n * export class FooterComponent {\n * readonly version = inject(NGWR_VERSION_TOKEN);\n * }\n * ```\n */\nexport const NGWR_VERSION_TOKEN = new InjectionToken<string>('NGWR_VERSION_TOKEN', {\n providedIn: 'root',\n factory: () => NGWR_VERSION,\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAEH;;;;;;;;;AASG;AACI,MAAM,YAAY,GAAG;;ACjB5B;;;;;AAKG;AAMH;;;;;;;;;;;;;AAaG;MACU,kBAAkB,GAAG,IAAI,cAAc,CAAS,oBAAoB,EAAE;AACjF,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAM,YAAY;AAC5B,CAAA;;AC5BD;;AAEG;;;;"}
@@ -83,10 +83,10 @@ class WrVirtualScroll {
83
83
  checkViewportSize() {
84
84
  this.viewport().checkViewportSize();
85
85
  }
86
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrVirtualScroll, deps: [], target: i0.ɵɵFactoryTarget.Component });
87
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.2", type: WrVirtualScroll, isStandalone: true, selector: "wr-virtual-scroll", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, minBufferPx: { classPropertyName: "minBufferPx", publicName: "minBufferPx", isSignal: true, isRequired: false, transformFunction: null }, maxBufferPx: { classPropertyName: "maxBufferPx", publicName: "maxBufferPx", isSignal: true, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-virtual-scroll" }, queries: [{ propertyName: "rowTemplate", first: true, predicate: (TemplateRef), descendants: true, isSignal: true }], viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], ngImport: i0, template: "<cdk-virtual-scroll-viewport\n class=\"wr-virtual-scroll__viewport\"\n [itemSize]=\"itemSize()\"\n [minBufferPx]=\"resolvedMinBuffer()\"\n [maxBufferPx]=\"resolvedMaxBuffer()\"\n [style.height]=\"resolvedHeight()\"\n>\n <ng-container *cdkVirtualFor=\"let item of items(); let i = index; trackBy: trackBy()\">\n <ng-container *ngTemplateOutlet=\"rowTemplate(); context: { $implicit: item, index: i }\" />\n </ng-container>\n</cdk-virtual-scroll-viewport>\n", styles: [".wr-virtual-scroll{display:block;width:100%;overflow:hidden}.wr-virtual-scroll__viewport{width:100%;height:100%;scrollbar-width:thin}.wr-virtual-scroll__viewport::-webkit-scrollbar{width:.5rem;height:.5rem}.wr-virtual-scroll__viewport::-webkit-scrollbar-thumb{background:rgba(var(--wr-color-dark-rgb),.2);border-radius:999px}\n"], dependencies: [{ kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], encapsulation: i0.ViewEncapsulation.None });
86
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrVirtualScroll, deps: [], target: i0.ɵɵFactoryTarget.Component });
87
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.4", type: WrVirtualScroll, isStandalone: true, selector: "wr-virtual-scroll", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, minBufferPx: { classPropertyName: "minBufferPx", publicName: "minBufferPx", isSignal: true, isRequired: false, transformFunction: null }, maxBufferPx: { classPropertyName: "maxBufferPx", publicName: "maxBufferPx", isSignal: true, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-virtual-scroll" }, queries: [{ propertyName: "rowTemplate", first: true, predicate: (TemplateRef), descendants: true, isSignal: true }], viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], ngImport: i0, template: "<cdk-virtual-scroll-viewport\n class=\"wr-virtual-scroll__viewport\"\n [itemSize]=\"itemSize()\"\n [minBufferPx]=\"resolvedMinBuffer()\"\n [maxBufferPx]=\"resolvedMaxBuffer()\"\n [style.height]=\"resolvedHeight()\"\n>\n <ng-container *cdkVirtualFor=\"let item of items(); let i = index; trackBy: trackBy()\">\n <ng-container *ngTemplateOutlet=\"rowTemplate(); context: { $implicit: item, index: i }\" />\n </ng-container>\n</cdk-virtual-scroll-viewport>\n", styles: [".wr-virtual-scroll{display:block;width:100%;overflow:hidden}.wr-virtual-scroll__viewport{width:100%;height:100%;scrollbar-width:thin}.wr-virtual-scroll__viewport::-webkit-scrollbar{width:.5rem;height:.5rem}.wr-virtual-scroll__viewport::-webkit-scrollbar-thumb{background:rgba(var(--wr-color-dark-rgb),.2);border-radius:999px}\n"], dependencies: [{ kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], encapsulation: i0.ViewEncapsulation.None });
88
88
  }
89
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrVirtualScroll, decorators: [{
89
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrVirtualScroll, decorators: [{
90
90
  type: Component,
91
91
  args: [{ selector: 'wr-virtual-scroll', encapsulation: ViewEncapsulation.None, imports: [ScrollingModule, NgTemplateOutlet], host: { class: 'wr-virtual-scroll' }, template: "<cdk-virtual-scroll-viewport\n class=\"wr-virtual-scroll__viewport\"\n [itemSize]=\"itemSize()\"\n [minBufferPx]=\"resolvedMinBuffer()\"\n [maxBufferPx]=\"resolvedMaxBuffer()\"\n [style.height]=\"resolvedHeight()\"\n>\n <ng-container *cdkVirtualFor=\"let item of items(); let i = index; trackBy: trackBy()\">\n <ng-container *ngTemplateOutlet=\"rowTemplate(); context: { $implicit: item, index: i }\" />\n </ng-container>\n</cdk-virtual-scroll-viewport>\n", styles: [".wr-virtual-scroll{display:block;width:100%;overflow:hidden}.wr-virtual-scroll__viewport{width:100%;height:100%;scrollbar-width:thin}.wr-virtual-scroll__viewport::-webkit-scrollbar{width:.5rem;height:.5rem}.wr-virtual-scroll__viewport::-webkit-scrollbar-thumb{background:rgba(var(--wr-color-dark-rgb),.2);border-radius:999px}\n"] }]
92
92
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], itemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemSize", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], minBufferPx: [{ type: i0.Input, args: [{ isSignal: true, alias: "minBufferPx", required: false }] }], maxBufferPx: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxBufferPx", required: false }] }], trackBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackBy", required: false }] }], rowTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }], viewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }] } });
@@ -337,10 +337,10 @@ class WrWaves {
337
337
  mouse.set = true;
338
338
  }
339
339
  }
340
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrWaves, deps: [], target: i0.ɵɵFactoryTarget.Component });
341
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.2", type: WrWaves, isStandalone: true, selector: "wr-waves", inputs: { lineColor: { classPropertyName: "lineColor", publicName: "lineColor", isSignal: true, isRequired: false, transformFunction: null }, backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, waveSpeedX: { classPropertyName: "waveSpeedX", publicName: "waveSpeedX", isSignal: true, isRequired: false, transformFunction: null }, waveSpeedY: { classPropertyName: "waveSpeedY", publicName: "waveSpeedY", isSignal: true, isRequired: false, transformFunction: null }, waveAmpX: { classPropertyName: "waveAmpX", publicName: "waveAmpX", isSignal: true, isRequired: false, transformFunction: null }, waveAmpY: { classPropertyName: "waveAmpY", publicName: "waveAmpY", isSignal: true, isRequired: false, transformFunction: null }, xGap: { classPropertyName: "xGap", publicName: "xGap", isSignal: true, isRequired: false, transformFunction: null }, yGap: { classPropertyName: "yGap", publicName: "yGap", isSignal: true, isRequired: false, transformFunction: null }, friction: { classPropertyName: "friction", publicName: "friction", isSignal: true, isRequired: false, transformFunction: null }, tension: { classPropertyName: "tension", publicName: "tension", isSignal: true, isRequired: false, transformFunction: null }, maxCursorMove: { classPropertyName: "maxCursorMove", publicName: "maxCursorMove", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.background-color": "backgroundColor()" }, classAttribute: "wr-waves" }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvas"], descendants: true, isSignal: true }], ngImport: i0, template: '<canvas #canvas class="wr-waves__canvas"></canvas>', isInline: true, styles: [".wr-waves{--wr-waves-line-color: rgba(var(--wr-color-dark-rgb), .12);position:absolute;inset:0;display:block;margin:0;padding:0;overflow:hidden}.wr-waves__canvas{display:block;width:100%;height:100%}[data-theme=dark] .wr-waves{--wr-waves-line-color: rgb(255 255 255 / 14%)}\n"], encapsulation: i0.ViewEncapsulation.None });
340
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrWaves, deps: [], target: i0.ɵɵFactoryTarget.Component });
341
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.4", type: WrWaves, isStandalone: true, selector: "wr-waves", inputs: { lineColor: { classPropertyName: "lineColor", publicName: "lineColor", isSignal: true, isRequired: false, transformFunction: null }, backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, waveSpeedX: { classPropertyName: "waveSpeedX", publicName: "waveSpeedX", isSignal: true, isRequired: false, transformFunction: null }, waveSpeedY: { classPropertyName: "waveSpeedY", publicName: "waveSpeedY", isSignal: true, isRequired: false, transformFunction: null }, waveAmpX: { classPropertyName: "waveAmpX", publicName: "waveAmpX", isSignal: true, isRequired: false, transformFunction: null }, waveAmpY: { classPropertyName: "waveAmpY", publicName: "waveAmpY", isSignal: true, isRequired: false, transformFunction: null }, xGap: { classPropertyName: "xGap", publicName: "xGap", isSignal: true, isRequired: false, transformFunction: null }, yGap: { classPropertyName: "yGap", publicName: "yGap", isSignal: true, isRequired: false, transformFunction: null }, friction: { classPropertyName: "friction", publicName: "friction", isSignal: true, isRequired: false, transformFunction: null }, tension: { classPropertyName: "tension", publicName: "tension", isSignal: true, isRequired: false, transformFunction: null }, maxCursorMove: { classPropertyName: "maxCursorMove", publicName: "maxCursorMove", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.background-color": "backgroundColor()" }, classAttribute: "wr-waves" }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvas"], descendants: true, isSignal: true }], ngImport: i0, template: '<canvas #canvas class="wr-waves__canvas"></canvas>', isInline: true, styles: [".wr-waves{--wr-waves-line-color: rgba(var(--wr-color-dark-rgb), .12);position:absolute;inset:0;display:block;margin:0;padding:0;overflow:hidden}.wr-waves__canvas{display:block;width:100%;height:100%}[data-theme=dark] .wr-waves{--wr-waves-line-color: rgb(255 255 255 / 14%)}\n"], encapsulation: i0.ViewEncapsulation.None });
342
342
  }
343
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrWaves, decorators: [{
343
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrWaves, decorators: [{
344
344
  type: Component,
345
345
  args: [{ selector: 'wr-waves', template: '<canvas #canvas class="wr-waves__canvas"></canvas>', encapsulation: ViewEncapsulation.None, host: {
346
346
  class: 'wr-waves',
@@ -487,10 +487,10 @@ class WrWindow {
487
487
  this.x_.set(clamp(this.x_(), MIN_ON_VIEWPORT - w, vw - MIN_ON_VIEWPORT));
488
488
  this.y_.set(clamp(this.y_(), 0, vh - MIN_ON_VIEWPORT));
489
489
  }
490
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrWindow, deps: [], target: i0.ɵɵFactoryTarget.Component });
491
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: WrWindow, isStandalone: true, selector: "wr-window", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, initialX: { classPropertyName: "initialX", publicName: "initialX", isSignal: true, isRequired: false, transformFunction: null }, initialY: { classPropertyName: "initialY", publicName: "initialY", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, initialWidth: { classPropertyName: "initialWidth", publicName: "initialWidth", isSignal: true, isRequired: false, transformFunction: null }, initialHeight: { classPropertyName: "initialHeight", publicName: "initialHeight", isSignal: true, isRequired: false, transformFunction: null }, os: { classPropertyName: "os", publicName: "os", isSignal: true, isRequired: false, transformFunction: null }, chromeSize: { classPropertyName: "chromeSize", publicName: "chromeSize", isSignal: true, isRequired: false, transformFunction: null }, animations: { classPropertyName: "animations", publicName: "animations", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, movable: { classPropertyName: "movable", publicName: "movable", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, keepInViewport: { classPropertyName: "keepInViewport", publicName: "keepInViewport", isSignal: true, isRequired: false, transformFunction: null }, snap: { classPropertyName: "snap", publicName: "snap", isSignal: true, isRequired: false, transformFunction: null }, dragHandle: { classPropertyName: "dragHandle", publicName: "dragHandle", isSignal: true, isRequired: false, transformFunction: null }, showMinimize: { classPropertyName: "showMinimize", publicName: "showMinimize", isSignal: true, isRequired: false, transformFunction: null }, showMaximize: { classPropertyName: "showMaximize", publicName: "showMaximize", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", state: "stateChange", closed: "closed", moved: "moved", resized: "resized" }, host: { attributes: { "role": "dialog" }, listeners: { "pointerdown": "focusWindow()" }, properties: { "class": "classes()", "style.left.px": "x()", "style.top.px": "y()", "style.width.px": "width()", "style.height.px": "height()", "style.z-index": "z()", "attr.aria-hidden": "!open()", "attr.aria-labelledby": "titleId" } }, ngImport: i0, template: "<div class=\"wr-window__chrome\" (pointerdown)=\"startMove($event)\" (dblclick)=\"showMaximize() && maximize()\">\n <div class=\"wr-window__title\" [attr.id]=\"titleId\">{{ title() }}</div>\n <div class=\"wr-window__title-extra\">\n <ng-content select=\"[wrWindowTitleExtra]\" />\n </div>\n\n <div class=\"wr-window__chrome-actions\">\n @if (resolvedOs() === 'macos') {\n <!-- macOS-style traffic-light cluster: close \u2192 minimize \u2192 maximize.\n Glyphs (\u00D7, \u2212, +) appear on cluster hover. -->\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--close\"\n aria-label=\"Close\"\n (click)=\"close()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path\n d=\"M2.2 2.2 L7.8 7.8 M7.8 2.2 L2.2 7.8\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n }\n @if (showMinimize()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--minimize\"\n [attr.aria-label]=\"state() === 'minimized' ? 'Restore' : 'Minimize'\"\n (click)=\"minimize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <line x1=\"2\" y1=\"5\" x2=\"8\" y2=\"5\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n @if (showMaximize()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--maximize\"\n [attr.aria-label]=\"state() === 'maximized' ? 'Restore down' : 'Maximize'\"\n (click)=\"maximize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n @if (state() === 'maximized') {\n <path\n d=\"M3 1 L1 1 L1 3 M7 1 L9 1 L9 3 M1 7 L1 9 L3 9 M9 7 L9 9 L7 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n fill=\"none\"\n />\n } @else {\n <path d=\"M2 5 L8 5 M5 2 L5 8\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n }\n </svg>\n </button>\n }\n } @else {\n <!-- Windows / Linux glyph buttons -->\n @if (resolvedOs() !== 'linux' && showMinimize()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--minimize\"\n [attr.aria-label]=\"state() === 'minimized' ? 'Restore' : 'Minimize'\"\n (click)=\"minimize()\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <line x1=\"1\" y1=\"8\" x2=\"9\" y2=\"8\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n\n @if (resolvedOs() !== 'linux' && showMaximize()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--maximize\"\n [attr.aria-label]=\"state() === 'maximized' ? 'Restore down' : 'Maximize'\"\n (click)=\"maximize()\"\n >\n @if (state() === 'maximized') {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <rect x=\"1.5\" y=\"2.5\" width=\"6\" height=\"6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n <rect x=\"3\" y=\"1\" width=\"6\" height=\"6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n </svg>\n } @else {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <rect x=\"1\" y=\"1\" width=\"8\" height=\"8\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n </svg>\n }\n </button>\n }\n\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--close\"\n aria-label=\"Close\"\n (click)=\"close()\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M1 1 L9 9 M9 1 L1 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n }\n </div>\n</div>\n\n<div class=\"wr-window__body\">\n <ng-content />\n</div>\n\n<div class=\"wr-window__status-bar\">\n <ng-content select=\"[wrWindowStatusBar]\" />\n</div>\n\n@if (resizable() && state() === 'normal') {\n <span class=\"wr-window__handle wr-window__handle--t\" (pointerdown)=\"resizeT($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--r\" (pointerdown)=\"resizeR($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--b\" (pointerdown)=\"resizeB($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--l\" (pointerdown)=\"resizeL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--tl\" (pointerdown)=\"resizeTL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--tr\" (pointerdown)=\"resizeTR($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--bl\" (pointerdown)=\"resizeBL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--br\" (pointerdown)=\"resizeBR($event)\"></span>\n}\n", encapsulation: i0.ViewEncapsulation.None });
490
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrWindow, deps: [], target: i0.ɵɵFactoryTarget.Component });
491
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: WrWindow, isStandalone: true, selector: "wr-window", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, initialX: { classPropertyName: "initialX", publicName: "initialX", isSignal: true, isRequired: false, transformFunction: null }, initialY: { classPropertyName: "initialY", publicName: "initialY", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, initialWidth: { classPropertyName: "initialWidth", publicName: "initialWidth", isSignal: true, isRequired: false, transformFunction: null }, initialHeight: { classPropertyName: "initialHeight", publicName: "initialHeight", isSignal: true, isRequired: false, transformFunction: null }, os: { classPropertyName: "os", publicName: "os", isSignal: true, isRequired: false, transformFunction: null }, chromeSize: { classPropertyName: "chromeSize", publicName: "chromeSize", isSignal: true, isRequired: false, transformFunction: null }, animations: { classPropertyName: "animations", publicName: "animations", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, movable: { classPropertyName: "movable", publicName: "movable", isSignal: true, isRequired: false, transformFunction: null }, resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, keepInViewport: { classPropertyName: "keepInViewport", publicName: "keepInViewport", isSignal: true, isRequired: false, transformFunction: null }, snap: { classPropertyName: "snap", publicName: "snap", isSignal: true, isRequired: false, transformFunction: null }, dragHandle: { classPropertyName: "dragHandle", publicName: "dragHandle", isSignal: true, isRequired: false, transformFunction: null }, showMinimize: { classPropertyName: "showMinimize", publicName: "showMinimize", isSignal: true, isRequired: false, transformFunction: null }, showMaximize: { classPropertyName: "showMaximize", publicName: "showMaximize", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", state: "stateChange", closed: "closed", moved: "moved", resized: "resized" }, host: { attributes: { "role": "dialog" }, listeners: { "pointerdown": "focusWindow()" }, properties: { "class": "classes()", "style.left.px": "x()", "style.top.px": "y()", "style.width.px": "width()", "style.height.px": "height()", "style.z-index": "z()", "attr.aria-hidden": "!open()", "attr.aria-labelledby": "titleId" } }, ngImport: i0, template: "<div class=\"wr-window__chrome\" (pointerdown)=\"startMove($event)\" (dblclick)=\"showMaximize() && maximize()\">\n <div class=\"wr-window__title\" [attr.id]=\"titleId\">{{ title() }}</div>\n <div class=\"wr-window__title-extra\">\n <ng-content select=\"[wrWindowTitleExtra]\" />\n </div>\n\n <div class=\"wr-window__chrome-actions\">\n @if (resolvedOs() === 'macos') {\n <!-- macOS-style traffic-light cluster: close \u2192 minimize \u2192 maximize.\n Glyphs (\u00D7, \u2212, +) appear on cluster hover. -->\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--close\"\n aria-label=\"Close\"\n (click)=\"close()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path\n d=\"M2.2 2.2 L7.8 7.8 M7.8 2.2 L2.2 7.8\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n }\n @if (showMinimize()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--minimize\"\n [attr.aria-label]=\"state() === 'minimized' ? 'Restore' : 'Minimize'\"\n (click)=\"minimize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <line x1=\"2\" y1=\"5\" x2=\"8\" y2=\"5\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n @if (showMaximize()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--maximize\"\n [attr.aria-label]=\"state() === 'maximized' ? 'Restore down' : 'Maximize'\"\n (click)=\"maximize()\"\n >\n <svg class=\"wr-window__chrome-action-glyph\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n @if (state() === 'maximized') {\n <path\n d=\"M3 1 L1 1 L1 3 M7 1 L9 1 L9 3 M1 7 L1 9 L3 9 M9 7 L9 9 L7 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linecap=\"round\"\n fill=\"none\"\n />\n } @else {\n <path d=\"M2 5 L8 5 M5 2 L5 8\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n }\n </svg>\n </button>\n }\n } @else {\n <!-- Windows / Linux glyph buttons -->\n @if (resolvedOs() !== 'linux' && showMinimize()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--minimize\"\n [attr.aria-label]=\"state() === 'minimized' ? 'Restore' : 'Minimize'\"\n (click)=\"minimize()\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <line x1=\"1\" y1=\"8\" x2=\"9\" y2=\"8\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n\n @if (resolvedOs() !== 'linux' && showMaximize()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--maximize\"\n [attr.aria-label]=\"state() === 'maximized' ? 'Restore down' : 'Maximize'\"\n (click)=\"maximize()\"\n >\n @if (state() === 'maximized') {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <rect x=\"1.5\" y=\"2.5\" width=\"6\" height=\"6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n <rect x=\"3\" y=\"1\" width=\"6\" height=\"6\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n </svg>\n } @else {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <rect x=\"1\" y=\"1\" width=\"8\" height=\"8\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n </svg>\n }\n </button>\n }\n\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"wr-window__chrome-action wr-window__chrome-action--close\"\n aria-label=\"Close\"\n (click)=\"close()\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M1 1 L9 9 M9 1 L1 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </button>\n }\n }\n </div>\n</div>\n\n<div class=\"wr-window__body\">\n <ng-content />\n</div>\n\n<div class=\"wr-window__status-bar\">\n <ng-content select=\"[wrWindowStatusBar]\" />\n</div>\n\n@if (resizable() && state() === 'normal') {\n <span class=\"wr-window__handle wr-window__handle--t\" (pointerdown)=\"resizeT($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--r\" (pointerdown)=\"resizeR($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--b\" (pointerdown)=\"resizeB($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--l\" (pointerdown)=\"resizeL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--tl\" (pointerdown)=\"resizeTL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--tr\" (pointerdown)=\"resizeTR($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--bl\" (pointerdown)=\"resizeBL($event)\"></span>\n <span class=\"wr-window__handle wr-window__handle--br\" (pointerdown)=\"resizeBR($event)\"></span>\n}\n", encapsulation: i0.ViewEncapsulation.None });
492
492
  }
493
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrWindow, decorators: [{
493
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrWindow, decorators: [{
494
494
  type: Component,
495
495
  args: [{ selector: 'wr-window', encapsulation: ViewEncapsulation.None, host: {
496
496
  role: 'dialog',
@@ -639,10 +639,10 @@ class WrWindowContainer {
639
639
  });
640
640
  });
641
641
  }
642
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrWindowContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
643
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: WrWindowContainer, isStandalone: true, selector: "wr-window-container", viewQueries: [{ propertyName: "contentVcr", first: true, predicate: ["content"], descendants: true, read: ViewContainerRef, isSignal: true }, { propertyName: "wrWindow", first: true, predicate: WrWindow, descendants: true, isSignal: true }], ngImport: i0, template: "<wr-window\n [open]=\"true\"\n [title]=\"ref.title()\"\n [os]=\"config.os ?? 'auto'\"\n [size]=\"config.size ?? 'md'\"\n [chromeSize]=\"config.chromeSize ?? 'normal'\"\n [animations]=\"config.animations ?? true\"\n [initialX]=\"config.x ?? null\"\n [initialY]=\"config.y ?? null\"\n [initialWidth]=\"config.width ?? null\"\n [initialHeight]=\"config.height ?? null\"\n [minWidth]=\"config.minWidth ?? 220\"\n [minHeight]=\"config.minHeight ?? 140\"\n [maxWidth]=\"config.maxWidth ?? 1000000\"\n [maxHeight]=\"config.maxHeight ?? 1000000\"\n [movable]=\"config.movable ?? true\"\n [resizable]=\"config.resizable ?? true\"\n [keepInViewport]=\"config.keepInViewport ?? true\"\n [snap]=\"config.snap ?? 'none'\"\n [dragHandle]=\"config.dragHandle ?? null\"\n [showMinimize]=\"config.showMinimize ?? true\"\n [showMaximize]=\"config.showMaximize ?? true\"\n [showClose]=\"config.showClose ?? true\"\n (closed)=\"ref.close()\"\n #window\n>\n <ng-container #content />\n</wr-window>\n\n@if (window.snapTarget(); as target) {\n <div class=\"wr-window__snap-hint\" [attr.data-target]=\"target\" aria-hidden=\"true\"></div>\n}\n", dependencies: [{ kind: "component", type: WrWindow, selector: "wr-window", inputs: ["open", "state", "title", "initialX", "initialY", "size", "initialWidth", "initialHeight", "os", "chromeSize", "animations", "minWidth", "minHeight", "maxWidth", "maxHeight", "movable", "resizable", "keepInViewport", "snap", "dragHandle", "showMinimize", "showMaximize", "showClose"], outputs: ["openChange", "stateChange", "closed", "moved", "resized"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
642
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrWindowContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
643
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: WrWindowContainer, isStandalone: true, selector: "wr-window-container", viewQueries: [{ propertyName: "contentVcr", first: true, predicate: ["content"], descendants: true, read: ViewContainerRef, isSignal: true }, { propertyName: "wrWindow", first: true, predicate: WrWindow, descendants: true, isSignal: true }], ngImport: i0, template: "<wr-window\n [open]=\"true\"\n [title]=\"ref.title()\"\n [os]=\"config.os ?? 'auto'\"\n [size]=\"config.size ?? 'md'\"\n [chromeSize]=\"config.chromeSize ?? 'normal'\"\n [animations]=\"config.animations ?? true\"\n [initialX]=\"config.x ?? null\"\n [initialY]=\"config.y ?? null\"\n [initialWidth]=\"config.width ?? null\"\n [initialHeight]=\"config.height ?? null\"\n [minWidth]=\"config.minWidth ?? 220\"\n [minHeight]=\"config.minHeight ?? 140\"\n [maxWidth]=\"config.maxWidth ?? 1000000\"\n [maxHeight]=\"config.maxHeight ?? 1000000\"\n [movable]=\"config.movable ?? true\"\n [resizable]=\"config.resizable ?? true\"\n [keepInViewport]=\"config.keepInViewport ?? true\"\n [snap]=\"config.snap ?? 'none'\"\n [dragHandle]=\"config.dragHandle ?? null\"\n [showMinimize]=\"config.showMinimize ?? true\"\n [showMaximize]=\"config.showMaximize ?? true\"\n [showClose]=\"config.showClose ?? true\"\n (closed)=\"ref.close()\"\n #window\n>\n <ng-container #content />\n</wr-window>\n\n@if (window.snapTarget(); as target) {\n <div class=\"wr-window__snap-hint\" [attr.data-target]=\"target\" aria-hidden=\"true\"></div>\n}\n", dependencies: [{ kind: "component", type: WrWindow, selector: "wr-window", inputs: ["open", "state", "title", "initialX", "initialY", "size", "initialWidth", "initialHeight", "os", "chromeSize", "animations", "minWidth", "minHeight", "maxWidth", "maxHeight", "movable", "resizable", "keepInViewport", "snap", "dragHandle", "showMinimize", "showMaximize", "showClose"], outputs: ["openChange", "stateChange", "closed", "moved", "resized"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
644
644
  }
645
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrWindowContainer, decorators: [{
645
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrWindowContainer, decorators: [{
646
646
  type: Component,
647
647
  args: [{ selector: 'wr-window-container', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [WrWindow], template: "<wr-window\n [open]=\"true\"\n [title]=\"ref.title()\"\n [os]=\"config.os ?? 'auto'\"\n [size]=\"config.size ?? 'md'\"\n [chromeSize]=\"config.chromeSize ?? 'normal'\"\n [animations]=\"config.animations ?? true\"\n [initialX]=\"config.x ?? null\"\n [initialY]=\"config.y ?? null\"\n [initialWidth]=\"config.width ?? null\"\n [initialHeight]=\"config.height ?? null\"\n [minWidth]=\"config.minWidth ?? 220\"\n [minHeight]=\"config.minHeight ?? 140\"\n [maxWidth]=\"config.maxWidth ?? 1000000\"\n [maxHeight]=\"config.maxHeight ?? 1000000\"\n [movable]=\"config.movable ?? true\"\n [resizable]=\"config.resizable ?? true\"\n [keepInViewport]=\"config.keepInViewport ?? true\"\n [snap]=\"config.snap ?? 'none'\"\n [dragHandle]=\"config.dragHandle ?? null\"\n [showMinimize]=\"config.showMinimize ?? true\"\n [showMaximize]=\"config.showMaximize ?? true\"\n [showClose]=\"config.showClose ?? true\"\n (closed)=\"ref.close()\"\n #window\n>\n <ng-container #content />\n</wr-window>\n\n@if (window.snapTarget(); as target) {\n <div class=\"wr-window__snap-hint\" [attr.data-target]=\"target\" aria-hidden=\"true\"></div>\n}\n" }]
648
648
  }], ctorParameters: () => [], propDecorators: { contentVcr: [{ type: i0.ViewChild, args: ['content', { ...{ read: ViewContainerRef }, isSignal: true }] }], wrWindow: [{ type: i0.ViewChild, args: [i0.forwardRef(() => WrWindow), { isSignal: true }] }] } });
@@ -1073,10 +1073,10 @@ class WrWindowManager {
1073
1073
  clearLayout(name) {
1074
1074
  this.storage.remove(this.layoutKey(name));
1075
1075
  }
1076
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrWindowManager, deps: [], target: i0.ɵɵFactoryTarget.Service });
1077
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.2", ngImport: i0, type: WrWindowManager });
1076
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrWindowManager, deps: [], target: i0.ɵɵFactoryTarget.Service });
1077
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.4", ngImport: i0, type: WrWindowManager });
1078
1078
  }
1079
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrWindowManager, decorators: [{
1079
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrWindowManager, decorators: [{
1080
1080
  type: Service
1081
1081
  }] });
1082
1082
 
@@ -1121,10 +1121,10 @@ class WrWindowTaskbar {
1121
1121
  event.stopPropagation();
1122
1122
  void ref.close();
1123
1123
  }
1124
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrWindowTaskbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
1125
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: WrWindowTaskbar, isStandalone: true, selector: "wr-window-taskbar", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "toolbar", "aria-label": "Minimized windows" }, properties: { "class": "classes()" } }, ngImport: i0, template: "@if (items().length > 0) {\n <div class=\"wr-window-taskbar__rail\">\n @for (ref of items(); track ref.id) {\n <button\n type=\"button\"\n class=\"wr-window-taskbar__tab\"\n [attr.aria-label]=\"`Restore ${ref.title() || 'Untitled'}`\"\n (click)=\"restore(ref)\"\n >\n <span class=\"wr-window-taskbar__tab-title\">{{ ref.title() || 'Untitled' }}</span>\n <span\n class=\"wr-window-taskbar__tab-close\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Close window\"\n (click)=\"close(ref, $event)\"\n (keydown.enter)=\"close(ref, $event)\"\n >\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M1 1 L9 9 M9 1 L1 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </span>\n </button>\n }\n </div>\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1124
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrWindowTaskbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
1125
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: WrWindowTaskbar, isStandalone: true, selector: "wr-window-taskbar", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "toolbar", "aria-label": "Minimized windows" }, properties: { "class": "classes()" } }, ngImport: i0, template: "@if (items().length > 0) {\n <div class=\"wr-window-taskbar__rail\">\n @for (ref of items(); track ref.id) {\n <button\n type=\"button\"\n class=\"wr-window-taskbar__tab\"\n [attr.aria-label]=\"`Restore ${ref.title() || 'Untitled'}`\"\n (click)=\"restore(ref)\"\n >\n <span class=\"wr-window-taskbar__tab-title\">{{ ref.title() || 'Untitled' }}</span>\n <span\n class=\"wr-window-taskbar__tab-close\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Close window\"\n (click)=\"close(ref, $event)\"\n (keydown.enter)=\"close(ref, $event)\"\n >\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M1 1 L9 9 M9 1 L1 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </span>\n </button>\n }\n </div>\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1126
1126
  }
1127
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrWindowTaskbar, decorators: [{
1127
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: WrWindowTaskbar, decorators: [{
1128
1128
  type: Component,
1129
1129
  args: [{ selector: 'wr-window-taskbar', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()', role: 'toolbar', 'aria-label': 'Minimized windows' }, template: "@if (items().length > 0) {\n <div class=\"wr-window-taskbar__rail\">\n @for (ref of items(); track ref.id) {\n <button\n type=\"button\"\n class=\"wr-window-taskbar__tab\"\n [attr.aria-label]=\"`Restore ${ref.title() || 'Untitled'}`\"\n (click)=\"restore(ref)\"\n >\n <span class=\"wr-window-taskbar__tab-title\">{{ ref.title() || 'Untitled' }}</span>\n <span\n class=\"wr-window-taskbar__tab-close\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Close window\"\n (click)=\"close(ref, $event)\"\n (keydown.enter)=\"close(ref, $event)\"\n >\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M1 1 L9 9 M9 1 L1 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </span>\n </button>\n }\n </div>\n}\n" }]
1130
1130
  }], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }] } });
@@ -57,7 +57,7 @@
57
57
  display: flex;
58
58
  flex-direction: column;
59
59
  gap: 0.125rem;
60
- font-size: 0.875rem;
60
+ font-size: var(--wr-text-sm);
61
61
  line-height: 1.25rem;
62
62
 
63
63
  strong {
@@ -72,7 +72,7 @@
72
72
  small {
73
73
  margin-top: 0.25rem;
74
74
  color: var(--wr-color-medium);
75
- font-size: 0.75rem;
75
+ font-size: var(--wr-text-xs);
76
76
  }
77
77
  }
78
78
 
@@ -106,7 +106,7 @@
106
106
  background: var(--wr-color-white);
107
107
  border: 1px solid var(--wr-color-light);
108
108
  @include theme.smooth-br(var(--wr-border-radius-base));
109
- font-size: 0.875rem;
109
+ font-size: var(--wr-text-sm);
110
110
  line-height: 1.25rem;
111
111
  }
112
112
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  > label {
10
10
  color: var(--wr-color-medium);
11
- font-size: 0.8125rem;
11
+ font-size: var(--wr-text-sm);
12
12
  font-weight: 500;
13
13
  line-height: 1.25rem;
14
14
  transition: color var(--wr-transition-base);
@@ -30,7 +30,7 @@
30
30
  .wr-form-error {
31
31
  display: block;
32
32
  color: var(--wr-color-danger);
33
- font-size: 0.75rem;
33
+ font-size: var(--wr-text-xs);
34
34
  line-height: 1rem;
35
35
  }
36
36
 
@@ -45,7 +45,7 @@
45
45
  align-items: center;
46
46
  gap: 0.25rem;
47
47
  color: var(--wr-color-dark);
48
- font-size: 0.875rem;
48
+ font-size: var(--wr-text-sm);
49
49
  font-weight: 500;
50
50
  line-height: 1.25rem;
51
51
  }
@@ -57,7 +57,7 @@
57
57
  &__optional {
58
58
  color: var(--wr-color-medium);
59
59
  font-weight: 400;
60
- font-size: 0.8125rem;
60
+ font-size: var(--wr-text-sm);
61
61
  }
62
62
 
63
63
  &__control {
@@ -79,7 +79,7 @@
79
79
 
80
80
  &__error {
81
81
  color: var(--wr-color-danger);
82
- font-size: 0.8125rem;
82
+ font-size: var(--wr-text-sm);
83
83
  line-height: 1.25;
84
84
  }
85
85
 
@@ -5,11 +5,8 @@
5
5
  .wr-glitch-text {
6
6
  --wr-glitch-text-before-duration: 2s;
7
7
  --wr-glitch-text-after-duration: 3s;
8
- --wr-glitch-text-before-shadow: 5px 0 cyan;
9
- --wr-glitch-text-after-shadow: -5px 0 red;
10
- // Clone backgrounds must match the page surface for the slicing
11
- // illusion; the text itself uses the readable foreground token.
12
- --wr-glitch-text-bg: var(--wr-color-white, #fff);
8
+ --wr-glitch-text-before-shadow: 5px 0 var(--wr-color-info);
9
+ --wr-glitch-text-after-shadow: -5px 0 var(--wr-color-danger);
13
10
 
14
11
  position: relative;
15
12
  display: inline-block;
@@ -24,7 +21,7 @@
24
21
  position: absolute;
25
22
  top: 0;
26
23
  color: inherit;
27
- background-color: var(--wr-glitch-text-bg);
24
+ background-color: var(--wr-glitch-text-bg, transparent);
28
25
  overflow: hidden;
29
26
  clip-path: inset(0 0 0 0);
30
27
  }
@@ -25,7 +25,7 @@
25
25
  &__backdrop {
26
26
  position: absolute;
27
27
  inset: 0;
28
- background: rgba(var(--wr-color-backdrop-rgb), 0.5);
28
+ background: var(--wr-color-overlay);
29
29
  pointer-events: none;
30
30
  }
31
31
 
@@ -44,7 +44,7 @@
44
44
  background: var(--wr-color-white);
45
45
  border: 1px solid var(--wr-color-primary);
46
46
  border-radius: 50%;
47
- box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15);
47
+ box-shadow: 0 0 0 1px rgba(var(--wr-color-black-rgb), 0.15);
48
48
  box-sizing: border-box;
49
49
 
50
50
  // Position each handle by its edge / corner.
@@ -107,7 +107,7 @@
107
107
  padding: 2rem;
108
108
  text-align: center;
109
109
  color: var(--wr-color-medium);
110
- background: rgba(var(--wr-color-light-rgb), 0.4);
110
+ background: var(--wr-color-hover);
111
111
  border: 1px dashed var(--wr-color-light);
112
112
  @include theme.smooth-br(var(--wr-border-radius-base));
113
113
  }
@@ -10,12 +10,12 @@
10
10
  --wr-input-placeholder: rgba(var(--wr-color-medium-rgb), 0.7);
11
11
  --wr-input-bg: var(--wr-color-white);
12
12
  --wr-input-border: var(--wr-color-light);
13
- --wr-input-radius: var(--wr-border-radius-base);
13
+ --wr-input-radius: var(--wr-control-radius-md);
14
14
  --wr-input-ring: transparent;
15
- --wr-input-padding-y: 0.4375rem;
16
- --wr-input-padding-x: 0.75rem;
17
- --wr-input-font-size: 0.875rem;
18
- --wr-input-line-height: 1.25rem;
15
+ --wr-input-padding-y: var(--wr-control-padding-y-md);
16
+ --wr-input-padding-x: var(--wr-control-padding-x-md);
17
+ --wr-input-font-size: var(--wr-control-font-size-md);
18
+ --wr-input-line-height: var(--wr-control-line-height-md);
19
19
 
20
20
  display: inline-block;
21
21
  width: 100%;
@@ -57,6 +57,25 @@
57
57
  cursor: not-allowed;
58
58
  }
59
59
 
60
+ // Sizes — share the `--wr-control-*` contract (22 / 30 / 36 px). Declared
61
+ // before `--rounded` so the pill modifier's radius / padding-x still win
62
+ // when both classes are present.
63
+ &--sm {
64
+ --wr-input-radius: var(--wr-control-radius-sm);
65
+ --wr-input-padding-y: var(--wr-control-padding-y-sm);
66
+ --wr-input-padding-x: var(--wr-control-padding-x-sm);
67
+ --wr-input-font-size: var(--wr-control-font-size-sm);
68
+ --wr-input-line-height: var(--wr-control-line-height-sm);
69
+ }
70
+
71
+ &--lg {
72
+ --wr-input-radius: var(--wr-control-radius-lg);
73
+ --wr-input-padding-y: var(--wr-control-padding-y-lg);
74
+ --wr-input-padding-x: var(--wr-control-padding-x-lg);
75
+ --wr-input-font-size: var(--wr-control-font-size-lg);
76
+ --wr-input-line-height: var(--wr-control-line-height-lg);
77
+ }
78
+
60
79
  &--rounded {
61
80
  --wr-input-radius: var(--wr-border-radius-pill);
62
81
  --wr-input-padding-x: 1rem;
@@ -70,7 +89,7 @@
70
89
  // `[wrInputPrefix]` / `[wrInputSuffix]` / `<wr-password-toggle>` siblings.
71
90
  //
72
91
  .wr-input-group {
73
- --wr-input-group-radius: var(--wr-border-radius-base);
92
+ --wr-input-group-radius: var(--wr-control-radius-md);
74
93
  --wr-input-group-bg: var(--wr-color-white);
75
94
  --wr-input-group-border: var(--wr-color-light);
76
95
  --wr-input-group-ring: transparent;
@@ -120,7 +139,7 @@
120
139
  user-select: none;
121
140
  font-weight: 500;
122
141
  font-family: var(--wr-font-family-base);
123
- font-size: 0.875rem;
142
+ font-size: var(--wr-text-sm);
124
143
  line-height: 1.25rem;
125
144
  }
126
145
 
@@ -5,11 +5,14 @@
5
5
  --wr-input-otp-border: var(--wr-color-light);
6
6
  --wr-input-otp-color: var(--wr-color-dark);
7
7
  --wr-input-otp-focus: var(--wr-color-primary);
8
- --wr-input-otp-size: 2.75rem;
8
+ --wr-input-otp-size: 2.5rem; // md cell (40px)
9
+ --wr-input-otp-font: var(--wr-text-lg); // 18px
10
+ --wr-input-otp-radius: var(--wr-control-radius-md);
11
+ --wr-input-otp-gap: 0.5rem;
9
12
 
10
13
  display: inline-flex;
11
14
  align-items: center;
12
- gap: 0.5rem;
15
+ gap: var(--wr-input-otp-gap);
13
16
  font-family: var(--wr-font-family-base);
14
17
 
15
18
  &__cell {
@@ -18,20 +21,20 @@
18
21
  padding: 0;
19
22
  text-align: center;
20
23
  font-family: var(--wr-font-family-mono, monospace);
21
- font-size: 1.125rem;
24
+ font-size: var(--wr-input-otp-font);
22
25
  font-weight: 500;
23
26
  line-height: 1;
24
27
  color: var(--wr-input-otp-color);
25
28
  background: var(--wr-input-otp-bg);
26
29
  border: 1px solid var(--wr-input-otp-border);
27
- @include theme.smooth-br(var(--wr-border-radius-base));
30
+ @include theme.smooth-br(var(--wr-input-otp-radius));
28
31
  appearance: none;
29
32
  transition:
30
33
  border-color var(--wr-transition-base),
31
34
  box-shadow var(--wr-transition-base);
32
35
 
33
36
  &::placeholder {
34
- color: rgba(var(--wr-color-medium-rgb), 0.5);
37
+ color: var(--wr-color-text-faint);
35
38
  }
36
39
 
37
40
  &:focus {
@@ -47,6 +50,21 @@
47
50
  }
48
51
  }
49
52
 
53
+ // Sizes — cell, digit font, radius + gap scale together.
54
+ &--sm {
55
+ --wr-input-otp-size: 2rem; // 32px
56
+ --wr-input-otp-font: var(--wr-text-base); // 16px
57
+ --wr-input-otp-radius: var(--wr-control-radius-sm);
58
+ --wr-input-otp-gap: 0.375rem;
59
+ }
60
+
61
+ &--lg {
62
+ --wr-input-otp-size: 3rem; // 48px
63
+ --wr-input-otp-font: var(--wr-text-xl); // 20px
64
+ --wr-input-otp-radius: var(--wr-control-radius-lg);
65
+ --wr-input-otp-gap: 0.625rem;
66
+ }
67
+
50
68
  &--disabled {
51
69
  opacity: 0.7;
52
70
  }