ngwr 14.7.0 → 14.9.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 (482) hide show
  1. package/README.md +66 -332
  2. package/alert/styles/_index.scss +10 -0
  3. package/avatar/styles/_index.scss +18 -7
  4. package/badge/styles/_index.scss +7 -0
  5. package/badge/styles/_tag.scss +7 -1
  6. package/bar-chart/styles/_index.scss +1 -0
  7. package/button/styles/_index.scss +6 -0
  8. package/calendar-heatmap/styles/_index.scss +1 -0
  9. package/cascader/styles/_rules.scss +87 -15
  10. package/checkbox/styles/_index.scss +4 -0
  11. package/command-palette/styles/_index.scss +1 -1
  12. package/date-picker/styles/_index.scss +30 -0
  13. package/density/styles/_index.scss +4 -2
  14. package/divider/styles/_index.scss +2 -0
  15. package/donut-chart/styles/_index.scss +10 -0
  16. package/dropdown/styles/_index.scss +67 -5
  17. package/editor/styles/_index.scss +441 -0
  18. package/event-calendar/styles/_index.scss +209 -35
  19. package/fesm2022/ngwr-action-sheet-testing.mjs.map +1 -1
  20. package/fesm2022/ngwr-action-sheet.mjs +3 -3
  21. package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
  22. package/fesm2022/ngwr-affix.mjs +3 -3
  23. package/fesm2022/ngwr-affix.mjs.map +1 -1
  24. package/fesm2022/ngwr-alert.mjs +3 -3
  25. package/fesm2022/ngwr-alert.mjs.map +1 -1
  26. package/fesm2022/ngwr-anchor.mjs +3 -3
  27. package/fesm2022/ngwr-anchor.mjs.map +1 -1
  28. package/fesm2022/ngwr-aurora.mjs +3 -3
  29. package/fesm2022/ngwr-aurora.mjs.map +1 -1
  30. package/fesm2022/ngwr-avatar.mjs +3 -3
  31. package/fesm2022/ngwr-avatar.mjs.map +1 -1
  32. package/fesm2022/ngwr-back-top.mjs +3 -3
  33. package/fesm2022/ngwr-back-top.mjs.map +1 -1
  34. package/fesm2022/ngwr-badge.mjs +28 -13
  35. package/fesm2022/ngwr-badge.mjs.map +1 -1
  36. package/fesm2022/ngwr-bar-chart-testing.mjs.map +1 -1
  37. package/fesm2022/ngwr-bar-chart.mjs +31 -6
  38. package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
  39. package/fesm2022/ngwr-blur-text-testing.mjs.map +1 -1
  40. package/fesm2022/ngwr-blur-text.mjs +3 -3
  41. package/fesm2022/ngwr-blur-text.mjs.map +1 -1
  42. package/fesm2022/ngwr-border-glow-testing.mjs.map +1 -1
  43. package/fesm2022/ngwr-border-glow.mjs +3 -3
  44. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  45. package/fesm2022/ngwr-breadcrumbs.mjs +6 -6
  46. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  47. package/fesm2022/ngwr-burger.mjs +3 -3
  48. package/fesm2022/ngwr-burger.mjs.map +1 -1
  49. package/fesm2022/ngwr-button-testing.mjs.map +1 -1
  50. package/fesm2022/ngwr-button.mjs +6 -6
  51. package/fesm2022/ngwr-button.mjs.map +1 -1
  52. package/fesm2022/ngwr-calendar-heatmap-testing.mjs.map +1 -1
  53. package/fesm2022/ngwr-calendar-heatmap.mjs +61 -6
  54. package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
  55. package/fesm2022/ngwr-calendar-testing.mjs.map +1 -1
  56. package/fesm2022/ngwr-calendar.mjs +3 -3
  57. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  58. package/fesm2022/ngwr-card.mjs +9 -9
  59. package/fesm2022/ngwr-card.mjs.map +1 -1
  60. package/fesm2022/ngwr-carousel-testing.mjs.map +1 -1
  61. package/fesm2022/ngwr-carousel.mjs +6 -6
  62. package/fesm2022/ngwr-carousel.mjs.map +1 -1
  63. package/fesm2022/ngwr-cascader-testing.mjs.map +1 -1
  64. package/fesm2022/ngwr-cascader.mjs +4 -4
  65. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  66. package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -1
  67. package/fesm2022/ngwr-checkbox.mjs +18 -8
  68. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  69. package/fesm2022/ngwr-circular-text-testing.mjs.map +1 -1
  70. package/fesm2022/ngwr-circular-text.mjs +3 -3
  71. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  72. package/fesm2022/ngwr-click-spark.mjs +3 -3
  73. package/fesm2022/ngwr-click-spark.mjs.map +1 -1
  74. package/fesm2022/ngwr-clipboard.mjs +3 -3
  75. package/fesm2022/ngwr-clipboard.mjs.map +1 -1
  76. package/fesm2022/ngwr-collapse-testing.mjs.map +1 -1
  77. package/fesm2022/ngwr-collapse.mjs +9 -9
  78. package/fesm2022/ngwr-collapse.mjs.map +1 -1
  79. package/fesm2022/ngwr-color-picker-testing.mjs.map +1 -1
  80. package/fesm2022/ngwr-color-picker.mjs +6 -6
  81. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  82. package/fesm2022/ngwr-command-palette-testing.mjs.map +1 -1
  83. package/fesm2022/ngwr-command-palette.mjs +3 -3
  84. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  85. package/fesm2022/ngwr-compare.mjs +3 -3
  86. package/fesm2022/ngwr-compare.mjs.map +1 -1
  87. package/fesm2022/ngwr-confetti.mjs +3 -3
  88. package/fesm2022/ngwr-confetti.mjs.map +1 -1
  89. package/fesm2022/ngwr-config.mjs.map +1 -1
  90. package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -1
  91. package/fesm2022/ngwr-context-menu.mjs +12 -12
  92. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  93. package/fesm2022/ngwr-cookie.mjs +3 -3
  94. package/fesm2022/ngwr-cookie.mjs.map +1 -1
  95. package/fesm2022/ngwr-counter.mjs +6 -6
  96. package/fesm2022/ngwr-counter.mjs.map +1 -1
  97. package/fesm2022/ngwr-date-adapters-fns.mjs +3 -3
  98. package/fesm2022/ngwr-date-adapters-fns.mjs.map +1 -1
  99. package/fesm2022/ngwr-date-adapters-luxon.mjs +3 -3
  100. package/fesm2022/ngwr-date-adapters-luxon.mjs.map +1 -1
  101. package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -1
  102. package/fesm2022/ngwr-date-picker.mjs +721 -62
  103. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  104. package/fesm2022/ngwr-date.mjs +3 -3
  105. package/fesm2022/ngwr-date.mjs.map +1 -1
  106. package/fesm2022/ngwr-decrypt-text-testing.mjs.map +1 -1
  107. package/fesm2022/ngwr-decrypt-text.mjs +3 -3
  108. package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
  109. package/fesm2022/ngwr-density.mjs +6 -6
  110. package/fesm2022/ngwr-density.mjs.map +1 -1
  111. package/fesm2022/ngwr-descriptions.mjs +6 -6
  112. package/fesm2022/ngwr-descriptions.mjs.map +1 -1
  113. package/fesm2022/ngwr-dialog-testing.mjs.map +1 -1
  114. package/fesm2022/ngwr-dialog.mjs +15 -15
  115. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  116. package/fesm2022/ngwr-directives.mjs +12 -12
  117. package/fesm2022/ngwr-directives.mjs.map +1 -1
  118. package/fesm2022/ngwr-divider.mjs +3 -3
  119. package/fesm2022/ngwr-divider.mjs.map +1 -1
  120. package/fesm2022/ngwr-donut-chart-testing.mjs.map +1 -1
  121. package/fesm2022/ngwr-donut-chart.mjs +48 -6
  122. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  123. package/fesm2022/ngwr-drag-drop.mjs +6 -6
  124. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  125. package/fesm2022/ngwr-drawer-testing.mjs.map +1 -1
  126. package/fesm2022/ngwr-drawer.mjs +18 -18
  127. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  128. package/fesm2022/ngwr-dropdown-testing.mjs.map +1 -1
  129. package/fesm2022/ngwr-dropdown.mjs +174 -25
  130. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  131. package/fesm2022/ngwr-editor-testing.mjs +568 -0
  132. package/fesm2022/ngwr-editor-testing.mjs.map +1 -0
  133. package/fesm2022/ngwr-editor.mjs +2601 -0
  134. package/fesm2022/ngwr-editor.mjs.map +1 -0
  135. package/fesm2022/ngwr-empty.mjs +3 -3
  136. package/fesm2022/ngwr-empty.mjs.map +1 -1
  137. package/fesm2022/ngwr-event-calendar-testing.mjs.map +1 -1
  138. package/fesm2022/ngwr-event-calendar.mjs +14 -7
  139. package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
  140. package/fesm2022/ngwr-falling-text-testing.mjs.map +1 -1
  141. package/fesm2022/ngwr-falling-text.mjs +3 -3
  142. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  143. package/fesm2022/ngwr-file-upload-testing.mjs.map +1 -1
  144. package/fesm2022/ngwr-file-upload.mjs +3 -3
  145. package/fesm2022/ngwr-file-upload.mjs.map +1 -1
  146. package/fesm2022/ngwr-form-testing.mjs.map +1 -1
  147. package/fesm2022/ngwr-form.mjs +61 -10
  148. package/fesm2022/ngwr-form.mjs.map +1 -1
  149. package/fesm2022/ngwr-fuzzy-text-testing.mjs.map +1 -1
  150. package/fesm2022/ngwr-fuzzy-text.mjs +3 -3
  151. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  152. package/fesm2022/ngwr-gauge-testing.mjs.map +1 -1
  153. package/fesm2022/ngwr-gauge.mjs +35 -6
  154. package/fesm2022/ngwr-gauge.mjs.map +1 -1
  155. package/fesm2022/ngwr-glitch-text-testing.mjs.map +1 -1
  156. package/fesm2022/ngwr-glitch-text.mjs +3 -3
  157. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  158. package/fesm2022/ngwr-gradient-text-testing.mjs.map +1 -1
  159. package/fesm2022/ngwr-gradient-text.mjs +3 -3
  160. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  161. package/fesm2022/ngwr-graph-testing.mjs.map +1 -1
  162. package/fesm2022/ngwr-graph.mjs +6 -6
  163. package/fesm2022/ngwr-graph.mjs.map +1 -1
  164. package/fesm2022/ngwr-hotkey.mjs +6 -6
  165. package/fesm2022/ngwr-hotkey.mjs.map +1 -1
  166. package/fesm2022/ngwr-i18n-ar.mjs +31 -0
  167. package/fesm2022/ngwr-i18n-ar.mjs.map +1 -1
  168. package/fesm2022/ngwr-i18n-cs.mjs +31 -0
  169. package/fesm2022/ngwr-i18n-cs.mjs.map +1 -1
  170. package/fesm2022/ngwr-i18n-de.mjs +31 -0
  171. package/fesm2022/ngwr-i18n-de.mjs.map +1 -1
  172. package/fesm2022/ngwr-i18n-en.mjs +39 -0
  173. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  174. package/fesm2022/ngwr-i18n-es.mjs +31 -0
  175. package/fesm2022/ngwr-i18n-es.mjs.map +1 -1
  176. package/fesm2022/ngwr-i18n-fr.mjs +31 -0
  177. package/fesm2022/ngwr-i18n-fr.mjs.map +1 -1
  178. package/fesm2022/ngwr-i18n-he.mjs +31 -0
  179. package/fesm2022/ngwr-i18n-he.mjs.map +1 -1
  180. package/fesm2022/ngwr-i18n-hi.mjs +31 -0
  181. package/fesm2022/ngwr-i18n-hi.mjs.map +1 -1
  182. package/fesm2022/ngwr-i18n-id.mjs +31 -0
  183. package/fesm2022/ngwr-i18n-id.mjs.map +1 -1
  184. package/fesm2022/ngwr-i18n-it.mjs +31 -0
  185. package/fesm2022/ngwr-i18n-it.mjs.map +1 -1
  186. package/fesm2022/ngwr-i18n-ja.mjs +31 -0
  187. package/fesm2022/ngwr-i18n-ja.mjs.map +1 -1
  188. package/fesm2022/ngwr-i18n-ko.mjs +31 -0
  189. package/fesm2022/ngwr-i18n-ko.mjs.map +1 -1
  190. package/fesm2022/ngwr-i18n-nl.mjs +31 -0
  191. package/fesm2022/ngwr-i18n-nl.mjs.map +1 -1
  192. package/fesm2022/ngwr-i18n-pl.mjs +31 -0
  193. package/fesm2022/ngwr-i18n-pl.mjs.map +1 -1
  194. package/fesm2022/ngwr-i18n-pt.mjs +31 -0
  195. package/fesm2022/ngwr-i18n-pt.mjs.map +1 -1
  196. package/fesm2022/ngwr-i18n-ru.mjs +31 -0
  197. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  198. package/fesm2022/ngwr-i18n-sv.mjs +31 -0
  199. package/fesm2022/ngwr-i18n-sv.mjs.map +1 -1
  200. package/fesm2022/ngwr-i18n-tr.mjs +31 -0
  201. package/fesm2022/ngwr-i18n-tr.mjs.map +1 -1
  202. package/fesm2022/ngwr-i18n-uk.mjs +31 -0
  203. package/fesm2022/ngwr-i18n-uk.mjs.map +1 -1
  204. package/fesm2022/ngwr-i18n-vi.mjs +31 -0
  205. package/fesm2022/ngwr-i18n-vi.mjs.map +1 -1
  206. package/fesm2022/ngwr-i18n-zh-TW.mjs +31 -0
  207. package/fesm2022/ngwr-i18n-zh-TW.mjs.map +1 -1
  208. package/fesm2022/ngwr-i18n-zh.mjs +31 -0
  209. package/fesm2022/ngwr-i18n-zh.mjs.map +1 -1
  210. package/fesm2022/ngwr-i18n.mjs +9 -9
  211. package/fesm2022/ngwr-i18n.mjs.map +1 -1
  212. package/fesm2022/ngwr-icon-adapters-feather.mjs.map +1 -1
  213. package/fesm2022/ngwr-icon-adapters-lucide.mjs.map +1 -1
  214. package/fesm2022/ngwr-icon.mjs +6 -6
  215. package/fesm2022/ngwr-icon.mjs.map +1 -1
  216. package/fesm2022/ngwr-image-cropper-testing.mjs.map +1 -1
  217. package/fesm2022/ngwr-image-cropper.mjs +3 -3
  218. package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
  219. package/fesm2022/ngwr-input-number-testing.mjs.map +1 -1
  220. package/fesm2022/ngwr-input-number.mjs +15 -3
  221. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  222. package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -1
  223. package/fesm2022/ngwr-input-otp.mjs +3 -3
  224. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  225. package/fesm2022/ngwr-input-testing.mjs.map +1 -1
  226. package/fesm2022/ngwr-input.mjs +15 -15
  227. package/fesm2022/ngwr-input.mjs.map +1 -1
  228. package/fesm2022/ngwr-keyboard.mjs +3 -3
  229. package/fesm2022/ngwr-keyboard.mjs.map +1 -1
  230. package/fesm2022/ngwr-knob-testing.mjs.map +1 -1
  231. package/fesm2022/ngwr-knob.mjs +3 -3
  232. package/fesm2022/ngwr-knob.mjs.map +1 -1
  233. package/fesm2022/ngwr-layout.mjs +15 -15
  234. package/fesm2022/ngwr-layout.mjs.map +1 -1
  235. package/fesm2022/ngwr-lightbox-testing.mjs.map +1 -1
  236. package/fesm2022/ngwr-lightbox.mjs +3 -3
  237. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  238. package/fesm2022/ngwr-line-chart-testing.mjs.map +1 -1
  239. package/fesm2022/ngwr-line-chart.mjs +18 -7
  240. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  241. package/fesm2022/ngwr-list.mjs +6 -6
  242. package/fesm2022/ngwr-list.mjs.map +1 -1
  243. package/fesm2022/ngwr-loading-bar-router.mjs.map +1 -1
  244. package/fesm2022/ngwr-loading-bar.mjs +6 -6
  245. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  246. package/fesm2022/ngwr-markdown-testing.mjs.map +1 -1
  247. package/fesm2022/ngwr-markdown.mjs +798 -17
  248. package/fesm2022/ngwr-markdown.mjs.map +1 -1
  249. package/fesm2022/ngwr-marquee-testing.mjs.map +1 -1
  250. package/fesm2022/ngwr-marquee.mjs +3 -3
  251. package/fesm2022/ngwr-marquee.mjs.map +1 -1
  252. package/fesm2022/ngwr-media.mjs +3 -3
  253. package/fesm2022/ngwr-media.mjs.map +1 -1
  254. package/fesm2022/ngwr-mention-testing.mjs.map +1 -1
  255. package/fesm2022/ngwr-mention.mjs +6 -6
  256. package/fesm2022/ngwr-mention.mjs.map +1 -1
  257. package/fesm2022/ngwr-meta.mjs +6 -6
  258. package/fesm2022/ngwr-meta.mjs.map +1 -1
  259. package/fesm2022/ngwr-meter-group-testing.mjs +7 -3
  260. package/fesm2022/ngwr-meter-group-testing.mjs.map +1 -1
  261. package/fesm2022/ngwr-meter-group.mjs +26 -6
  262. package/fesm2022/ngwr-meter-group.mjs.map +1 -1
  263. package/fesm2022/ngwr-overlay.mjs +6 -6
  264. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  265. package/fesm2022/ngwr-page-header.mjs +13 -5
  266. package/fesm2022/ngwr-page-header.mjs.map +1 -1
  267. package/fesm2022/ngwr-pagination-testing.mjs.map +1 -1
  268. package/fesm2022/ngwr-pagination.mjs +3 -3
  269. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  270. package/fesm2022/ngwr-pipes.mjs +21 -21
  271. package/fesm2022/ngwr-pipes.mjs.map +1 -1
  272. package/fesm2022/ngwr-platform.mjs +9 -9
  273. package/fesm2022/ngwr-platform.mjs.map +1 -1
  274. package/fesm2022/ngwr-popconfirm-testing.mjs.map +1 -1
  275. package/fesm2022/ngwr-popconfirm.mjs +6 -6
  276. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  277. package/fesm2022/ngwr-popover-testing.mjs.map +1 -1
  278. package/fesm2022/ngwr-popover.mjs +578 -16
  279. package/fesm2022/ngwr-popover.mjs.map +1 -1
  280. package/fesm2022/ngwr-progress.mjs +3 -3
  281. package/fesm2022/ngwr-progress.mjs.map +1 -1
  282. package/fesm2022/ngwr-pull-to-refresh.mjs +3 -3
  283. package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -1
  284. package/fesm2022/ngwr-qr.mjs +3 -3
  285. package/fesm2022/ngwr-qr.mjs.map +1 -1
  286. package/fesm2022/ngwr-radio-testing.mjs.map +1 -1
  287. package/fesm2022/ngwr-radio.mjs +6 -6
  288. package/fesm2022/ngwr-radio.mjs.map +1 -1
  289. package/fesm2022/ngwr-rating-testing.mjs.map +1 -1
  290. package/fesm2022/ngwr-rating.mjs +3 -3
  291. package/fesm2022/ngwr-rating.mjs.map +1 -1
  292. package/fesm2022/ngwr-result.mjs +12 -12
  293. package/fesm2022/ngwr-result.mjs.map +1 -1
  294. package/fesm2022/ngwr-rotating-text-testing.mjs.map +1 -1
  295. package/fesm2022/ngwr-rotating-text.mjs +3 -3
  296. package/fesm2022/ngwr-rotating-text.mjs.map +1 -1
  297. package/fesm2022/ngwr-schema-form.mjs +3 -3
  298. package/fesm2022/ngwr-schema-form.mjs.map +1 -1
  299. package/fesm2022/ngwr-scroll.mjs +3 -3
  300. package/fesm2022/ngwr-scroll.mjs.map +1 -1
  301. package/fesm2022/ngwr-segmented-testing.mjs.map +1 -1
  302. package/fesm2022/ngwr-segmented.mjs +3 -3
  303. package/fesm2022/ngwr-segmented.mjs.map +1 -1
  304. package/fesm2022/ngwr-select-testing.mjs.map +1 -1
  305. package/fesm2022/ngwr-select.mjs +12 -12
  306. package/fesm2022/ngwr-select.mjs.map +1 -1
  307. package/fesm2022/ngwr-shiny-text-testing.mjs.map +1 -1
  308. package/fesm2022/ngwr-shiny-text.mjs +6 -6
  309. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  310. package/fesm2022/ngwr-sidebar.mjs +10 -3
  311. package/fesm2022/ngwr-sidebar.mjs.map +1 -1
  312. package/fesm2022/ngwr-skeleton.mjs +3 -3
  313. package/fesm2022/ngwr-skeleton.mjs.map +1 -1
  314. package/fesm2022/ngwr-slider-testing.mjs.map +1 -1
  315. package/fesm2022/ngwr-slider.mjs +3 -3
  316. package/fesm2022/ngwr-slider.mjs.map +1 -1
  317. package/fesm2022/ngwr-sparkline-testing.mjs.map +1 -1
  318. package/fesm2022/ngwr-sparkline.mjs +84 -10
  319. package/fesm2022/ngwr-sparkline.mjs.map +1 -1
  320. package/fesm2022/ngwr-speed-dial-testing.mjs.map +1 -1
  321. package/fesm2022/ngwr-speed-dial.mjs +3 -3
  322. package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
  323. package/fesm2022/ngwr-spinner.mjs +3 -3
  324. package/fesm2022/ngwr-spinner.mjs.map +1 -1
  325. package/fesm2022/ngwr-splash-cursor-testing.mjs.map +1 -1
  326. package/fesm2022/ngwr-splash-cursor.mjs +3 -3
  327. package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
  328. package/fesm2022/ngwr-split-text-testing.mjs.map +1 -1
  329. package/fesm2022/ngwr-split-text.mjs +3 -3
  330. package/fesm2022/ngwr-split-text.mjs.map +1 -1
  331. package/fesm2022/ngwr-splitter-testing.mjs.map +1 -1
  332. package/fesm2022/ngwr-splitter.mjs +3 -3
  333. package/fesm2022/ngwr-splitter.mjs.map +1 -1
  334. package/fesm2022/ngwr-spotlight-card-testing.mjs.map +1 -1
  335. package/fesm2022/ngwr-spotlight-card.mjs +6 -6
  336. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  337. package/fesm2022/ngwr-squircle.mjs +6 -6
  338. package/fesm2022/ngwr-squircle.mjs.map +1 -1
  339. package/fesm2022/ngwr-star-border-testing.mjs.map +1 -1
  340. package/fesm2022/ngwr-star-border.mjs +3 -3
  341. package/fesm2022/ngwr-star-border.mjs.map +1 -1
  342. package/fesm2022/ngwr-statistic.mjs +9 -9
  343. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  344. package/fesm2022/ngwr-stepper-testing.mjs.map +1 -1
  345. package/fesm2022/ngwr-stepper.mjs +6 -6
  346. package/fesm2022/ngwr-stepper.mjs.map +1 -1
  347. package/fesm2022/ngwr-storage.mjs +3 -3
  348. package/fesm2022/ngwr-storage.mjs.map +1 -1
  349. package/fesm2022/ngwr-switch-testing.mjs.map +1 -1
  350. package/fesm2022/ngwr-switch.mjs +3 -3
  351. package/fesm2022/ngwr-switch.mjs.map +1 -1
  352. package/fesm2022/ngwr-table-testing.mjs.map +1 -1
  353. package/fesm2022/ngwr-table.mjs +18 -18
  354. package/fesm2022/ngwr-table.mjs.map +1 -1
  355. package/fesm2022/ngwr-tabs-router.mjs +3 -3
  356. package/fesm2022/ngwr-tabs-router.mjs.map +1 -1
  357. package/fesm2022/ngwr-tabs-testing.mjs.map +1 -1
  358. package/fesm2022/ngwr-tabs.mjs +6 -6
  359. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  360. package/fesm2022/ngwr-textarea-testing.mjs.map +1 -1
  361. package/fesm2022/ngwr-textarea.mjs +3 -3
  362. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  363. package/fesm2022/ngwr-theme.mjs +3 -3
  364. package/fesm2022/ngwr-theme.mjs.map +1 -1
  365. package/fesm2022/ngwr-tilt-card-testing.mjs.map +1 -1
  366. package/fesm2022/ngwr-tilt-card.mjs +6 -6
  367. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  368. package/fesm2022/ngwr-timeline.mjs +6 -6
  369. package/fesm2022/ngwr-timeline.mjs.map +1 -1
  370. package/fesm2022/ngwr-toast-testing.mjs.map +1 -1
  371. package/fesm2022/ngwr-toast.mjs +9 -9
  372. package/fesm2022/ngwr-toast.mjs.map +1 -1
  373. package/fesm2022/ngwr-toolbar.mjs +10 -3
  374. package/fesm2022/ngwr-toolbar.mjs.map +1 -1
  375. package/fesm2022/ngwr-tour-testing.mjs.map +1 -1
  376. package/fesm2022/ngwr-tour.mjs +6 -6
  377. package/fesm2022/ngwr-tour.mjs.map +1 -1
  378. package/fesm2022/ngwr-transfer-testing.mjs.map +1 -1
  379. package/fesm2022/ngwr-transfer.mjs +3 -3
  380. package/fesm2022/ngwr-transfer.mjs.map +1 -1
  381. package/fesm2022/ngwr-tree-testing.mjs.map +1 -1
  382. package/fesm2022/ngwr-tree.mjs +3 -3
  383. package/fesm2022/ngwr-tree.mjs.map +1 -1
  384. package/fesm2022/ngwr-typewriter-testing.mjs.map +1 -1
  385. package/fesm2022/ngwr-typewriter.mjs +3 -3
  386. package/fesm2022/ngwr-typewriter.mjs.map +1 -1
  387. package/fesm2022/ngwr-typography.mjs +7 -3
  388. package/fesm2022/ngwr-typography.mjs.map +1 -1
  389. package/fesm2022/ngwr-utils.mjs.map +1 -1
  390. package/fesm2022/ngwr-validators.mjs.map +1 -1
  391. package/fesm2022/ngwr-version.mjs +1 -1
  392. package/fesm2022/ngwr-version.mjs.map +1 -1
  393. package/fesm2022/ngwr-virtual-scroll.mjs +3 -3
  394. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  395. package/fesm2022/ngwr-waves-testing.mjs.map +1 -1
  396. package/fesm2022/ngwr-waves.mjs +3 -3
  397. package/fesm2022/ngwr-waves.mjs.map +1 -1
  398. package/fesm2022/ngwr-window-testing.mjs.map +1 -1
  399. package/fesm2022/ngwr-window.mjs +12 -12
  400. package/fesm2022/ngwr-window.mjs.map +1 -1
  401. package/form/styles/_index.scss +16 -1
  402. package/gauge/styles/_index.scss +1 -0
  403. package/i18n/ar.json +32 -1
  404. package/i18n/cs.json +32 -1
  405. package/i18n/de.json +32 -1
  406. package/i18n/en.json +32 -1
  407. package/i18n/es.json +32 -1
  408. package/i18n/fr.json +32 -1
  409. package/i18n/he.json +32 -1
  410. package/i18n/hi.json +32 -1
  411. package/i18n/id.json +32 -1
  412. package/i18n/it.json +32 -1
  413. package/i18n/ja.json +32 -1
  414. package/i18n/ko.json +32 -1
  415. package/i18n/nl.json +32 -1
  416. package/i18n/pl.json +32 -1
  417. package/i18n/pt.json +32 -1
  418. package/i18n/ru.json +32 -1
  419. package/i18n/sv.json +32 -1
  420. package/i18n/tr.json +32 -1
  421. package/i18n/uk.json +32 -1
  422. package/i18n/vi.json +32 -1
  423. package/i18n/zh-TW.json +32 -1
  424. package/i18n/zh.json +32 -1
  425. package/input/styles/_index.scss +24 -1
  426. package/input-number/styles/_index.scss +69 -0
  427. package/input-otp/styles/_index.scss +5 -5
  428. package/line-chart/styles/_index.scss +30 -2
  429. package/llms-full.txt +14 -4
  430. package/llms.txt +188 -132
  431. package/mcp/providers.js +2 -2
  432. package/mcp/server.js +1 -1
  433. package/meter-group/styles/_index.scss +1 -0
  434. package/overlay/styles/_arrow.scss +30 -2
  435. package/package.json +43 -2
  436. package/page-header/styles/_index.scss +37 -1
  437. package/pagination/styles/_index.scss +9 -5
  438. package/popover/styles/_index.scss +73 -5
  439. package/progress/styles/_index.scss +4 -0
  440. package/radio/styles/_index.scss +4 -1
  441. package/schematics/use/symbol-map.json +1 -0
  442. package/select/styles/_index.scss +51 -12
  443. package/sidebar/styles/_index.scss +44 -2
  444. package/skeleton/styles/_index.scss +3 -0
  445. package/skills/ngwr/SKILL.md +5 -5
  446. package/skills/ngwr/references/catalog.md +2 -0
  447. package/skills/ngwr/references/setup.md +3 -3
  448. package/sparkline/styles/_index.scss +19 -0
  449. package/styles.scss +1 -0
  450. package/table/styles/_index.scss +7 -0
  451. package/textarea/styles/_index.scss +12 -3
  452. package/theme/styles/_colors.scss +39 -13
  453. package/theme/styles/_contrast.scss +9 -7
  454. package/toast/styles/_index.scss +4 -0
  455. package/toolbar/styles/_index.scss +35 -1
  456. package/tree/styles/_index.scss +46 -7
  457. package/types/ngwr-badge.d.ts +22 -7
  458. package/types/ngwr-bar-chart.d.ts +19 -1
  459. package/types/ngwr-calendar-heatmap.d.ts +29 -1
  460. package/types/ngwr-checkbox.d.ts +2 -0
  461. package/types/ngwr-config.d.ts +12 -0
  462. package/types/ngwr-date-picker.d.ts +308 -43
  463. package/types/ngwr-donut-chart.d.ts +24 -1
  464. package/types/ngwr-dropdown.d.ts +22 -2
  465. package/types/ngwr-editor-testing.d.ts +378 -0
  466. package/types/ngwr-editor.d.ts +449 -0
  467. package/types/ngwr-event-calendar.d.ts +8 -0
  468. package/types/ngwr-form.d.ts +35 -5
  469. package/types/ngwr-gauge.d.ts +20 -1
  470. package/types/ngwr-input-number.d.ts +7 -0
  471. package/types/ngwr-line-chart.d.ts +9 -1
  472. package/types/ngwr-markdown.d.ts +61 -2
  473. package/types/ngwr-meter-group-testing.d.ts +3 -2
  474. package/types/ngwr-meter-group.d.ts +14 -1
  475. package/types/ngwr-page-header.d.ts +10 -2
  476. package/types/ngwr-popover.d.ts +154 -3
  477. package/types/ngwr-sidebar.d.ts +7 -0
  478. package/types/ngwr-sparkline.d.ts +43 -1
  479. package/types/ngwr-toolbar.d.ts +7 -0
  480. package/types/ngwr-typography.d.ts +4 -0
  481. package/types/ngwr-version.d.ts +1 -1
  482. package/typography/styles/_index.scss +16 -0
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-input-otp.mjs","sources":["../../../projects/lib/input-otp/input-otp.ts","../../../projects/lib/input-otp/input-otp.html","../../../projects/lib/input-otp/ngwr-input-otp.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 { Directionality } from '@angular/cdk/bidi';\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n Injector,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n model,\n output,\n signal,\n type ElementRef,\n untracked,\n viewChildren,\n} from '@angular/core';\nimport type { FormValueControl } from '@angular/forms/signals';\n\nimport { useConfigValue } from 'ngwr/config';\nimport { useFormFieldAria } from 'ngwr/form';\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\nimport { isComposing } from 'ngwr/utils';\n\nimport type { WrInputOtpMode, WrInputOtpSize } from './interfaces';\n\n/**\n * Fixed-length one-time-code input. Renders one `<input>` per character,\n * auto-advances focus on typing, handles paste of a full code, and supports\n * masking like a password field.\n *\n * A signal-forms native control: it implements `FormValueControl<string>`, so\n * `[formField]` binds straight to its `value` model — no\n * `ControlValueAccessor` in between. `[(value)]` works standalone. Emits\n * `completed` once all cells are filled (useful for auto-submission).\n *\n * @example\n * ```html\n * <!-- signal forms -->\n * <wr-input-otp [formField]=\"form.code\" length=\"6\" (completed)=\"verify($event)\" />\n *\n * <!-- standalone two-way binding -->\n * <wr-input-otp [(value)]=\"code\" length=\"6\" (completed)=\"verify($event)\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/input-otp\n */\n@Component({\n selector: 'wr-input-otp',\n templateUrl: './input-otp.html',\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'classes()',\n role: 'group',\n '[attr.aria-label]': 'groupName()',\n '[attr.aria-labelledby]': 'labelledBy()',\n },\n})\nexport class WrInputOtp implements FormValueControl<string> {\n private readonly dir = inject(Directionality, { optional: true });\n private readonly injector = inject(Injector);\n\n /** Accessible name of the whole strip. Falls back to `inputOtp.label`. */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'inputOtp.label', 'Verification code');\n\n /** Number of cells to render. Clamped to `[1, 20]`. @default 6 */\n readonly length = input(6, {\n transform: (v: unknown): number => Math.max(1, Math.min(20, coerceNumberProperty(v, 6))),\n });\n\n /** Character set per cell. @default 'numeric' */\n readonly mode = input<WrInputOtpMode>('numeric');\n\n /**\n * Control size — shares the `--wr-control-*` contract. Unset falls back to the\n * `inputOtp.size` app default from `provideWrConfig()`. @default 'md'\n */\n readonly size = input<WrInputOtpSize | null>(null);\n\n /**\n * `size`, then the app config, then `md`.\n *\n * Read ONCE, here: a box carries no size of its own — the host modifier sets\n * `--wr-input-otp-size` / `-font` / `-radius` / `-gap` and every box reads them\n * from the cascade — so one resolution sizes the whole strip however many boxes\n * `length` renders.\n */\n protected readonly resolvedSize = useConfigValue(this.size, c => c.inputOtp?.size, 'md');\n\n /** Mask the typed characters like a password. @default false */\n readonly mask = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Disable interaction. Bound automatically from the field's disabled state\n * when used with `[formField]`.\n *\n * @default false\n */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Refuse edits while every box stays focusable and the code still submits.\n * Bound automatically from the field's readonly state when used with\n * `[formField]`.\n *\n * Each box is a real text input, so this is the native `readonly` attribute —\n * arrow keys, Home / End and selection keep working, which is the whole\n * difference from `disabled`. Paste is cancelled too, since a `paste` still\n * reaches a read-only input even though typing does not.\n *\n * @default false\n */\n readonly readonly = input(false, { transform: coerceBooleanProperty });\n\n /**\n * The surrounding `<wr-form-field>`'s error state — bound per BOX rather than\n * on the `role=\"group\"` host, because the box is what takes focus and a reader\n * queries the focused element.\n *\n * @internal\n */\n protected readonly fieldAria = useFormFieldAria();\n\n /**\n * The field's label names the strip, when there is one.\n *\n * The host is a `role=\"group\"`, which `<wr-form-field>`'s `<label for>` cannot\n * reach — `for` binds only to a labelable element — so a field wrapping this\n * rendered a label that named nothing and the strip announced its own generic\n * default instead. An explicit `ariaLabel` still wins over both.\n */\n protected readonly labelledBy = computed(() => (this.ariaLabel() ? null : this.fieldAria.labelledBy()));\n\n /** `null` while the field's label carries the name, or the two are announced together. */\n protected readonly groupName = computed(() => (this.labelledBy() ? null : this.resolvedAriaLabel()));\n\n /** Character shown in empty cells. @default '•' */\n readonly placeholder = input<string>('•');\n\n /** The entered code. Bound by `[formField]`, or two-way via `[(value)]`. */\n readonly value = model<string>('');\n\n /** Fires once when every cell holds a character. */\n readonly completed = output<string>();\n\n /** Emitted on blur so a bound field can mark itself touched. */\n readonly touch = output<void>();\n\n protected readonly cells = signal<readonly string[]>(Array.from({ length: 6 }, () => ''));\n\n protected readonly classes = computed(() => {\n const parts = ['wr-input-otp'];\n const size = this.resolvedSize();\n if (size !== 'md') parts.push(`wr-input-otp--${size}`);\n if (this.disabled()) parts.push('wr-input-otp--disabled');\n else if (this.readonly()) parts.push('wr-input-otp--readonly');\n return parts.join(' ');\n });\n\n protected readonly cellType = computed<'password' | 'text'>(() => (this.mask() ? 'password' : 'text'));\n protected readonly cellInputMode = computed(() => (this.mode() === 'numeric' ? 'numeric' : 'text'));\n\n private readonly digitLabel = useI18nFormatter('inputOtp.digit', 'Digit {{index}}');\n private readonly characterLabel = useI18nFormatter('inputOtp.character', 'Character {{index}}');\n\n protected readonly cellRefs = viewChildren<ElementRef<HTMLInputElement>>('cell');\n\n constructor() {\n // Resize the cell array whenever `length` changes — preserves existing values.\n effect(() => {\n const len = this.length();\n const current = this.cells();\n if (current.length === len) return;\n const next = Array.from({ length: len }, (_, i) => current[i] ?? '');\n this.cells.set(next);\n });\n\n // Split an external `value` write back into cells (mirrors the old\n // writeValue). Skipped when the value is merely the echo of an in-cell\n // edit, so re-splitting can never shift or clobber what the user typed.\n effect(() => {\n // Coerce null/undefined to '' — a classic-forms binding can write null,\n // which the old `writeValue(v: string | null)` accepted too.\n const v = this.value() ?? '';\n untracked(() => {\n if (this.cells().join('') === v) return;\n const len = this.length();\n const raw = v.slice(0, len);\n const next = Array.from({ length: len }, (_, i) => this.sanitiseChar(raw[i] ?? ''));\n this.cells.set(next);\n });\n });\n }\n\n // Template handlers\n\n protected onInput(event: Event, index: number): void {\n // An input method leaves its half-built reading in the box and only replaces\n // it on `compositionend`. Sanitising that intermediate text writes `''` back\n // into the field the IME is still composing in, which aborts the conversion\n // outright — so the box is left alone until the text is real.\n if ((event as InputEvent).isComposing) return;\n this.commitCell(event.target as HTMLInputElement, index);\n }\n\n /** @see onInput — this is where an IME's text finally arrives. */\n protected onCompositionEnd(event: CompositionEvent, index: number): void {\n this.commitCell(event.target as HTMLInputElement, index);\n }\n\n private commitCell(target: HTMLInputElement, index: number): void {\n if (this.readonly()) {\n // A read-only input refuses typed characters on its own; this covers the\n // synthetic writes a script (or a spec) can still make.\n target.value = this.cells()[index] ?? '';\n return;\n }\n const char = this.sanitiseChar(target.value.slice(-1));\n target.value = char;\n this.update(index, char);\n if (char) this.focusCell(index + 1);\n }\n\n protected onKeyDown(event: KeyboardEvent, index: number): void {\n // Backspace and the arrows move the caret between boxes; while a conversion\n // is open they belong to the candidate window, and moving focus out of the\n // composing box discards it.\n if (isComposing(event)) return;\n\n const target = event.target as HTMLInputElement;\n switch (this.inlineKey(event.key)) {\n case 'Backspace':\n if (this.readonly()) {\n // Backspace on an empty box is an EDIT (it clears the previous one),\n // so it goes; the pure navigation keys below stay.\n event.preventDefault();\n break;\n }\n if (target.value === '') {\n event.preventDefault();\n this.update(index - 1, '');\n this.focusCell(index - 1);\n }\n break;\n case 'ArrowLeft':\n event.preventDefault();\n this.focusCell(index - 1);\n break;\n case 'ArrowRight':\n event.preventDefault();\n this.focusCell(index + 1);\n break;\n case 'Home':\n event.preventDefault();\n this.focusCell(0);\n break;\n case 'End':\n event.preventDefault();\n this.focusCell(this.length() - 1);\n break;\n }\n }\n\n protected onPaste(event: ClipboardEvent): void {\n event.preventDefault();\n if (this.readonly()) return;\n const text = event.clipboardData?.getData('text') ?? '';\n const chars = text\n .split('')\n .map(c => this.sanitiseChar(c))\n .filter(c => c.length > 0);\n if (chars.length === 0) return;\n const trimmed = chars.slice(0, this.length());\n const next = Array.from({ length: this.length() }, (_, i) => trimmed[i] ?? '');\n this.cells.set(next);\n this.emitChange();\n // `afterNextRender`, not a straight call. `focusCell` ends in `select()`, and\n // under zoneless CD the DOM still holds the PREVIOUS value at this point —\n // change detection runs in a macrotask. So the selection was made over an\n // empty box and the caret ended up after the character instead of over it:\n // measured, the landing box read `3` with the selection at `1-1`. With\n // `maxlength=\"1\"` and one character already in the box, the very next\n // keystroke was then refused, so a user who pasted a code and typed to\n // correct its last digit got nothing.\n //\n // Only the paste path needs this. Arrow keys move between boxes whose values\n // are not changing, so a synchronous select there is over settled DOM.\n afterNextRender(() => this.focusCell(Math.min(trimmed.length, this.length() - 1)), {\n injector: this.injector,\n });\n }\n\n protected onBlur(): void {\n this.touch.emit();\n }\n\n protected trackIndex(index: number): number {\n return index;\n }\n\n /**\n * A box's accessible name. It projects no text and carries no label of its own,\n * so this string IS the name a screen reader reads for it.\n *\n * Keyed off `mode`, not fixed: `sanitiseChar` passes any letter through in\n * `alphanumeric` and `text`, so the old literal announced \"Digit 3\" over a box\n * holding `A` — wrong in a way translating it would not have fixed.\n */\n protected cellLabel(index: number): string {\n const params = { index: index + 1 };\n return this.mode() === 'numeric' ? this.digitLabel(params) : this.characterLabel(params);\n }\n\n // Internals\n\n private update(index: number, char: string): void {\n if (index < 0 || index >= this.length()) return;\n const next = [...this.cells()];\n next[index] = char;\n this.cells.set(next);\n this.emitChange();\n }\n\n private emitChange(): void {\n const code = this.cells().join('');\n this.value.set(code);\n if (code.length === this.length() && code.split('').every(c => c.length === 1)) {\n this.completed.emit(code);\n }\n }\n\n private focusCell(i: number): void {\n if (i < 0 || i >= this.length()) return;\n const el = this.cellRefs()[i]?.nativeElement;\n if (!el) return;\n el.focus();\n el.select();\n }\n\n /** Drop a character that doesn't match the configured mode. */\n private sanitiseChar(c: string): string {\n if (!c) return '';\n const one = c.slice(0, 1);\n switch (this.mode()) {\n case 'numeric':\n return /\\d/.test(one) ? one : '';\n case 'alphanumeric':\n return /[a-zA-Z0-9]/.test(one) ? one : '';\n case 'text':\n default:\n return one;\n }\n }\n\n /**\n * The key as the strip SEES it.\n *\n * The boxes run along the inline axis, so under `dir=\"rtl\"` the box to the\n * visual right of the caret is the PREVIOUS one. Home/End stay semantic (first\n * and last box), and Backspace is not a direction at all.\n */\n private inlineKey(key: string): string {\n if (this.dir?.value !== 'rtl') return key;\n if (key === 'ArrowRight') return 'ArrowLeft';\n if (key === 'ArrowLeft') return 'ArrowRight';\n return key;\n }\n}\n","@for (cell of cells(); track trackIndex($index)) {\n <input\n #cell\n class=\"wr-input-otp__cell\"\n [type]=\"cellType()\"\n [attr.inputmode]=\"cellInputMode()\"\n maxlength=\"1\"\n autocomplete=\"one-time-code\"\n autocapitalize=\"off\"\n spellcheck=\"false\"\n [value]=\"cell\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"cellLabel($index)\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n (input)=\"onInput($event, $index)\"\n (keydown)=\"onKeyDown($event, $index)\"\n (compositionend)=\"onCompositionEnd($event, $index)\"\n (paste)=\"onPaste($event)\"\n (blur)=\"onBlur()\"\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-input-otp.mjs","sources":["../../../projects/lib/input-otp/input-otp.ts","../../../projects/lib/input-otp/input-otp.html","../../../projects/lib/input-otp/ngwr-input-otp.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 { Directionality } from '@angular/cdk/bidi';\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n Injector,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n model,\n output,\n signal,\n type ElementRef,\n untracked,\n viewChildren,\n} from '@angular/core';\nimport type { FormValueControl } from '@angular/forms/signals';\n\nimport { useConfigValue } from 'ngwr/config';\nimport { useFormFieldAria } from 'ngwr/form';\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\nimport { isComposing } from 'ngwr/utils';\n\nimport type { WrInputOtpMode, WrInputOtpSize } from './interfaces';\n\n/**\n * Fixed-length one-time-code input. Renders one `<input>` per character,\n * auto-advances focus on typing, handles paste of a full code, and supports\n * masking like a password field.\n *\n * A signal-forms native control: it implements `FormValueControl<string>`, so\n * `[formField]` binds straight to its `value` model — no\n * `ControlValueAccessor` in between. `[(value)]` works standalone. Emits\n * `completed` once all cells are filled (useful for auto-submission).\n *\n * @example\n * ```html\n * <!-- signal forms -->\n * <wr-input-otp [formField]=\"form.code\" length=\"6\" (completed)=\"verify($event)\" />\n *\n * <!-- standalone two-way binding -->\n * <wr-input-otp [(value)]=\"code\" length=\"6\" (completed)=\"verify($event)\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/input-otp\n */\n@Component({\n selector: 'wr-input-otp',\n templateUrl: './input-otp.html',\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'classes()',\n role: 'group',\n '[attr.aria-label]': 'groupName()',\n '[attr.aria-labelledby]': 'labelledBy()',\n },\n})\nexport class WrInputOtp implements FormValueControl<string> {\n private readonly dir = inject(Directionality, { optional: true });\n private readonly injector = inject(Injector);\n\n /** Accessible name of the whole strip. Falls back to `inputOtp.label`. */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'inputOtp.label', 'Verification code');\n\n /** Number of cells to render. Clamped to `[1, 20]`. @default 6 */\n readonly length = input(6, {\n transform: (v: unknown): number => Math.max(1, Math.min(20, coerceNumberProperty(v, 6))),\n });\n\n /** Character set per cell. @default 'numeric' */\n readonly mode = input<WrInputOtpMode>('numeric');\n\n /**\n * Control size — shares the `--wr-control-*` contract. Unset falls back to the\n * `inputOtp.size` app default from `provideWrConfig()`. @default 'md'\n */\n readonly size = input<WrInputOtpSize | null>(null);\n\n /**\n * `size`, then the app config, then `md`.\n *\n * Read ONCE, here: a box carries no size of its own — the host modifier sets\n * `--wr-input-otp-size` / `-font` / `-radius` / `-gap` and every box reads them\n * from the cascade — so one resolution sizes the whole strip however many boxes\n * `length` renders.\n */\n protected readonly resolvedSize = useConfigValue(this.size, c => c.inputOtp?.size, 'md');\n\n /** Mask the typed characters like a password. @default false */\n readonly mask = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Disable interaction. Bound automatically from the field's disabled state\n * when used with `[formField]`.\n *\n * @default false\n */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Refuse edits while every box stays focusable and the code still submits.\n * Bound automatically from the field's readonly state when used with\n * `[formField]`.\n *\n * Each box is a real text input, so this is the native `readonly` attribute —\n * arrow keys, Home / End and selection keep working, which is the whole\n * difference from `disabled`. Paste is cancelled too, since a `paste` still\n * reaches a read-only input even though typing does not.\n *\n * @default false\n */\n readonly readonly = input(false, { transform: coerceBooleanProperty });\n\n /**\n * The surrounding `<wr-form-field>`'s error state — bound per BOX rather than\n * on the `role=\"group\"` host, because the box is what takes focus and a reader\n * queries the focused element.\n *\n * @internal\n */\n protected readonly fieldAria = useFormFieldAria();\n\n /**\n * The field's label names the strip, when there is one.\n *\n * The host is a `role=\"group\"`, which `<wr-form-field>`'s `<label for>` cannot\n * reach — `for` binds only to a labelable element — so a field wrapping this\n * rendered a label that named nothing and the strip announced its own generic\n * default instead. An explicit `ariaLabel` still wins over both.\n */\n protected readonly labelledBy = computed(() => (this.ariaLabel() ? null : this.fieldAria.labelledBy()));\n\n /** `null` while the field's label carries the name, or the two are announced together. */\n protected readonly groupName = computed(() => (this.labelledBy() ? null : this.resolvedAriaLabel()));\n\n /** Character shown in empty cells. @default '•' */\n readonly placeholder = input<string>('•');\n\n /** The entered code. Bound by `[formField]`, or two-way via `[(value)]`. */\n readonly value = model<string>('');\n\n /** Fires once when every cell holds a character. */\n readonly completed = output<string>();\n\n /** Emitted on blur so a bound field can mark itself touched. */\n readonly touch = output<void>();\n\n protected readonly cells = signal<readonly string[]>(Array.from({ length: 6 }, () => ''));\n\n protected readonly classes = computed(() => {\n const parts = ['wr-input-otp'];\n const size = this.resolvedSize();\n if (size !== 'md') parts.push(`wr-input-otp--${size}`);\n if (this.disabled()) parts.push('wr-input-otp--disabled');\n else if (this.readonly()) parts.push('wr-input-otp--readonly');\n return parts.join(' ');\n });\n\n protected readonly cellType = computed<'password' | 'text'>(() => (this.mask() ? 'password' : 'text'));\n protected readonly cellInputMode = computed(() => (this.mode() === 'numeric' ? 'numeric' : 'text'));\n\n private readonly digitLabel = useI18nFormatter('inputOtp.digit', 'Digit {{index}}');\n private readonly characterLabel = useI18nFormatter('inputOtp.character', 'Character {{index}}');\n\n protected readonly cellRefs = viewChildren<ElementRef<HTMLInputElement>>('cell');\n\n constructor() {\n // Resize the cell array whenever `length` changes — preserves existing values.\n effect(() => {\n const len = this.length();\n const current = this.cells();\n if (current.length === len) return;\n const next = Array.from({ length: len }, (_, i) => current[i] ?? '');\n this.cells.set(next);\n });\n\n // Split an external `value` write back into cells (mirrors the old\n // writeValue). Skipped when the value is merely the echo of an in-cell\n // edit, so re-splitting can never shift or clobber what the user typed.\n effect(() => {\n // Coerce null/undefined to '' — a classic-forms binding can write null,\n // which the old `writeValue(v: string | null)` accepted too.\n const v = this.value() ?? '';\n untracked(() => {\n if (this.cells().join('') === v) return;\n const len = this.length();\n const raw = v.slice(0, len);\n const next = Array.from({ length: len }, (_, i) => this.sanitiseChar(raw[i] ?? ''));\n this.cells.set(next);\n });\n });\n }\n\n // Template handlers\n\n protected onInput(event: Event, index: number): void {\n // An input method leaves its half-built reading in the box and only replaces\n // it on `compositionend`. Sanitising that intermediate text writes `''` back\n // into the field the IME is still composing in, which aborts the conversion\n // outright — so the box is left alone until the text is real.\n if ((event as InputEvent).isComposing) return;\n this.commitCell(event.target as HTMLInputElement, index);\n }\n\n /** @see onInput — this is where an IME's text finally arrives. */\n protected onCompositionEnd(event: CompositionEvent, index: number): void {\n this.commitCell(event.target as HTMLInputElement, index);\n }\n\n private commitCell(target: HTMLInputElement, index: number): void {\n if (this.readonly()) {\n // A read-only input refuses typed characters on its own; this covers the\n // synthetic writes a script (or a spec) can still make.\n target.value = this.cells()[index] ?? '';\n return;\n }\n const char = this.sanitiseChar(target.value.slice(-1));\n target.value = char;\n this.update(index, char);\n if (char) this.focusCell(index + 1);\n }\n\n protected onKeyDown(event: KeyboardEvent, index: number): void {\n // Backspace and the arrows move the caret between boxes; while a conversion\n // is open they belong to the candidate window, and moving focus out of the\n // composing box discards it.\n if (isComposing(event)) return;\n\n const target = event.target as HTMLInputElement;\n switch (this.inlineKey(event.key)) {\n case 'Backspace':\n if (this.readonly()) {\n // Backspace on an empty box is an EDIT (it clears the previous one),\n // so it goes; the pure navigation keys below stay.\n event.preventDefault();\n break;\n }\n if (target.value === '') {\n event.preventDefault();\n this.update(index - 1, '');\n this.focusCell(index - 1);\n }\n break;\n case 'ArrowLeft':\n event.preventDefault();\n this.focusCell(index - 1);\n break;\n case 'ArrowRight':\n event.preventDefault();\n this.focusCell(index + 1);\n break;\n case 'Home':\n event.preventDefault();\n this.focusCell(0);\n break;\n case 'End':\n event.preventDefault();\n this.focusCell(this.length() - 1);\n break;\n }\n }\n\n protected onPaste(event: ClipboardEvent): void {\n event.preventDefault();\n if (this.readonly()) return;\n const text = event.clipboardData?.getData('text') ?? '';\n const chars = text\n .split('')\n .map(c => this.sanitiseChar(c))\n .filter(c => c.length > 0);\n if (chars.length === 0) return;\n const trimmed = chars.slice(0, this.length());\n const next = Array.from({ length: this.length() }, (_, i) => trimmed[i] ?? '');\n this.cells.set(next);\n this.emitChange();\n // `afterNextRender`, not a straight call. `focusCell` ends in `select()`, and\n // under zoneless CD the DOM still holds the PREVIOUS value at this point —\n // change detection runs in a macrotask. So the selection was made over an\n // empty box and the caret ended up after the character instead of over it:\n // measured, the landing box read `3` with the selection at `1-1`. With\n // `maxlength=\"1\"` and one character already in the box, the very next\n // keystroke was then refused, so a user who pasted a code and typed to\n // correct its last digit got nothing.\n //\n // Only the paste path needs this. Arrow keys move between boxes whose values\n // are not changing, so a synchronous select there is over settled DOM.\n afterNextRender(() => this.focusCell(Math.min(trimmed.length, this.length() - 1)), {\n injector: this.injector,\n });\n }\n\n protected onBlur(): void {\n this.touch.emit();\n }\n\n protected trackIndex(index: number): number {\n return index;\n }\n\n /**\n * A box's accessible name. It projects no text and carries no label of its own,\n * so this string IS the name a screen reader reads for it.\n *\n * Keyed off `mode`, not fixed: `sanitiseChar` passes any letter through in\n * `alphanumeric` and `text`, so the old literal announced \"Digit 3\" over a box\n * holding `A` — wrong in a way translating it would not have fixed.\n */\n protected cellLabel(index: number): string {\n const params = { index: index + 1 };\n return this.mode() === 'numeric' ? this.digitLabel(params) : this.characterLabel(params);\n }\n\n // Internals\n\n private update(index: number, char: string): void {\n if (index < 0 || index >= this.length()) return;\n const next = [...this.cells()];\n next[index] = char;\n this.cells.set(next);\n this.emitChange();\n }\n\n private emitChange(): void {\n const code = this.cells().join('');\n this.value.set(code);\n if (code.length === this.length() && code.split('').every(c => c.length === 1)) {\n this.completed.emit(code);\n }\n }\n\n private focusCell(i: number): void {\n if (i < 0 || i >= this.length()) return;\n const el = this.cellRefs()[i]?.nativeElement;\n if (!el) return;\n el.focus();\n el.select();\n }\n\n /** Drop a character that doesn't match the configured mode. */\n private sanitiseChar(c: string): string {\n if (!c) return '';\n const one = c.slice(0, 1);\n switch (this.mode()) {\n case 'numeric':\n return /\\d/.test(one) ? one : '';\n case 'alphanumeric':\n return /[a-zA-Z0-9]/.test(one) ? one : '';\n case 'text':\n default:\n return one;\n }\n }\n\n /**\n * The key as the strip SEES it.\n *\n * The boxes run along the inline axis, so under `dir=\"rtl\"` the box to the\n * visual right of the caret is the PREVIOUS one. Home/End stay semantic (first\n * and last box), and Backspace is not a direction at all.\n */\n private inlineKey(key: string): string {\n if (this.dir?.value !== 'rtl') return key;\n if (key === 'ArrowRight') return 'ArrowLeft';\n if (key === 'ArrowLeft') return 'ArrowRight';\n return key;\n }\n}\n","@for (cell of cells(); track trackIndex($index)) {\n <input\n #cell\n class=\"wr-input-otp__cell\"\n [type]=\"cellType()\"\n [attr.inputmode]=\"cellInputMode()\"\n maxlength=\"1\"\n autocomplete=\"one-time-code\"\n autocapitalize=\"off\"\n spellcheck=\"false\"\n [value]=\"cell\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"cellLabel($index)\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n (input)=\"onInput($event, $index)\"\n (keydown)=\"onKeyDown($event, $index)\"\n (compositionend)=\"onCompositionEnd($event, $index)\"\n (paste)=\"onPaste($event)\"\n (blur)=\"onBlur()\"\n />\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-input-testing.mjs","sources":["../../../projects/lib/input/testing/wr-input-harness.ts","../../../projects/lib/input/testing/ngwr-input-testing.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 { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\n\nimport type { WrInputHarnessFilters } from './interfaces';\n\n/**\n * Test harness for `[wrInput]` — the directive form, on a real `<input>` or\n * `<textarea>`.\n *\n * There is no `<wr-input>` component to wrap: ngwr styles the native control in\n * place, which is why the value, the placeholder and the disabled state are all\n * read straight off the host. {@link setValue} dispatches `input` AND `change`,\n * because a signal-forms control listens to the first and classic `[(ngModel)]`\n * setups to the second — typing into only one of them makes a harness that works\n * in some consumers' specs and not others.\n *\n * @example\n * ```ts\n * const email = await loader.getHarness(WrInputHarness.with({ placeholder: 'Email' }));\n * await email.setValue('ada@example.test');\n * expect(await email.getValue()).toBe('ada@example.test');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrInputHarness extends ComponentHarness {\n static hostSelector = 'input[wrInput], textarea[wrInput]';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrInputHarnessFilters = {}): HarnessPredicate<WrInputHarness> {\n return new HarnessPredicate(WrInputHarness, options)\n .addOption('value', options.value, (harness, value) => HarnessPredicate.stringMatches(harness.getValue(), value))\n .addOption('placeholder', options.placeholder, (harness, placeholder) =>\n HarnessPredicate.stringMatches(harness.getPlaceholder(), placeholder)\n )\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n async getValue(): Promise<string> {\n return (await this.host()).getProperty<string>('value');\n }\n\n /**\n * Type a value in, the way a user would as far as the framework can tell.\n *\n * `input` is the one that carries the value — a signal-forms control listens to\n * it, and so does Angular's `DefaultValueAccessor`, which is what `[(ngModel)]`\n * and a reactive form bind through (its listeners are `input`, `blur` and the\n * two composition events; `change` is NOT among them). `change` is dispatched\n * after it for the consumer's own `(change)` handler: a browser defers that\n * event to the commit — blur, or Enter — which a harness write never reaches, so\n * a spec binding it would otherwise never see it fire.\n */\n async setValue(value: string): Promise<void> {\n const host = await this.host();\n await host.clear();\n await host.sendKeys(value);\n await host.dispatchEvent('change');\n }\n\n /** Clear the field, dispatching the same pair of events as {@link setValue}. */\n async clear(): Promise<void> {\n const host = await this.host();\n await host.clear();\n await host.dispatchEvent('change');\n }\n\n async getPlaceholder(): Promise<string> {\n return (await this.host()).getProperty<string>('placeholder');\n }\n\n async isDisabled(): Promise<boolean> {\n return (await this.host()).getProperty<boolean>('disabled');\n }\n\n async isReadonly(): Promise<boolean> {\n return (await this.host()).getProperty<boolean>('readOnly');\n }\n\n /** `input` or `textarea` — the directive styles both. */\n async getTagName(): Promise<string> {\n return (await (await this.host()).getProperty<string>('tagName')).toLowerCase();\n }\n\n /**\n * Whether the field is marked invalid.\n *\n * `<wr-form-field>` sets `aria-invalid` when it has an error to describe, so\n * this answers what a screen reader is told rather than what the model thinks.\n */\n async isInvalid(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-invalid')) === 'true';\n }\n\n async focus(): Promise<void> {\n return (await this.host()).focus();\n }\n\n async blur(): Promise<void> {\n return (await this.host()).blur();\n }\n\n async isFocused(): Promise<boolean> {\n return (await this.host()).isFocused();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAMH;;;;;;;;;;;;;;;;;;;AAmBG;AACG,MAAO,cAAe,SAAQ,gBAAgB,CAAA;AAClD,IAAA,OAAO,YAAY,GAAG,mCAAmC;;AAGzD,IAAA,OAAO,IAAI,CAAC,OAAA,GAAiC,EAAE,EAAA;AAC7C,QAAA,OAAO,IAAI,gBAAgB,CAAC,cAAc,EAAE,OAAO;aAChD,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,KAAK,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC;aAC/G,SAAS,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,WAAW,KAClE,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,WAAW,CAAC;aAEtE,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,MAAM,QAAQ,CAAC;IACpH;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,CAAS,OAAO,CAAC;IACzD;AAEA;;;;;;;;;;AAUG;IACH,MAAM,QAAQ,CAAC,KAAa,EAAA;AAC1B,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;AAC9B,QAAA,MAAM,IAAI,CAAC,KAAK,EAAE;AAClB,QAAA,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC1B,QAAA,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC;IACpC;;AAGA,IAAA,MAAM,KAAK,GAAA;AACT,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;AAC9B,QAAA,MAAM,IAAI,CAAC,KAAK,EAAE;AAClB,QAAA,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC;IACpC;AAEA,IAAA,MAAM,cAAc,GAAA;AAClB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,CAAS,aAAa,CAAC;IAC/D;AAEA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,CAAU,UAAU,CAAC;IAC7D;AAEA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,CAAU,UAAU,CAAC;IAC7D;;AAGA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,CAAS,SAAS,CAAC,EAAE,WAAW,EAAE;IACjF;AAEA;;;;;AAKG;AACH,IAAA,MAAM,SAAS,GAAA;AACb,QAAA,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,cAAc,CAAC,MAAM,MAAM;IAC5E;AAEA,IAAA,MAAM,KAAK,GAAA;QACT,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE;IACpC;AAEA,IAAA,MAAM,IAAI,GAAA;QACR,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE;IACnC;AAEA,IAAA,MAAM,SAAS,GAAA;QACb,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE;IACxC;;;AC9GF;;AAEG;;;;"}
1
+ {"version":3,"file":"ngwr-input-testing.mjs","sources":["../../../projects/lib/input/testing/wr-input-harness.ts","../../../projects/lib/input/testing/ngwr-input-testing.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 { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\n\nimport type { WrInputHarnessFilters } from './interfaces';\n\n/**\n * Test harness for `[wrInput]` — the directive form, on a real `<input>` or\n * `<textarea>`.\n *\n * There is no `<wr-input>` component to wrap: ngwr styles the native control in\n * place, which is why the value, the placeholder and the disabled state are all\n * read straight off the host. {@link setValue} dispatches `input` AND `change`,\n * because a signal-forms control listens to the first and classic `[(ngModel)]`\n * setups to the second — typing into only one of them makes a harness that works\n * in some consumers' specs and not others.\n *\n * @example\n * ```ts\n * const email = await loader.getHarness(WrInputHarness.with({ placeholder: 'Email' }));\n * await email.setValue('ada@example.test');\n * expect(await email.getValue()).toBe('ada@example.test');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrInputHarness extends ComponentHarness {\n static hostSelector = 'input[wrInput], textarea[wrInput]';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrInputHarnessFilters = {}): HarnessPredicate<WrInputHarness> {\n return new HarnessPredicate(WrInputHarness, options)\n .addOption('value', options.value, (harness, value) => HarnessPredicate.stringMatches(harness.getValue(), value))\n .addOption('placeholder', options.placeholder, (harness, placeholder) =>\n HarnessPredicate.stringMatches(harness.getPlaceholder(), placeholder)\n )\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n async getValue(): Promise<string> {\n return (await this.host()).getProperty<string>('value');\n }\n\n /**\n * Type a value in, the way a user would as far as the framework can tell.\n *\n * `input` is the one that carries the value — a signal-forms control listens to\n * it, and so does Angular's `DefaultValueAccessor`, which is what `[(ngModel)]`\n * and a reactive form bind through (its listeners are `input`, `blur` and the\n * two composition events; `change` is NOT among them). `change` is dispatched\n * after it for the consumer's own `(change)` handler: a browser defers that\n * event to the commit — blur, or Enter — which a harness write never reaches, so\n * a spec binding it would otherwise never see it fire.\n */\n async setValue(value: string): Promise<void> {\n const host = await this.host();\n await host.clear();\n await host.sendKeys(value);\n await host.dispatchEvent('change');\n }\n\n /** Clear the field, dispatching the same pair of events as {@link setValue}. */\n async clear(): Promise<void> {\n const host = await this.host();\n await host.clear();\n await host.dispatchEvent('change');\n }\n\n async getPlaceholder(): Promise<string> {\n return (await this.host()).getProperty<string>('placeholder');\n }\n\n async isDisabled(): Promise<boolean> {\n return (await this.host()).getProperty<boolean>('disabled');\n }\n\n async isReadonly(): Promise<boolean> {\n return (await this.host()).getProperty<boolean>('readOnly');\n }\n\n /** `input` or `textarea` — the directive styles both. */\n async getTagName(): Promise<string> {\n return (await (await this.host()).getProperty<string>('tagName')).toLowerCase();\n }\n\n /**\n * Whether the field is marked invalid.\n *\n * `<wr-form-field>` sets `aria-invalid` when it has an error to describe, so\n * this answers what a screen reader is told rather than what the model thinks.\n */\n async isInvalid(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-invalid')) === 'true';\n }\n\n async focus(): Promise<void> {\n return (await this.host()).focus();\n }\n\n async blur(): Promise<void> {\n return (await this.host()).blur();\n }\n\n async isFocused(): Promise<boolean> {\n return (await this.host()).isFocused();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAMH;;;;;;;;;;;;;;;;;;;AAmBG;AACG,MAAO,cAAe,SAAQ,gBAAgB,CAAA;AAClD,IAAA,OAAO,YAAY,GAAG,mCAAmC;;AAGzD,IAAA,OAAO,IAAI,CAAC,OAAA,GAAiC,EAAE,EAAA;AAC7C,QAAA,OAAO,IAAI,gBAAgB,CAAC,cAAc,EAAE,OAAO;aAChD,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,KAAK,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC;aAC/G,SAAS,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,WAAW,KAClE,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,WAAW,CAAC;aAEtE,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,MAAM,QAAQ,CAAC;IACpH;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,CAAS,OAAO,CAAC;IACzD;AAEA;;;;;;;;;;AAUG;IACH,MAAM,QAAQ,CAAC,KAAa,EAAA;AAC1B,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;AAC9B,QAAA,MAAM,IAAI,CAAC,KAAK,EAAE;AAClB,QAAA,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC1B,QAAA,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC;IACpC;;AAGA,IAAA,MAAM,KAAK,GAAA;AACT,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;AAC9B,QAAA,MAAM,IAAI,CAAC,KAAK,EAAE;AAClB,QAAA,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC;IACpC;AAEA,IAAA,MAAM,cAAc,GAAA;AAClB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,CAAS,aAAa,CAAC;IAC/D;AAEA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,CAAU,UAAU,CAAC;IAC7D;AAEA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,CAAU,UAAU,CAAC;IAC7D;;AAGA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,CAAS,SAAS,CAAC,EAAE,WAAW,EAAE;IACjF;AAEA;;;;;AAKG;AACH,IAAA,MAAM,SAAS,GAAA;AACb,QAAA,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,cAAc,CAAC,MAAM,MAAM;IAC5E;AAEA,IAAA,MAAM,KAAK,GAAA;QACT,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE;IACpC;AAEA,IAAA,MAAM,IAAI,GAAA;QACR,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE;IACnC;AAEA,IAAA,MAAM,SAAS,GAAA;QACb,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE;IACxC;;;AC9GF;;AAEG;;"}
@@ -112,10 +112,10 @@ class WrInput {
112
112
  return parts.join(' ');
113
113
  }, /* @ts-ignore */
114
114
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
115
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrInput, deps: [], target: i0.ɵɵFactoryTarget.Directive });
116
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.6", type: WrInput, isStandalone: true, selector: "input[wrInput], textarea[wrInput]", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()", "attr.id": "resolvedId()", "attr.aria-invalid": "ariaInvalid()", "attr.aria-describedby": "describedBy()" } }, ngImport: i0 });
115
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrInput, deps: [], target: i0.ɵɵFactoryTarget.Directive });
116
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: WrInput, isStandalone: true, selector: "input[wrInput], textarea[wrInput]", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()", "attr.id": "resolvedId()", "attr.aria-invalid": "ariaInvalid()", "attr.aria-describedby": "describedBy()" } }, ngImport: i0 });
117
117
  }
118
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrInput, decorators: [{
118
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrInput, decorators: [{
119
119
  type: Directive,
120
120
  args: [{
121
121
  selector: 'input[wrInput], textarea[wrInput]',
@@ -148,10 +148,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
148
148
  * ```
149
149
  */
150
150
  class WrInputPrefix {
151
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrInputPrefix, deps: [], target: i0.ɵɵFactoryTarget.Directive });
152
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: WrInputPrefix, isStandalone: true, selector: "[wrInputPrefix]", host: { classAttribute: "wr-input-group__affix wr-input-group__affix--prefix" }, ngImport: i0 });
151
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrInputPrefix, deps: [], target: i0.ɵɵFactoryTarget.Directive });
152
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: WrInputPrefix, isStandalone: true, selector: "[wrInputPrefix]", host: { classAttribute: "wr-input-group__affix wr-input-group__affix--prefix" }, ngImport: i0 });
153
153
  }
154
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrInputPrefix, decorators: [{
154
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrInputPrefix, decorators: [{
155
155
  type: Directive,
156
156
  args: [{
157
157
  selector: '[wrInputPrefix]',
@@ -179,10 +179,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
179
179
  * ```
180
180
  */
181
181
  class WrInputSuffix {
182
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrInputSuffix, deps: [], target: i0.ɵɵFactoryTarget.Directive });
183
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: WrInputSuffix, isStandalone: true, selector: "[wrInputSuffix]", host: { classAttribute: "wr-input-group__affix wr-input-group__affix--suffix" }, ngImport: i0 });
182
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrInputSuffix, deps: [], target: i0.ɵɵFactoryTarget.Directive });
183
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: WrInputSuffix, isStandalone: true, selector: "[wrInputSuffix]", host: { classAttribute: "wr-input-group__affix wr-input-group__affix--suffix" }, ngImport: i0 });
184
184
  }
185
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrInputSuffix, decorators: [{
185
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrInputSuffix, decorators: [{
186
186
  type: Directive,
187
187
  args: [{
188
188
  selector: '[wrInputSuffix]',
@@ -239,10 +239,10 @@ class WrInputGroup {
239
239
  return parts.join(' ');
240
240
  }, /* @ts-ignore */
241
241
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
242
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrInputGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
243
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: WrInputGroup, isStandalone: true, selector: "wr-input-group", inputs: { rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: '<ng-content />', isInline: true, encapsulation: i0.ViewEncapsulation.None });
242
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrInputGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
243
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.7", type: WrInputGroup, isStandalone: true, selector: "wr-input-group", inputs: { rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: '<ng-content />', isInline: true, encapsulation: i0.ViewEncapsulation.None });
244
244
  }
245
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrInputGroup, decorators: [{
245
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrInputGroup, decorators: [{
246
246
  type: Component,
247
247
  args: [{
248
248
  selector: 'wr-input-group',
@@ -293,10 +293,10 @@ class WrPasswordToggle {
293
293
  input.type = next;
294
294
  this.revealed.set(next === 'text');
295
295
  }
296
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrPasswordToggle, deps: [], target: i0.ɵɵFactoryTarget.Component });
297
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrPasswordToggle, isStandalone: true, selector: "wr-password-toggle", inputs: { for: { classPropertyName: "for", publicName: "for", isSignal: true, isRequired: true, transformFunction: null }, showLabel: { classPropertyName: "showLabel", publicName: "showLabel", isSignal: true, isRequired: false, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<button\n type=\"button\"\n class=\"wr-input-group__toggle\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-pressed]=\"revealed()\"\n (click)=\"toggle()\"\n>\n @if (revealed()) {\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=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\" />\n <path d=\"M14.084 14.158a3 3 0 0 1-4.242-4.242\" />\n <path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\" />\n <path d=\"m2 2 20 20\" />\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 <path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n }\n</button>\n", encapsulation: i0.ViewEncapsulation.None });
296
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrPasswordToggle, deps: [], target: i0.ɵɵFactoryTarget.Component });
297
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: WrPasswordToggle, isStandalone: true, selector: "wr-password-toggle", inputs: { for: { classPropertyName: "for", publicName: "for", isSignal: true, isRequired: true, transformFunction: null }, showLabel: { classPropertyName: "showLabel", publicName: "showLabel", isSignal: true, isRequired: false, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<button\n type=\"button\"\n class=\"wr-input-group__toggle\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-pressed]=\"revealed()\"\n (click)=\"toggle()\"\n>\n @if (revealed()) {\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=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\" />\n <path d=\"M14.084 14.158a3 3 0 0 1-4.242-4.242\" />\n <path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\" />\n <path d=\"m2 2 20 20\" />\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 <path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n }\n</button>\n", encapsulation: i0.ViewEncapsulation.None });
298
298
  }
299
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrPasswordToggle, decorators: [{
299
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrPasswordToggle, decorators: [{
300
300
  type: Component,
301
301
  args: [{ selector: 'wr-password-toggle', encapsulation: ViewEncapsulation.None, template: "<button\n type=\"button\"\n class=\"wr-input-group__toggle\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-pressed]=\"revealed()\"\n (click)=\"toggle()\"\n>\n @if (revealed()) {\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=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\" />\n <path d=\"M14.084 14.158a3 3 0 0 1-4.242-4.242\" />\n <path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\" />\n <path d=\"m2 2 20 20\" />\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 <path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n }\n</button>\n" }]
302
302
  }], propDecorators: { for: [{ type: i0.Input, args: [{ isSignal: true, alias: "for", required: true }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], hideLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLabel", required: false }] }] } });
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-input.mjs","sources":["../../../projects/lib/input/directives/wr-input.ts","../../../projects/lib/input/directives/wr-input-prefix.ts","../../../projects/lib/input/directives/wr-input-suffix.ts","../../../projects/lib/input/input-group.ts","../../../projects/lib/input/password-toggle.ts","../../../projects/lib/input/password-toggle.html","../../../projects/lib/input/ngwr-input.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 BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Directive, ElementRef, computed, inject, input } from '@angular/core';\n\nimport { useConfigValue } from 'ngwr/config';\nimport { WR_FORM_FIELD, useFormFieldAria } from 'ngwr/form';\n\nimport type { WrInputSize } from '../interfaces';\n\n/**\n * Applies NGWR input styling to a native `<input>` element.\n *\n * Because this is an attribute directive on the real `<input>` (not a wrapper\n * component), any other directive that targets `input` — `[(ngModel)]`,\n * `[formControl]`, validators, third-party libraries like `ngx-mask` — composes\n * naturally on the same element.\n *\n * @example\n * ```html\n * <input wrInput [(ngModel)]=\"name\" placeholder=\"Your name\" />\n *\n * <!-- Works with ngx-mask, validators, etc. -->\n * <input wrInput [(ngModel)]=\"phone\" mask=\"(000) 000-0000\" />\n * ```\n *\n * For prefix / suffix / password-toggle layouts, wrap the input in\n * `<wr-input-group>`.\n *\n * @see https://ngwr.dev/reference/components/input\n */\n@Directive({\n selector: 'input[wrInput], textarea[wrInput]',\n host: {\n '[class]': 'classes()',\n '[attr.id]': 'resolvedId()',\n '[attr.aria-invalid]': 'ariaInvalid()',\n '[attr.aria-describedby]': 'describedBy()',\n },\n})\nexport class WrInput {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly field = inject(WR_FORM_FIELD, { optional: true });\n\n /**\n * Read once, at construction: a static `id=\"\"` in the template is already on\n * the element by the time a directive is instantiated, and it must win over\n * the field's generated one.\n */\n private readonly ownId = this.host.nativeElement.getAttribute('id');\n\n /**\n * Adopts the surrounding `<wr-form-field>`'s `controlId`, so the label it\n * already rendered actually points at this element. Without this the `for`\n * referenced an id that existed nowhere and the input had no label at all.\n */\n protected readonly resolvedId = computed(() => this.ownId ?? this.field?.controlId() ?? null);\n\n constructor() {\n // Tell the field which id actually stuck. Without this its `<label for>` keeps\n // pointing at the generated id while this element answers to the author's own —\n // a label referencing nothing, which is the same as having none.\n if (this.ownId) this.field?.adoptControlId(this.ownId);\n }\n\n /**\n * Announced state, taken from the surrounding `<wr-form-field>`.\n *\n * The field renders the message but cannot reach the projected control, so\n * the control reads back: without this the error is visible on screen and\n * invisible to a screen reader, which never learns the field is invalid or\n * what the message says.\n */\n // Through the shared helper, not a local pair: the hint is described by\n // `hintId`, which only `useFormFieldAria()` composes, and `aria-invalid` keys\n // on the error COUNT rather than on \"something is described\". Hand-rolled here,\n // these three announced the error and never the hint — and `<input wrInput>` is\n // the control the report was filed against.\n private readonly fieldAria = useFormFieldAria();\n protected readonly describedBy = this.fieldAria.describedBy;\n protected readonly ariaInvalid = this.fieldAria.ariaInvalid;\n\n /**\n * Control size. Unset, it falls back to\n * `provideWrConfig({ input: { size } })`. @default 'md'\n *\n * Called `wrSize` until v14, to dodge the native `<input size>` attribute —\n * which measures the field in characters and which `.wr-input`'s `width: 100%`\n * has always overridden, so the clash it guarded against was never observable.\n * It made this the one size input in the catalog spelled differently from the\n * other twenty-three. The cost of the change is that a consumer who wanted the\n * NATIVE `size` on an ngwr input can no longer have it — but `width: 100%`\n * meant they never did.\n */\n readonly size = input<WrInputSize | null>(null);\n\n /**\n * Pill-shaped corners. Unset, it falls back to\n * `provideWrConfig({ input: { rounded } })`; `[rounded]=\"false\"` turns a\n * configured `true` back off. @default false\n */\n readonly rounded = input<boolean | null, BooleanInput>(null, {\n // Null-preserving: the plain `coerceBooleanProperty` folds `null` into `false`,\n // which would make \"not set\" and \"set to false\" the same value — and a config\n // default nothing could ever supply. A valueless `rounded` attribute still\n // arrives as `''` and still coerces to `true`.\n transform: (v: BooleanInput): boolean | null => (v == null ? null : coerceBooleanProperty(v)),\n });\n\n // `null` as each input's own default, not `'md'` / `false`: with a literal sitting\n // there, \"the template said nothing\" and \"the template said md\" are the same value,\n // so no app-wide default could ever apply. The effective default is the last\n // argument below, which is where the old inline one moved to.\n protected readonly resolvedSize = useConfigValue(this.size, c => c.input?.size, 'md');\n protected readonly resolvedRounded = useConfigValue(this.rounded, c => c.input?.rounded, false);\n\n protected readonly classes = computed(() => {\n const parts = ['wr-input'];\n const size = this.resolvedSize();\n if (size !== 'md') parts.push(`wr-input--${size}`);\n if (this.resolvedRounded()) parts.push('wr-input--rounded');\n return parts.join(' ');\n });\n}\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 { Directive } from '@angular/core';\n\n/**\n * Marks an element as the **left** decoration inside `<wr-input-group>`.\n * Adds the `.wr-input-group__affix` class so the group's layout flexes it\n * to the input's left edge.\n *\n * @example\n * ```html\n * <wr-input-group>\n * <span wrInputPrefix>$</span>\n * <input wrInput [(ngModel)]=\"amount\" type=\"number\" />\n * </wr-input-group>\n * ```\n */\n@Directive({\n selector: '[wrInputPrefix]',\n host: { class: 'wr-input-group__affix wr-input-group__affix--prefix' },\n})\nexport class WrInputPrefix {}\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 { Directive } from '@angular/core';\n\n/**\n * Marks an element as the **right** decoration inside `<wr-input-group>`.\n * Adds the `.wr-input-group__affix` class so the group's layout flexes it\n * to the input's right edge.\n *\n * @example\n * ```html\n * <wr-input-group>\n * <input wrInput [(ngModel)]=\"amount\" type=\"number\" />\n * <span wrInputSuffix>USD</span>\n * </wr-input-group>\n * ```\n */\n@Directive({\n selector: '[wrInputSuffix]',\n host: { class: 'wr-input-group__affix wr-input-group__affix--suffix' },\n})\nexport class WrInputSuffix {}\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 { type BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\nimport { useConfigValue } from 'ngwr/config';\n\n/**\n * Container for `<input wrInput>` + `[wrInputPrefix]` / `[wrInputSuffix]` /\n * `<wr-password-toggle>` siblings. Renders the border and focus ring; the\n * inner native input drops its own border so it visually melts into the\n * group.\n *\n * Pure layout — no signals shared with the inner directive, focus styling is\n * driven entirely by `:focus-within` so any focusable child counts.\n *\n * @example\n * ```html\n * <wr-input-group>\n * <span wrInputPrefix>$</span>\n * <input wrInput [(ngModel)]=\"amount\" type=\"number\" />\n * <span wrInputSuffix>USD</span>\n * </wr-input-group>\n * ```\n *\n * @see https://ngwr.dev/reference/components/input\n */\n@Component({\n selector: 'wr-input-group',\n template: '<ng-content />',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n})\nexport class WrInputGroup {\n /**\n * Pill-shaped corners. Unset, it falls back to\n * `provideWrConfig({ input: { rounded } })` — the same key the inner `[wrInput]`\n * reads. @default false\n */\n readonly rounded = input<boolean | null, BooleanInput>(null, {\n // Null-preserving, like `[wrInput]`'s: the plain `coerceBooleanProperty` folds\n // `null` into `false`, which would make \"not set\" and \"set to false\" the same\n // value — and a config default nothing could ever supply.\n transform: (v: BooleanInput): boolean | null => (v == null ? null : coerceBooleanProperty(v)),\n });\n\n // `input.rounded`, and deliberately not a key of its own: the group owns the visible\n // border once it wraps an input, which drops its own chrome. Resolving one and not\n // the other would put a pill radius on the element nobody can see and leave the\n // corner the user does see square.\n protected readonly resolvedRounded = useConfigValue(this.rounded, c => c.input?.rounded, false);\n\n protected readonly classes = computed(() => {\n const parts = ['wr-input-group'];\n if (this.resolvedRounded()) parts.push('wr-input-group--rounded');\n return parts.join(' ');\n });\n}\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 { Component, ViewEncapsulation, computed, input, signal } from '@angular/core';\n\nimport { useI18nText } from 'ngwr/i18n';\n\n/**\n * Self-contained eye-toggle button. Flips the linked `<input>`'s `type`\n * attribute between `password` and `text`. Drop it inside an\n * `<wr-input-group>` next to a password input.\n *\n * @example\n * ```html\n * <wr-input-group>\n * <input wrInput type=\"password\" [(ngModel)]=\"pw\" #pwInput />\n * <wr-password-toggle [for]=\"pwInput\" />\n * </wr-input-group>\n * ```\n */\n@Component({\n selector: 'wr-password-toggle',\n templateUrl: './password-toggle.html',\n encapsulation: ViewEncapsulation.None,\n})\nexport class WrPasswordToggle {\n /** Reference to the linked password input. */\n readonly for = input.required<HTMLInputElement>();\n\n protected readonly revealed = signal(false);\n\n /** Accessible name while the password is hidden. Falls back to `input.showPassword`. */\n readonly showLabel = input<string | null>(null);\n\n /** Accessible name while the password is revealed. Falls back to `input.hidePassword`. */\n readonly hideLabel = input<string | null>(null);\n\n private readonly resolvedShowLabel = useI18nText(this.showLabel, 'input.showPassword', 'Show password');\n private readonly resolvedHideLabel = useI18nText(this.hideLabel, 'input.hidePassword', 'Hide password');\n\n protected readonly ariaLabel = computed(() =>\n this.revealed() ? this.resolvedHideLabel() : this.resolvedShowLabel()\n );\n\n protected toggle(): void {\n const input = this.for();\n const next = input.type === 'password' ? 'text' : 'password';\n input.type = next;\n this.revealed.set(next === 'text');\n }\n}\n","<button\n type=\"button\"\n class=\"wr-input-group__toggle\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-pressed]=\"revealed()\"\n (click)=\"toggle()\"\n>\n @if (revealed()) {\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=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\" />\n <path d=\"M14.084 14.158a3 3 0 0 1-4.242-4.242\" />\n <path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\" />\n <path d=\"m2 2 20 20\" />\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 <path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n }\n</button>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;AAAA;;;;;AAKG;AAUH;;;;;;;;;;;;;;;;;;;;AAoBG;MAUU,OAAO,CAAA;AACD,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC;IAClD,KAAK,GAAG,MAAM,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAElE;;;;AAIG;IACc,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC;AAEnE;;;;AAIG;AACgB,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,IAAI;mFAAC;AAE7F,IAAA,WAAA,GAAA;;;;QAIE,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC;IACxD;AAEA;;;;;;;AAOG;;;;;;IAMc,SAAS,GAAG,gBAAgB,EAAE;AAC5B,IAAA,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW;AACxC,IAAA,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW;AAE3D;;;;;;;;;;;AAWG;IACM,IAAI,GAAG,KAAK,CAAqB,IAAI;6EAAC;AAE/C;;;;AAIG;IACM,OAAO,GAAG,KAAK,CAA+B,IAAI,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,SAAA,EAAA,8BAAA,EAAA,CAAA;;;;;QAKzD,SAAS,EAAE,CAAC,CAAe,MAAsB,CAAC,IAAI,IAAI,GAAG,IAAI,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC,EAAA,CAC7F;;;;;AAMiB,IAAA,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC;AAClE,IAAA,eAAe,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC;AAE5E,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AACzC,QAAA,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC;AAC1B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE;QAChC,IAAI,IAAI,KAAK,IAAI;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAA,CAAE,CAAC;QAClD,IAAI,IAAI,CAAC,eAAe,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;AAC3D,QAAA,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;IACxB,CAAC;gFAAC;uGAlFS,OAAO,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAP,OAAO,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mCAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,WAAA,EAAA,SAAA,EAAA,cAAA,EAAA,mBAAA,EAAA,eAAA,EAAA,uBAAA,EAAA,eAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAP,OAAO,EAAA,UAAA,EAAA,CAAA;kBATnB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,mCAAmC;AAC7C,oBAAA,IAAI,EAAE;AACJ,wBAAA,SAAS,EAAE,WAAW;AACtB,wBAAA,WAAW,EAAE,cAAc;AAC3B,wBAAA,qBAAqB,EAAE,eAAe;AACtC,wBAAA,yBAAyB,EAAE,eAAe;AAC3C,qBAAA;AACF,iBAAA;;;AC5CD;;;;;AAKG;AAIH;;;;;;;;;;;;AAYG;MAKU,aAAa,CAAA;uGAAb,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAb,aAAa,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,qDAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAb,aAAa,EAAA,UAAA,EAAA,CAAA;kBAJzB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,iBAAiB;AAC3B,oBAAA,IAAI,EAAE,EAAE,KAAK,EAAE,qDAAqD,EAAE;AACvE,iBAAA;;;ACzBD;;;;;AAKG;AAIH;;;;;;;;;;;;AAYG;MAKU,aAAa,CAAA;uGAAb,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAb,aAAa,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,qDAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAb,aAAa,EAAA,UAAA,EAAA,CAAA;kBAJzB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,iBAAiB;AAC3B,oBAAA,IAAI,EAAE,EAAE,KAAK,EAAE,qDAAqD,EAAE;AACvE,iBAAA;;;ACzBD;;;;;AAKG;AAOH;;;;;;;;;;;;;;;;;;;AAmBG;MAOU,YAAY,CAAA;AACvB;;;;AAIG;IACM,OAAO,GAAG,KAAK,CAA+B,IAAI,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,SAAA,EAAA,8BAAA,EAAA,CAAA;;;;QAIzD,SAAS,EAAE,CAAC,CAAe,MAAsB,CAAC,IAAI,IAAI,GAAG,IAAI,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC,EAAA,CAC7F;;;;;AAMiB,IAAA,eAAe,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC;AAE5E,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AACzC,QAAA,MAAM,KAAK,GAAG,CAAC,gBAAgB,CAAC;QAChC,IAAI,IAAI,CAAC,eAAe,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC;AACjE,QAAA,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;IACxB,CAAC;gFAAC;uGAvBS,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAZ,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAY,oQAJb,gBAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAIf,YAAY,EAAA,UAAA,EAAA,CAAA;kBANxB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,gBAAgB;AAC1B,oBAAA,QAAQ,EAAE,gBAAgB;oBAC1B,aAAa,EAAE,iBAAiB,CAAC,IAAI;AACrC,oBAAA,IAAI,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE;AACjC,iBAAA;;;ACrCD;;;;;AAKG;AAMH;;;;;;;;;;;;AAYG;MAMU,gBAAgB,CAAA;;IAElB,GAAG,GAAG,KAAK,CAAC,QAAQ;4EAAoB;IAE9B,QAAQ,GAAG,MAAM,CAAC,KAAK;iFAAC;;IAGlC,SAAS,GAAG,KAAK,CAAgB,IAAI;kFAAC;;IAGtC,SAAS,GAAG,KAAK,CAAgB,IAAI;kFAAC;IAE9B,iBAAiB,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,EAAE,eAAe,CAAC;IACtF,iBAAiB,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,EAAE,eAAe,CAAC;IAEpF,SAAS,GAAG,QAAQ,CAAC,MACtC,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,iBAAiB,EAAE,GAAG,IAAI,CAAC,iBAAiB,EAAE;kFACtE;IAES,MAAM,GAAA;AACd,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE;AACxB,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,UAAU,GAAG,MAAM,GAAG,UAAU;AAC5D,QAAA,KAAK,CAAC,IAAI,GAAG,IAAI;QACjB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC;IACpC;uGAxBW,gBAAgB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAhB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,gBAAgB,mdC7B7B,uyCAyCA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FDZa,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBAL5B,SAAS;+BACE,oBAAoB,EAAA,aAAA,EAEf,iBAAiB,CAAC,IAAI,EAAA,QAAA,EAAA,uyCAAA,EAAA;;;AE3BvC;;AAEG;;;;"}
1
+ {"version":3,"file":"ngwr-input.mjs","sources":["../../../projects/lib/input/directives/wr-input.ts","../../../projects/lib/input/directives/wr-input-prefix.ts","../../../projects/lib/input/directives/wr-input-suffix.ts","../../../projects/lib/input/input-group.ts","../../../projects/lib/input/password-toggle.ts","../../../projects/lib/input/password-toggle.html","../../../projects/lib/input/ngwr-input.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 BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Directive, ElementRef, computed, inject, input } from '@angular/core';\n\nimport { useConfigValue } from 'ngwr/config';\nimport { WR_FORM_FIELD, useFormFieldAria } from 'ngwr/form';\n\nimport type { WrInputSize } from '../interfaces';\n\n/**\n * Applies NGWR input styling to a native `<input>` element.\n *\n * Because this is an attribute directive on the real `<input>` (not a wrapper\n * component), any other directive that targets `input` — `[(ngModel)]`,\n * `[formControl]`, validators, third-party libraries like `ngx-mask` — composes\n * naturally on the same element.\n *\n * @example\n * ```html\n * <input wrInput [(ngModel)]=\"name\" placeholder=\"Your name\" />\n *\n * <!-- Works with ngx-mask, validators, etc. -->\n * <input wrInput [(ngModel)]=\"phone\" mask=\"(000) 000-0000\" />\n * ```\n *\n * For prefix / suffix / password-toggle layouts, wrap the input in\n * `<wr-input-group>`.\n *\n * @see https://ngwr.dev/reference/components/input\n */\n@Directive({\n selector: 'input[wrInput], textarea[wrInput]',\n host: {\n '[class]': 'classes()',\n '[attr.id]': 'resolvedId()',\n '[attr.aria-invalid]': 'ariaInvalid()',\n '[attr.aria-describedby]': 'describedBy()',\n },\n})\nexport class WrInput {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly field = inject(WR_FORM_FIELD, { optional: true });\n\n /**\n * Read once, at construction: a static `id=\"\"` in the template is already on\n * the element by the time a directive is instantiated, and it must win over\n * the field's generated one.\n */\n private readonly ownId = this.host.nativeElement.getAttribute('id');\n\n /**\n * Adopts the surrounding `<wr-form-field>`'s `controlId`, so the label it\n * already rendered actually points at this element. Without this the `for`\n * referenced an id that existed nowhere and the input had no label at all.\n */\n protected readonly resolvedId = computed(() => this.ownId ?? this.field?.controlId() ?? null);\n\n constructor() {\n // Tell the field which id actually stuck. Without this its `<label for>` keeps\n // pointing at the generated id while this element answers to the author's own —\n // a label referencing nothing, which is the same as having none.\n if (this.ownId) this.field?.adoptControlId(this.ownId);\n }\n\n /**\n * Announced state, taken from the surrounding `<wr-form-field>`.\n *\n * The field renders the message but cannot reach the projected control, so\n * the control reads back: without this the error is visible on screen and\n * invisible to a screen reader, which never learns the field is invalid or\n * what the message says.\n */\n // Through the shared helper, not a local pair: the hint is described by\n // `hintId`, which only `useFormFieldAria()` composes, and `aria-invalid` keys\n // on the error COUNT rather than on \"something is described\". Hand-rolled here,\n // these three announced the error and never the hint — and `<input wrInput>` is\n // the control the report was filed against.\n private readonly fieldAria = useFormFieldAria();\n protected readonly describedBy = this.fieldAria.describedBy;\n protected readonly ariaInvalid = this.fieldAria.ariaInvalid;\n\n /**\n * Control size. Unset, it falls back to\n * `provideWrConfig({ input: { size } })`. @default 'md'\n *\n * Called `wrSize` until v14, to dodge the native `<input size>` attribute —\n * which measures the field in characters and which `.wr-input`'s `width: 100%`\n * has always overridden, so the clash it guarded against was never observable.\n * It made this the one size input in the catalog spelled differently from the\n * other twenty-three. The cost of the change is that a consumer who wanted the\n * NATIVE `size` on an ngwr input can no longer have it — but `width: 100%`\n * meant they never did.\n */\n readonly size = input<WrInputSize | null>(null);\n\n /**\n * Pill-shaped corners. Unset, it falls back to\n * `provideWrConfig({ input: { rounded } })`; `[rounded]=\"false\"` turns a\n * configured `true` back off. @default false\n */\n readonly rounded = input<boolean | null, BooleanInput>(null, {\n // Null-preserving: the plain `coerceBooleanProperty` folds `null` into `false`,\n // which would make \"not set\" and \"set to false\" the same value — and a config\n // default nothing could ever supply. A valueless `rounded` attribute still\n // arrives as `''` and still coerces to `true`.\n transform: (v: BooleanInput): boolean | null => (v == null ? null : coerceBooleanProperty(v)),\n });\n\n // `null` as each input's own default, not `'md'` / `false`: with a literal sitting\n // there, \"the template said nothing\" and \"the template said md\" are the same value,\n // so no app-wide default could ever apply. The effective default is the last\n // argument below, which is where the old inline one moved to.\n protected readonly resolvedSize = useConfigValue(this.size, c => c.input?.size, 'md');\n protected readonly resolvedRounded = useConfigValue(this.rounded, c => c.input?.rounded, false);\n\n protected readonly classes = computed(() => {\n const parts = ['wr-input'];\n const size = this.resolvedSize();\n if (size !== 'md') parts.push(`wr-input--${size}`);\n if (this.resolvedRounded()) parts.push('wr-input--rounded');\n return parts.join(' ');\n });\n}\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 { Directive } from '@angular/core';\n\n/**\n * Marks an element as the **left** decoration inside `<wr-input-group>`.\n * Adds the `.wr-input-group__affix` class so the group's layout flexes it\n * to the input's left edge.\n *\n * @example\n * ```html\n * <wr-input-group>\n * <span wrInputPrefix>$</span>\n * <input wrInput [(ngModel)]=\"amount\" type=\"number\" />\n * </wr-input-group>\n * ```\n */\n@Directive({\n selector: '[wrInputPrefix]',\n host: { class: 'wr-input-group__affix wr-input-group__affix--prefix' },\n})\nexport class WrInputPrefix {}\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 { Directive } from '@angular/core';\n\n/**\n * Marks an element as the **right** decoration inside `<wr-input-group>`.\n * Adds the `.wr-input-group__affix` class so the group's layout flexes it\n * to the input's right edge.\n *\n * @example\n * ```html\n * <wr-input-group>\n * <input wrInput [(ngModel)]=\"amount\" type=\"number\" />\n * <span wrInputSuffix>USD</span>\n * </wr-input-group>\n * ```\n */\n@Directive({\n selector: '[wrInputSuffix]',\n host: { class: 'wr-input-group__affix wr-input-group__affix--suffix' },\n})\nexport class WrInputSuffix {}\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 { type BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\nimport { useConfigValue } from 'ngwr/config';\n\n/**\n * Container for `<input wrInput>` + `[wrInputPrefix]` / `[wrInputSuffix]` /\n * `<wr-password-toggle>` siblings. Renders the border and focus ring; the\n * inner native input drops its own border so it visually melts into the\n * group.\n *\n * Pure layout — no signals shared with the inner directive, focus styling is\n * driven entirely by `:focus-within` so any focusable child counts.\n *\n * @example\n * ```html\n * <wr-input-group>\n * <span wrInputPrefix>$</span>\n * <input wrInput [(ngModel)]=\"amount\" type=\"number\" />\n * <span wrInputSuffix>USD</span>\n * </wr-input-group>\n * ```\n *\n * @see https://ngwr.dev/reference/components/input\n */\n@Component({\n selector: 'wr-input-group',\n template: '<ng-content />',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n})\nexport class WrInputGroup {\n /**\n * Pill-shaped corners. Unset, it falls back to\n * `provideWrConfig({ input: { rounded } })` — the same key the inner `[wrInput]`\n * reads. @default false\n */\n readonly rounded = input<boolean | null, BooleanInput>(null, {\n // Null-preserving, like `[wrInput]`'s: the plain `coerceBooleanProperty` folds\n // `null` into `false`, which would make \"not set\" and \"set to false\" the same\n // value — and a config default nothing could ever supply.\n transform: (v: BooleanInput): boolean | null => (v == null ? null : coerceBooleanProperty(v)),\n });\n\n // `input.rounded`, and deliberately not a key of its own: the group owns the visible\n // border once it wraps an input, which drops its own chrome. Resolving one and not\n // the other would put a pill radius on the element nobody can see and leave the\n // corner the user does see square.\n protected readonly resolvedRounded = useConfigValue(this.rounded, c => c.input?.rounded, false);\n\n protected readonly classes = computed(() => {\n const parts = ['wr-input-group'];\n if (this.resolvedRounded()) parts.push('wr-input-group--rounded');\n return parts.join(' ');\n });\n}\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 { Component, ViewEncapsulation, computed, input, signal } from '@angular/core';\n\nimport { useI18nText } from 'ngwr/i18n';\n\n/**\n * Self-contained eye-toggle button. Flips the linked `<input>`'s `type`\n * attribute between `password` and `text`. Drop it inside an\n * `<wr-input-group>` next to a password input.\n *\n * @example\n * ```html\n * <wr-input-group>\n * <input wrInput type=\"password\" [(ngModel)]=\"pw\" #pwInput />\n * <wr-password-toggle [for]=\"pwInput\" />\n * </wr-input-group>\n * ```\n */\n@Component({\n selector: 'wr-password-toggle',\n templateUrl: './password-toggle.html',\n encapsulation: ViewEncapsulation.None,\n})\nexport class WrPasswordToggle {\n /** Reference to the linked password input. */\n readonly for = input.required<HTMLInputElement>();\n\n protected readonly revealed = signal(false);\n\n /** Accessible name while the password is hidden. Falls back to `input.showPassword`. */\n readonly showLabel = input<string | null>(null);\n\n /** Accessible name while the password is revealed. Falls back to `input.hidePassword`. */\n readonly hideLabel = input<string | null>(null);\n\n private readonly resolvedShowLabel = useI18nText(this.showLabel, 'input.showPassword', 'Show password');\n private readonly resolvedHideLabel = useI18nText(this.hideLabel, 'input.hidePassword', 'Hide password');\n\n protected readonly ariaLabel = computed(() =>\n this.revealed() ? this.resolvedHideLabel() : this.resolvedShowLabel()\n );\n\n protected toggle(): void {\n const input = this.for();\n const next = input.type === 'password' ? 'text' : 'password';\n input.type = next;\n this.revealed.set(next === 'text');\n }\n}\n","<button\n type=\"button\"\n class=\"wr-input-group__toggle\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-pressed]=\"revealed()\"\n (click)=\"toggle()\"\n>\n @if (revealed()) {\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=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\" />\n <path d=\"M14.084 14.158a3 3 0 0 1-4.242-4.242\" />\n <path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\" />\n <path d=\"m2 2 20 20\" />\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 <path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n }\n</button>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -26,10 +26,10 @@ class WrKbd {
26
26
  ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
27
27
  classes = computed(() => `wr-kbd wr-kbd--${this.size()}`, /* @ts-ignore */
28
28
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
29
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrKbd, deps: [], target: i0.ɵɵFactoryTarget.Component });
30
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: WrKbd, isStandalone: true, selector: "wr-kbd", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: '<ng-content />', isInline: true, encapsulation: i0.ViewEncapsulation.None });
29
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrKbd, deps: [], target: i0.ɵɵFactoryTarget.Component });
30
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.7", type: WrKbd, isStandalone: true, selector: "wr-kbd", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: '<ng-content />', isInline: true, encapsulation: i0.ViewEncapsulation.None });
31
31
  }
32
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrKbd, decorators: [{
32
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrKbd, decorators: [{
33
33
  type: Component,
34
34
  args: [{
35
35
  selector: 'wr-kbd',
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-keyboard.mjs","sources":["../../../projects/lib/keyboard/kbd.ts","../../../projects/lib/keyboard/ngwr-keyboard.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 { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\nimport type { WrKbdSize } from './interfaces';\n\n/**\n * Tiny keycap chip — renders projected content (`⌘`, `K`, `Enter`, etc.) in\n * a beveled rectangle that reads as a physical key. Stack multiple `<wr-kbd>`\n * with a plain `+` between them for chords.\n *\n * @example\n * ```html\n * <wr-kbd>⌘</wr-kbd> + <wr-kbd>K</wr-kbd>\n * <wr-kbd size=\"lg\">Esc</wr-kbd>\n * ```\n *\n * @see https://ngwr.dev/reference/components/keyboard\n */\n@Component({\n selector: 'wr-kbd',\n template: '<ng-content />',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n})\nexport class WrKbd {\n /** Visual size variant. @default 'md' */\n readonly size = input<WrKbdSize>('md');\n\n protected readonly classes = computed(() => `wr-kbd wr-kbd--${this.size()}`);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;AAAA;;;;;AAKG;AAMH;;;;;;;;;;;;AAYG;MAOU,KAAK,CAAA;;IAEP,IAAI,GAAG,KAAK,CAAY,IAAI;6EAAC;IAEnB,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAA,eAAA,EAAkB,IAAI,CAAC,IAAI,EAAE,CAAA,CAAE;gFAAC;uGAJjE,KAAK,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAL,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAK,mPAJN,gBAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAIf,KAAK,EAAA,UAAA,EAAA,CAAA;kBANjB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,QAAQ;AAClB,oBAAA,QAAQ,EAAE,gBAAgB;oBAC1B,aAAa,EAAE,iBAAiB,CAAC,IAAI;AACrC,oBAAA,IAAI,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE;AACjC,iBAAA;;;AC7BD;;AAEG;;;;"}
1
+ {"version":3,"file":"ngwr-keyboard.mjs","sources":["../../../projects/lib/keyboard/kbd.ts","../../../projects/lib/keyboard/ngwr-keyboard.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 { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\nimport type { WrKbdSize } from './interfaces';\n\n/**\n * Tiny keycap chip — renders projected content (`⌘`, `K`, `Enter`, etc.) in\n * a beveled rectangle that reads as a physical key. Stack multiple `<wr-kbd>`\n * with a plain `+` between them for chords.\n *\n * @example\n * ```html\n * <wr-kbd>⌘</wr-kbd> + <wr-kbd>K</wr-kbd>\n * <wr-kbd size=\"lg\">Esc</wr-kbd>\n * ```\n *\n * @see https://ngwr.dev/reference/components/keyboard\n */\n@Component({\n selector: 'wr-kbd',\n template: '<ng-content />',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n})\nexport class WrKbd {\n /** Visual size variant. @default 'md' */\n readonly size = input<WrKbdSize>('md');\n\n protected readonly classes = computed(() => `wr-kbd wr-kbd--${this.size()}`);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;AAAA;;;;;AAKG;AAMH;;;;;;;;;;;;AAYG;MAOU,KAAK,CAAA;;IAEP,IAAI,GAAG,KAAK,CAAY,IAAI;6EAAC;IAEnB,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAA,eAAA,EAAkB,IAAI,CAAC,IAAI,EAAE,CAAA,CAAE;gFAAC;uGAJjE,KAAK,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAL,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAK,mPAJN,gBAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAIf,KAAK,EAAA,UAAA,EAAA,CAAA;kBANjB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,QAAQ;AAClB,oBAAA,QAAQ,EAAE,gBAAgB;oBAC1B,aAAa,EAAE,iBAAiB,CAAC,IAAI;AACrC,oBAAA,IAAI,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE;AACjC,iBAAA;;;AC7BD;;AAEG;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-knob-testing.mjs","sources":["../../../projects/lib/knob/testing/wr-knob-harness.ts","../../../projects/lib/knob/testing/ngwr-knob-testing.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 { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';\n\nimport type { WrKnobArrowKey, WrKnobHarnessFilters } from './interfaces';\n\nconst ARROWS: Record<WrKnobArrowKey, TestKey> = {\n left: TestKey.LEFT_ARROW,\n right: TestKey.RIGHT_ARROW,\n up: TestKey.UP_ARROW,\n down: TestKey.DOWN_ARROW,\n};\n\n/** Enough presses to cross any sane range; a stall throws long before this. */\nconst WALK_LIMIT = 400;\n\n/**\n * Test harness for `<wr-knob>` — the radial dial.\n *\n * **Driven by the keyboard, and the drag is not merely unsupported.** Turning the\n * dial with a pointer takes `getBoundingClientRect()`, measures the angle from the\n * centre to the cursor, and maps it onto a 270° arc. jsdom lays nothing out, so the\n * centre is `(0, 0)` and every synthetic gesture writes the same corner of the arc\n * whatever coordinates it is given — a `turnTo()` built on one would pass while\n * proving nothing. The arrows reach every value on the grid and are the accessible\n * path anyway.\n *\n * **Two questions about the value, not one.** {@link getValue} is the number\n * `aria-valuenow` carries; {@link getDisplayValue} is the string in the middle of the\n * dial, which the `suffix` input can make `\"50%\"` while the announced value stays\n * `50`. They are separate methods because they can disagree, and because\n * `showValue` can remove the text entirely without touching the value.\n *\n * @example\n * ```ts\n * const knob = await loader.getHarness(WrKnobHarness);\n *\n * await knob.setValue(60);\n * expect(await knob.getValue()).toBe(60);\n * expect(await knob.getDisplayValue()).toBe('60%');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrKnobHarness extends ComponentHarness {\n static hostSelector = 'wr-knob';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrKnobHarnessFilters = {}): HarnessPredicate<WrKnobHarness> {\n return new HarnessPredicate(WrKnobHarness, options)\n .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))\n .addOption('value', options.value, async (harness, value) => (await harness.getValue()) === value)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)\n .addOption('readonly', options.readonly, async (harness, readonly) => (await harness.isReadonly()) === readonly);\n }\n\n private readonly surface = this.locatorFor('.wr-knob__surface');\n\n /** The value the dial announces, from `aria-valuenow`. */\n async getValue(): Promise<number> {\n return this.numeric('aria-valuenow');\n }\n\n /** The bottom of the range, from `aria-valuemin`. */\n async getMin(): Promise<number> {\n return this.numeric('aria-valuemin');\n }\n\n /** The top of the range, from `aria-valuemax`. */\n async getMax(): Promise<number> {\n return this.numeric('aria-valuemax');\n }\n\n /**\n * The text printed in the middle of the dial, suffix included, or `null` when the\n * knob was built with `[showValue]=\"false\"`.\n *\n * Not the same question as {@link getValue}: with a `suffix` the two disagree by\n * design, and a screen reader is told the bare number — the component publishes no\n * `aria-valuetext`, so `50` is what gets announced for a dial that reads `50%`.\n */\n async getDisplayValue(): Promise<string | null> {\n const text = await this.locatorForOptional('.wr-knob__text')();\n return text ? text.text() : null;\n }\n\n /** The suffix alone, or `null` when there is none (or no value text at all). */\n async getSuffix(): Promise<string | null> {\n const suffix = await this.locatorForOptional('.wr-knob__suffix')();\n if (!suffix) return null;\n const text = await suffix.text();\n return text === '' ? null : text;\n }\n\n /** The dial's accessible name — `role=\"slider\"` needs one. */\n async getLabel(): Promise<string | null> {\n return (await this.surface()).getAttribute('aria-label');\n }\n\n /** Whether the dial is disabled, from `aria-disabled`. */\n async isDisabled(): Promise<boolean> {\n return (await (await this.surface()).getAttribute('aria-disabled')) === 'true';\n }\n\n /** Whether the dial is read-only, from `aria-readonly`. */\n async isReadonly(): Promise<boolean> {\n return (await (await this.surface()).getAttribute('aria-readonly')) === 'true';\n }\n\n /**\n * Whether the dial is a tab stop.\n *\n * `disabled` only, never `readonly` — and the distinction is deliberate, not\n * incidental. A disabled control leaves the tab order; a READ-ONLY one stays\n * in it, keeps announcing its value, and still submits, which is the whole\n * difference between \"you may not\" and \"there is nothing here\". The component\n * records that driving this off an `interactive()` that folded the two\n * together made `readonly` unreachable, with an `aria-describedby` pointing\n * at an element nobody could focus.\n *\n * This docblock used to describe exactly that fixed bug — \"false while\n * readonly or disabled\" — so a reader trusting it would have asserted the\n * behaviour the component was changed to stop having.\n */\n async isFocusable(): Promise<boolean> {\n return (await (await this.surface()).getAttribute('tabindex')) === '0';\n }\n\n /** Move keyboard focus to the dial. */\n async focus(): Promise<void> {\n return (await this.surface()).focus();\n }\n\n /** Whether the dial currently holds focus. */\n async isFocused(): Promise<boolean> {\n return (await this.surface()).isFocused();\n }\n\n /** Blur the dial — which is what emits `touch` for a knob moved with the keyboard. */\n async blur(): Promise<void> {\n return (await this.surface()).blur();\n }\n\n /**\n * Press one arrow key.\n *\n * Right and Up raise the value, Left and Down lower it — all four are live on this\n * component, which has one axis and no mirroring to do. `shift` multiplies the step\n * by ten.\n */\n async pressArrow(arrow: WrKnobArrowKey, options: { shift?: boolean } = {}): Promise<void> {\n const surface = await this.surface();\n await (options.shift ? surface.sendKeys({ shift: true }, ARROWS[arrow]) : surface.sendKeys(ARROWS[arrow]));\n }\n\n /** Press Home — the bottom of the range. */\n async pressHome(): Promise<void> {\n return (await this.surface()).sendKeys(TestKey.HOME);\n }\n\n /**\n * Press End — the top of the range, or the last value ON the grid below it: a range\n * that is not a whole number of steps cannot reach its own maximum.\n */\n async pressEnd(): Promise<void> {\n return (await this.surface()).sendKeys(TestKey.END);\n }\n\n /**\n * Walk the dial to a value with the arrow keys, and assert it landed there.\n *\n * It measures the step as it goes rather than being told it — `step` is an input\n * with no DOM presence, and the value can arrive off the grid, since an external\n * write is clamped but never snapped. So the first press may move by less than a\n * step (it snaps onto the grid) and the walk adapts, which also means the ten-step\n * hops only start once a real step has been seen.\n *\n * Throws rather than half-arriving, and the two reasons read differently: a target\n * outside `[min, max]` is refused before anything moves, while a target BETWEEN two\n * grid points is only discovered by overshooting it, and says where it landed. A\n * dial that will not move at all — disabled, read-only — is the third.\n */\n async setValue(target: number): Promise<void> {\n const [min, max] = [await this.getMin(), await this.getMax()];\n if (target < min || target > max) {\n throw new Error(\n `WrKnobHarness.setValue(${target}): out of range — this dial accepts ${min}–${max}. The component ` +\n 'clamps, so the walk would stop at the bound and never reach the number asked for.'\n );\n }\n\n if (target === min) return this.pressHome();\n if (target === max) return this.pressEnd();\n\n await this.focus();\n let step: number | null = null;\n\n for (let guard = 0; guard < WALK_LIMIT; guard++) {\n const current = await this.getValue();\n if (current === target) return;\n\n const forward = target > current;\n const coarse = step !== null && Math.abs(target - current) >= step * 10;\n\n await this.pressArrow(forward ? 'right' : 'left', { shift: coarse });\n const now = await this.getValue();\n\n if (now === current) {\n throw new Error(\n `WrKnobHarness.setValue(${target}): the dial stopped moving at ${now}. A disabled or read-only ` +\n 'knob ignores its arrows, which is the usual reason.'\n );\n }\n if (!coarse) step = Math.abs(now - current);\n if (now === target) return;\n\n if (forward ? now > target : now < target) {\n throw new Error(\n `WrKnobHarness.setValue(${target}): the walk stepped from ${current} to ${now}, straight past the ` +\n 'target — it is not on the step grid, which the component measures from `min` rather than from zero.'\n );\n }\n }\n\n throw new Error(\n `WrKnobHarness.setValue(${target}): gave up after ${WALK_LIMIT} presses at ${await this.getValue()}.`\n );\n }\n\n /**\n * Where the handle dot sits, in the SVG's own 100×100 viewBox units.\n *\n * The dial's whole visual state is an arc path and this dot, and neither can be\n * measured in a unit test — but the dot's centre is written as plain `cx` / `cy`\n * attributes, so it reads with no layout at all. That makes it the evidence that\n * the drawing followed the value: at `min` the handle is at the 7 o'clock end of\n * the arc, at `max` the 5 o'clock end.\n */\n async getHandlePosition(): Promise<{ x: number; y: number }> {\n const handle = await this.locatorFor('.wr-knob__handle')();\n return {\n x: Number(await handle.getAttribute('cx')),\n y: Number(await handle.getAttribute('cy')),\n };\n }\n\n private async numeric(attribute: string): Promise<number> {\n const raw = await (await this.surface()).getAttribute(attribute);\n return raw === null ? Number.NaN : Number(raw);\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-knob-testing.mjs","sources":["../../../projects/lib/knob/testing/wr-knob-harness.ts","../../../projects/lib/knob/testing/ngwr-knob-testing.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 { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';\n\nimport type { WrKnobArrowKey, WrKnobHarnessFilters } from './interfaces';\n\nconst ARROWS: Record<WrKnobArrowKey, TestKey> = {\n left: TestKey.LEFT_ARROW,\n right: TestKey.RIGHT_ARROW,\n up: TestKey.UP_ARROW,\n down: TestKey.DOWN_ARROW,\n};\n\n/** Enough presses to cross any sane range; a stall throws long before this. */\nconst WALK_LIMIT = 400;\n\n/**\n * Test harness for `<wr-knob>` — the radial dial.\n *\n * **Driven by the keyboard, and the drag is not merely unsupported.** Turning the\n * dial with a pointer takes `getBoundingClientRect()`, measures the angle from the\n * centre to the cursor, and maps it onto a 270° arc. jsdom lays nothing out, so the\n * centre is `(0, 0)` and every synthetic gesture writes the same corner of the arc\n * whatever coordinates it is given — a `turnTo()` built on one would pass while\n * proving nothing. The arrows reach every value on the grid and are the accessible\n * path anyway.\n *\n * **Two questions about the value, not one.** {@link getValue} is the number\n * `aria-valuenow` carries; {@link getDisplayValue} is the string in the middle of the\n * dial, which the `suffix` input can make `\"50%\"` while the announced value stays\n * `50`. They are separate methods because they can disagree, and because\n * `showValue` can remove the text entirely without touching the value.\n *\n * @example\n * ```ts\n * const knob = await loader.getHarness(WrKnobHarness);\n *\n * await knob.setValue(60);\n * expect(await knob.getValue()).toBe(60);\n * expect(await knob.getDisplayValue()).toBe('60%');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrKnobHarness extends ComponentHarness {\n static hostSelector = 'wr-knob';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrKnobHarnessFilters = {}): HarnessPredicate<WrKnobHarness> {\n return new HarnessPredicate(WrKnobHarness, options)\n .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))\n .addOption('value', options.value, async (harness, value) => (await harness.getValue()) === value)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)\n .addOption('readonly', options.readonly, async (harness, readonly) => (await harness.isReadonly()) === readonly);\n }\n\n private readonly surface = this.locatorFor('.wr-knob__surface');\n\n /** The value the dial announces, from `aria-valuenow`. */\n async getValue(): Promise<number> {\n return this.numeric('aria-valuenow');\n }\n\n /** The bottom of the range, from `aria-valuemin`. */\n async getMin(): Promise<number> {\n return this.numeric('aria-valuemin');\n }\n\n /** The top of the range, from `aria-valuemax`. */\n async getMax(): Promise<number> {\n return this.numeric('aria-valuemax');\n }\n\n /**\n * The text printed in the middle of the dial, suffix included, or `null` when the\n * knob was built with `[showValue]=\"false\"`.\n *\n * Not the same question as {@link getValue}: with a `suffix` the two disagree by\n * design, and a screen reader is told the bare number — the component publishes no\n * `aria-valuetext`, so `50` is what gets announced for a dial that reads `50%`.\n */\n async getDisplayValue(): Promise<string | null> {\n const text = await this.locatorForOptional('.wr-knob__text')();\n return text ? text.text() : null;\n }\n\n /** The suffix alone, or `null` when there is none (or no value text at all). */\n async getSuffix(): Promise<string | null> {\n const suffix = await this.locatorForOptional('.wr-knob__suffix')();\n if (!suffix) return null;\n const text = await suffix.text();\n return text === '' ? null : text;\n }\n\n /** The dial's accessible name — `role=\"slider\"` needs one. */\n async getLabel(): Promise<string | null> {\n return (await this.surface()).getAttribute('aria-label');\n }\n\n /** Whether the dial is disabled, from `aria-disabled`. */\n async isDisabled(): Promise<boolean> {\n return (await (await this.surface()).getAttribute('aria-disabled')) === 'true';\n }\n\n /** Whether the dial is read-only, from `aria-readonly`. */\n async isReadonly(): Promise<boolean> {\n return (await (await this.surface()).getAttribute('aria-readonly')) === 'true';\n }\n\n /**\n * Whether the dial is a tab stop.\n *\n * `disabled` only, never `readonly` — and the distinction is deliberate, not\n * incidental. A disabled control leaves the tab order; a READ-ONLY one stays\n * in it, keeps announcing its value, and still submits, which is the whole\n * difference between \"you may not\" and \"there is nothing here\". The component\n * records that driving this off an `interactive()` that folded the two\n * together made `readonly` unreachable, with an `aria-describedby` pointing\n * at an element nobody could focus.\n *\n * This docblock used to describe exactly that fixed bug — \"false while\n * readonly or disabled\" — so a reader trusting it would have asserted the\n * behaviour the component was changed to stop having.\n */\n async isFocusable(): Promise<boolean> {\n return (await (await this.surface()).getAttribute('tabindex')) === '0';\n }\n\n /** Move keyboard focus to the dial. */\n async focus(): Promise<void> {\n return (await this.surface()).focus();\n }\n\n /** Whether the dial currently holds focus. */\n async isFocused(): Promise<boolean> {\n return (await this.surface()).isFocused();\n }\n\n /** Blur the dial — which is what emits `touch` for a knob moved with the keyboard. */\n async blur(): Promise<void> {\n return (await this.surface()).blur();\n }\n\n /**\n * Press one arrow key.\n *\n * Right and Up raise the value, Left and Down lower it — all four are live on this\n * component, which has one axis and no mirroring to do. `shift` multiplies the step\n * by ten.\n */\n async pressArrow(arrow: WrKnobArrowKey, options: { shift?: boolean } = {}): Promise<void> {\n const surface = await this.surface();\n await (options.shift ? surface.sendKeys({ shift: true }, ARROWS[arrow]) : surface.sendKeys(ARROWS[arrow]));\n }\n\n /** Press Home — the bottom of the range. */\n async pressHome(): Promise<void> {\n return (await this.surface()).sendKeys(TestKey.HOME);\n }\n\n /**\n * Press End — the top of the range, or the last value ON the grid below it: a range\n * that is not a whole number of steps cannot reach its own maximum.\n */\n async pressEnd(): Promise<void> {\n return (await this.surface()).sendKeys(TestKey.END);\n }\n\n /**\n * Walk the dial to a value with the arrow keys, and assert it landed there.\n *\n * It measures the step as it goes rather than being told it — `step` is an input\n * with no DOM presence, and the value can arrive off the grid, since an external\n * write is clamped but never snapped. So the first press may move by less than a\n * step (it snaps onto the grid) and the walk adapts, which also means the ten-step\n * hops only start once a real step has been seen.\n *\n * Throws rather than half-arriving, and the two reasons read differently: a target\n * outside `[min, max]` is refused before anything moves, while a target BETWEEN two\n * grid points is only discovered by overshooting it, and says where it landed. A\n * dial that will not move at all — disabled, read-only — is the third.\n */\n async setValue(target: number): Promise<void> {\n const [min, max] = [await this.getMin(), await this.getMax()];\n if (target < min || target > max) {\n throw new Error(\n `WrKnobHarness.setValue(${target}): out of range — this dial accepts ${min}–${max}. The component ` +\n 'clamps, so the walk would stop at the bound and never reach the number asked for.'\n );\n }\n\n if (target === min) return this.pressHome();\n if (target === max) return this.pressEnd();\n\n await this.focus();\n let step: number | null = null;\n\n for (let guard = 0; guard < WALK_LIMIT; guard++) {\n const current = await this.getValue();\n if (current === target) return;\n\n const forward = target > current;\n const coarse = step !== null && Math.abs(target - current) >= step * 10;\n\n await this.pressArrow(forward ? 'right' : 'left', { shift: coarse });\n const now = await this.getValue();\n\n if (now === current) {\n throw new Error(\n `WrKnobHarness.setValue(${target}): the dial stopped moving at ${now}. A disabled or read-only ` +\n 'knob ignores its arrows, which is the usual reason.'\n );\n }\n if (!coarse) step = Math.abs(now - current);\n if (now === target) return;\n\n if (forward ? now > target : now < target) {\n throw new Error(\n `WrKnobHarness.setValue(${target}): the walk stepped from ${current} to ${now}, straight past the ` +\n 'target — it is not on the step grid, which the component measures from `min` rather than from zero.'\n );\n }\n }\n\n throw new Error(\n `WrKnobHarness.setValue(${target}): gave up after ${WALK_LIMIT} presses at ${await this.getValue()}.`\n );\n }\n\n /**\n * Where the handle dot sits, in the SVG's own 100×100 viewBox units.\n *\n * The dial's whole visual state is an arc path and this dot, and neither can be\n * measured in a unit test — but the dot's centre is written as plain `cx` / `cy`\n * attributes, so it reads with no layout at all. That makes it the evidence that\n * the drawing followed the value: at `min` the handle is at the 7 o'clock end of\n * the arc, at `max` the 5 o'clock end.\n */\n async getHandlePosition(): Promise<{ x: number; y: number }> {\n const handle = await this.locatorFor('.wr-knob__handle')();\n return {\n x: Number(await handle.getAttribute('cx')),\n y: Number(await handle.getAttribute('cy')),\n };\n }\n\n private async numeric(attribute: string): Promise<number> {\n const raw = await (await this.surface()).getAttribute(attribute);\n return raw === null ? Number.NaN : Number(raw);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -289,10 +289,10 @@ class WrKnob {
289
289
  const largeArc = endDeg - startDeg > 180 ? 1 : 0;
290
290
  return `M ${sx} ${sy} A ${r} ${r} 0 ${largeArc} 1 ${ex} ${ey}`;
291
291
  }
292
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrKnob, deps: [], target: i0.ɵɵFactoryTarget.Component });
293
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrKnob, isStandalone: true, selector: "wr-knob", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null }, trackColor: { classPropertyName: "trackColor", publicName: "trackColor", isSignal: true, isRequired: false, transformFunction: null }, valueColor: { classPropertyName: "valueColor", publicName: "valueColor", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touch: "touch" }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: "<div\n class=\"wr-knob__surface\"\n role=\"slider\"\n [attr.aria-label]=\"nameLabel()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-valuemin]=\"min()\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n [attr.tabindex]=\"focusable() ? 0 : -1\"\n [style.width.px]=\"size()\"\n [style.height.px]=\"size()\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerUp($event)\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n>\n <svg viewBox=\"0 0 100 100\" aria-hidden=\"true\">\n <path\n class=\"wr-knob__track\"\n [attr.d]=\"trackPath()\"\n [attr.stroke]=\"trackColor()\"\n [attr.stroke-width]=\"strokeWidth()\"\n fill=\"none\"\n stroke-linecap=\"round\"\n />\n <path\n class=\"wr-knob__value\"\n [attr.d]=\"valuePath()\"\n [attr.stroke]=\"valueColor()\"\n [attr.stroke-width]=\"strokeWidth()\"\n fill=\"none\"\n stroke-linecap=\"round\"\n />\n <circle\n class=\"wr-knob__handle\"\n [attr.cx]=\"handlePos().x\"\n [attr.cy]=\"handlePos().y\"\n [attr.r]=\"strokeWidth() / 2\"\n [attr.fill]=\"valueColor()\"\n />\n </svg>\n @if (showValue()) {\n <!--\n `dir=\"auto\"` because this is a number and a unit read as one phrase, and\n the browser is the only thing that knows which way that phrase runs. In an\n RTL paragraph the Unicode BiDi algorithm treats a digit run as neutral\n against the letters beside it, so `40 dB` was drawn `dB 40` \u2014 and `-5 dB`\n as `dB 5-`, with the sign on the wrong end of the number. `dir=\"auto\"`\n picks the direction from the first strong character in the composed text,\n so a Latin `suffix` keeps the number first and an Arabic one reads\n right-to-left, which is correct for both.\n\n `unicode-bidi: isolate` does NOT fix this and was measured doing nothing:\n isolation seals the element off from its SURROUNDINGS, and the flip\n happens inside it.\n -->\n <div class=\"wr-knob__text\" dir=\"auto\">\n {{ value() }}<span class=\"wr-knob__suffix\">{{ suffix() }}</span>\n </div>\n }\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
292
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrKnob, deps: [], target: i0.ɵɵFactoryTarget.Component });
293
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: WrKnob, isStandalone: true, selector: "wr-knob", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null }, trackColor: { classPropertyName: "trackColor", publicName: "trackColor", isSignal: true, isRequired: false, transformFunction: null }, valueColor: { classPropertyName: "valueColor", publicName: "valueColor", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touch: "touch" }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: "<div\n class=\"wr-knob__surface\"\n role=\"slider\"\n [attr.aria-label]=\"nameLabel()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-valuemin]=\"min()\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n [attr.tabindex]=\"focusable() ? 0 : -1\"\n [style.width.px]=\"size()\"\n [style.height.px]=\"size()\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerUp($event)\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n>\n <svg viewBox=\"0 0 100 100\" aria-hidden=\"true\">\n <path\n class=\"wr-knob__track\"\n [attr.d]=\"trackPath()\"\n [attr.stroke]=\"trackColor()\"\n [attr.stroke-width]=\"strokeWidth()\"\n fill=\"none\"\n stroke-linecap=\"round\"\n />\n <path\n class=\"wr-knob__value\"\n [attr.d]=\"valuePath()\"\n [attr.stroke]=\"valueColor()\"\n [attr.stroke-width]=\"strokeWidth()\"\n fill=\"none\"\n stroke-linecap=\"round\"\n />\n <circle\n class=\"wr-knob__handle\"\n [attr.cx]=\"handlePos().x\"\n [attr.cy]=\"handlePos().y\"\n [attr.r]=\"strokeWidth() / 2\"\n [attr.fill]=\"valueColor()\"\n />\n </svg>\n @if (showValue()) {\n <!--\n `dir=\"auto\"` because this is a number and a unit read as one phrase, and\n the browser is the only thing that knows which way that phrase runs. In an\n RTL paragraph the Unicode BiDi algorithm treats a digit run as neutral\n against the letters beside it, so `40 dB` was drawn `dB 40` \u2014 and `-5 dB`\n as `dB 5-`, with the sign on the wrong end of the number. `dir=\"auto\"`\n picks the direction from the first strong character in the composed text,\n so a Latin `suffix` keeps the number first and an Arabic one reads\n right-to-left, which is correct for both.\n\n `unicode-bidi: isolate` does NOT fix this and was measured doing nothing:\n isolation seals the element off from its SURROUNDINGS, and the flip\n happens inside it.\n -->\n <div class=\"wr-knob__text\" dir=\"auto\">\n {{ value() }}<span class=\"wr-knob__suffix\">{{ suffix() }}</span>\n </div>\n }\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
294
294
  }
295
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrKnob, decorators: [{
295
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrKnob, decorators: [{
296
296
  type: Component,
297
297
  args: [{ selector: 'wr-knob', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, template: "<div\n class=\"wr-knob__surface\"\n role=\"slider\"\n [attr.aria-label]=\"nameLabel()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-valuemin]=\"min()\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n [attr.tabindex]=\"focusable() ? 0 : -1\"\n [style.width.px]=\"size()\"\n [style.height.px]=\"size()\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerUp($event)\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n>\n <svg viewBox=\"0 0 100 100\" aria-hidden=\"true\">\n <path\n class=\"wr-knob__track\"\n [attr.d]=\"trackPath()\"\n [attr.stroke]=\"trackColor()\"\n [attr.stroke-width]=\"strokeWidth()\"\n fill=\"none\"\n stroke-linecap=\"round\"\n />\n <path\n class=\"wr-knob__value\"\n [attr.d]=\"valuePath()\"\n [attr.stroke]=\"valueColor()\"\n [attr.stroke-width]=\"strokeWidth()\"\n fill=\"none\"\n stroke-linecap=\"round\"\n />\n <circle\n class=\"wr-knob__handle\"\n [attr.cx]=\"handlePos().x\"\n [attr.cy]=\"handlePos().y\"\n [attr.r]=\"strokeWidth() / 2\"\n [attr.fill]=\"valueColor()\"\n />\n </svg>\n @if (showValue()) {\n <!--\n `dir=\"auto\"` because this is a number and a unit read as one phrase, and\n the browser is the only thing that knows which way that phrase runs. In an\n RTL paragraph the Unicode BiDi algorithm treats a digit run as neutral\n against the letters beside it, so `40 dB` was drawn `dB 40` \u2014 and `-5 dB`\n as `dB 5-`, with the sign on the wrong end of the number. `dir=\"auto\"`\n picks the direction from the first strong character in the composed text,\n so a Latin `suffix` keeps the number first and an Arabic one reads\n right-to-left, which is correct for both.\n\n `unicode-bidi: isolate` does NOT fix this and was measured doing nothing:\n isolation seals the element off from its SURROUNDINGS, and the flip\n happens inside it.\n -->\n <div class=\"wr-knob__text\" dir=\"auto\">\n {{ value() }}<span class=\"wr-knob__suffix\">{{ suffix() }}</span>\n </div>\n }\n</div>\n" }]
298
298
  }], ctorParameters: () => [], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], valueColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueColor", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touch: [{ type: i0.Output, args: ["touch"] }] } });