ngwr 10.2.1 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) hide show
  1. package/README.md +39 -19
  2. package/anchor/styles/_index.scss +4 -4
  3. package/back-top/styles/_index.scss +6 -1
  4. package/blur-text/styles/_index.scss +13 -0
  5. package/button/styles/_index.scss +11 -6
  6. package/carousel/styles/_index.scss +13 -2
  7. package/cascader/styles/_index.scss +2 -2
  8. package/circular-text/styles/_index.scss +2 -0
  9. package/collapse/styles/_index.scss +1 -1
  10. package/color-picker/styles/_index.scss +6 -1
  11. package/compare/styles/_index.scss +1 -2
  12. package/context-menu/styles/_index.scss +6 -1
  13. package/descriptions/styles/_index.scss +2 -2
  14. package/dialog/styles/_index.scss +7 -0
  15. package/drawer/styles/_index.scss +20 -1
  16. package/dropdown/styles/_index.scss +19 -5
  17. package/empty/styles/_index.scss +10 -0
  18. package/fesm2022/ngwr-action-sheet.mjs +13 -3
  19. package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
  20. package/fesm2022/ngwr-affix.mjs +40 -13
  21. package/fesm2022/ngwr-affix.mjs.map +1 -1
  22. package/fesm2022/ngwr-anchor.mjs +18 -6
  23. package/fesm2022/ngwr-anchor.mjs.map +1 -1
  24. package/fesm2022/ngwr-aurora.mjs +2 -2
  25. package/fesm2022/ngwr-aurora.mjs.map +1 -1
  26. package/fesm2022/ngwr-avatar.mjs +31 -7
  27. package/fesm2022/ngwr-avatar.mjs.map +1 -1
  28. package/fesm2022/ngwr-back-top.mjs +6 -2
  29. package/fesm2022/ngwr-back-top.mjs.map +1 -1
  30. package/fesm2022/ngwr-badge.mjs +1 -1
  31. package/fesm2022/ngwr-badge.mjs.map +1 -1
  32. package/fesm2022/ngwr-bar-chart.mjs +30 -9
  33. package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
  34. package/fesm2022/ngwr-blur-text.mjs +2 -2
  35. package/fesm2022/ngwr-blur-text.mjs.map +1 -1
  36. package/fesm2022/ngwr-border-glow.mjs +2 -2
  37. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  38. package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
  39. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  40. package/fesm2022/ngwr-burger.mjs +9 -4
  41. package/fesm2022/ngwr-burger.mjs.map +1 -1
  42. package/fesm2022/ngwr-button-testing.mjs +96 -0
  43. package/fesm2022/ngwr-button-testing.mjs.map +1 -0
  44. package/fesm2022/ngwr-button.mjs +31 -14
  45. package/fesm2022/ngwr-button.mjs.map +1 -1
  46. package/fesm2022/ngwr-calendar-heatmap.mjs +40 -8
  47. package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
  48. package/fesm2022/ngwr-calendar.mjs +20 -1
  49. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  50. package/fesm2022/ngwr-card.mjs +2 -2
  51. package/fesm2022/ngwr-card.mjs.map +1 -1
  52. package/fesm2022/ngwr-carousel-testing.mjs +377 -0
  53. package/fesm2022/ngwr-carousel-testing.mjs.map +1 -0
  54. package/fesm2022/ngwr-carousel.mjs +67 -13
  55. package/fesm2022/ngwr-carousel.mjs.map +1 -1
  56. package/fesm2022/ngwr-cascader-testing.mjs +534 -0
  57. package/fesm2022/ngwr-cascader-testing.mjs.map +1 -0
  58. package/fesm2022/ngwr-cascader.mjs +2 -2
  59. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  60. package/fesm2022/ngwr-checkbox-testing.mjs +90 -0
  61. package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -0
  62. package/fesm2022/ngwr-checkbox.mjs +9 -3
  63. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  64. package/fesm2022/ngwr-circular-text.mjs +2 -2
  65. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  66. package/fesm2022/ngwr-click-spark.mjs +2 -2
  67. package/fesm2022/ngwr-click-spark.mjs.map +1 -1
  68. package/fesm2022/ngwr-collapse-testing.mjs +368 -0
  69. package/fesm2022/ngwr-collapse-testing.mjs.map +1 -0
  70. package/fesm2022/ngwr-color-picker.mjs +134 -14
  71. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  72. package/fesm2022/ngwr-command-palette-testing.mjs +589 -0
  73. package/fesm2022/ngwr-command-palette-testing.mjs.map +1 -0
  74. package/fesm2022/ngwr-command-palette.mjs +58 -8
  75. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  76. package/fesm2022/ngwr-compare.mjs +103 -13
  77. package/fesm2022/ngwr-compare.mjs.map +1 -1
  78. package/fesm2022/ngwr-config.mjs +106 -0
  79. package/fesm2022/ngwr-config.mjs.map +1 -0
  80. package/fesm2022/ngwr-context-menu-testing.mjs +631 -0
  81. package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -0
  82. package/fesm2022/ngwr-context-menu.mjs +94 -8
  83. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  84. package/fesm2022/ngwr-cookie.mjs +5 -1
  85. package/fesm2022/ngwr-cookie.mjs.map +1 -1
  86. package/fesm2022/ngwr-counter.mjs +11 -3
  87. package/fesm2022/ngwr-counter.mjs.map +1 -1
  88. package/fesm2022/ngwr-date-adapter-luxon.mjs +52 -4
  89. package/fesm2022/ngwr-date-adapter-luxon.mjs.map +1 -1
  90. package/fesm2022/ngwr-date-adapter.mjs +54 -8
  91. package/fesm2022/ngwr-date-adapter.mjs.map +1 -1
  92. package/fesm2022/ngwr-date-picker-testing.mjs +766 -0
  93. package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -0
  94. package/fesm2022/ngwr-date-picker.mjs +73 -3
  95. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  96. package/fesm2022/ngwr-decrypt-text.mjs +27 -9
  97. package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
  98. package/fesm2022/ngwr-dialog-testing.mjs +89 -0
  99. package/fesm2022/ngwr-dialog-testing.mjs.map +1 -0
  100. package/fesm2022/ngwr-directives.mjs +36 -12
  101. package/fesm2022/ngwr-directives.mjs.map +1 -1
  102. package/fesm2022/ngwr-donut-chart.mjs +22 -5
  103. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  104. package/fesm2022/ngwr-drag-drop.mjs +2 -2
  105. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  106. package/fesm2022/ngwr-drawer-testing.mjs +250 -0
  107. package/fesm2022/ngwr-drawer-testing.mjs.map +1 -0
  108. package/fesm2022/ngwr-dropdown-testing.mjs +291 -0
  109. package/fesm2022/ngwr-dropdown-testing.mjs.map +1 -0
  110. package/fesm2022/ngwr-dropdown.mjs +10 -2
  111. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  112. package/fesm2022/ngwr-empty.mjs +24 -7
  113. package/fesm2022/ngwr-empty.mjs.map +1 -1
  114. package/fesm2022/ngwr-event-calendar.mjs +57 -10
  115. package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
  116. package/fesm2022/ngwr-falling-text.mjs +2 -2
  117. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  118. package/fesm2022/ngwr-file-upload-testing.mjs +332 -0
  119. package/fesm2022/ngwr-file-upload-testing.mjs.map +1 -0
  120. package/fesm2022/ngwr-form-testing.mjs +451 -0
  121. package/fesm2022/ngwr-form-testing.mjs.map +1 -0
  122. package/fesm2022/ngwr-form.mjs +19 -3
  123. package/fesm2022/ngwr-form.mjs.map +1 -1
  124. package/fesm2022/ngwr-fuzzy-text.mjs +9 -2
  125. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  126. package/fesm2022/ngwr-gauge.mjs +19 -5
  127. package/fesm2022/ngwr-gauge.mjs.map +1 -1
  128. package/fesm2022/ngwr-glitch-text.mjs +2 -2
  129. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  130. package/fesm2022/ngwr-gradient-text.mjs +2 -2
  131. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  132. package/fesm2022/ngwr-i18n-en.mjs +50 -0
  133. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  134. package/fesm2022/ngwr-i18n-ru.mjs +48 -0
  135. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  136. package/fesm2022/ngwr-image-cropper.mjs +23 -0
  137. package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
  138. package/fesm2022/ngwr-input-number-testing.mjs +306 -0
  139. package/fesm2022/ngwr-input-number-testing.mjs.map +1 -0
  140. package/fesm2022/ngwr-input-number.mjs +35 -3
  141. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  142. package/fesm2022/ngwr-input-otp-testing.mjs +419 -0
  143. package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -0
  144. package/fesm2022/ngwr-input-otp.mjs +36 -5
  145. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  146. package/fesm2022/ngwr-input-testing.mjs +102 -0
  147. package/fesm2022/ngwr-input-testing.mjs.map +1 -0
  148. package/fesm2022/ngwr-input.mjs +47 -10
  149. package/fesm2022/ngwr-input.mjs.map +1 -1
  150. package/fesm2022/ngwr-knob.mjs +44 -8
  151. package/fesm2022/ngwr-knob.mjs.map +1 -1
  152. package/fesm2022/ngwr-layout.mjs +21 -5
  153. package/fesm2022/ngwr-layout.mjs.map +1 -1
  154. package/fesm2022/ngwr-lightbox.mjs +33 -6
  155. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  156. package/fesm2022/ngwr-line-chart.mjs +17 -4
  157. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  158. package/fesm2022/ngwr-list.mjs +2 -2
  159. package/fesm2022/ngwr-list.mjs.map +1 -1
  160. package/fesm2022/ngwr-loading-bar.mjs +2 -2
  161. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  162. package/fesm2022/ngwr-markdown-testing.mjs +516 -0
  163. package/fesm2022/ngwr-markdown-testing.mjs.map +1 -0
  164. package/fesm2022/ngwr-markdown.mjs +1492 -0
  165. package/fesm2022/ngwr-markdown.mjs.map +1 -0
  166. package/fesm2022/ngwr-marquee.mjs +17 -6
  167. package/fesm2022/ngwr-marquee.mjs.map +1 -1
  168. package/fesm2022/ngwr-mention-testing.mjs +513 -0
  169. package/fesm2022/ngwr-mention-testing.mjs.map +1 -0
  170. package/fesm2022/ngwr-mention.mjs +10 -1
  171. package/fesm2022/ngwr-mention.mjs.map +1 -1
  172. package/fesm2022/ngwr-meta.mjs +22 -7
  173. package/fesm2022/ngwr-meta.mjs.map +1 -1
  174. package/fesm2022/ngwr-meter-group.mjs +19 -5
  175. package/fesm2022/ngwr-meter-group.mjs.map +1 -1
  176. package/fesm2022/ngwr-overlay.mjs +41 -1
  177. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  178. package/fesm2022/ngwr-pagination-testing.mjs +389 -0
  179. package/fesm2022/ngwr-pagination-testing.mjs.map +1 -0
  180. package/fesm2022/ngwr-pagination.mjs +14 -2
  181. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  182. package/fesm2022/ngwr-popconfirm-testing.mjs +309 -0
  183. package/fesm2022/ngwr-popconfirm-testing.mjs.map +1 -0
  184. package/fesm2022/ngwr-popconfirm.mjs +95 -17
  185. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  186. package/fesm2022/ngwr-popover-testing.mjs +316 -0
  187. package/fesm2022/ngwr-popover-testing.mjs.map +1 -0
  188. package/fesm2022/ngwr-popover.mjs +21 -3
  189. package/fesm2022/ngwr-popover.mjs.map +1 -1
  190. package/fesm2022/ngwr-pull-to-refresh.mjs +17 -2
  191. package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -1
  192. package/fesm2022/ngwr-qr.mjs +13 -3
  193. package/fesm2022/ngwr-qr.mjs.map +1 -1
  194. package/fesm2022/ngwr-radio-testing.mjs +392 -0
  195. package/fesm2022/ngwr-radio-testing.mjs.map +1 -0
  196. package/fesm2022/ngwr-radio.mjs +10 -3
  197. package/fesm2022/ngwr-radio.mjs.map +1 -1
  198. package/fesm2022/ngwr-rating-testing.mjs +384 -0
  199. package/fesm2022/ngwr-rating-testing.mjs.map +1 -0
  200. package/fesm2022/ngwr-rating.mjs +37 -2
  201. package/fesm2022/ngwr-rating.mjs.map +1 -1
  202. package/fesm2022/ngwr-segmented-testing.mjs +512 -0
  203. package/fesm2022/ngwr-segmented-testing.mjs.map +1 -0
  204. package/fesm2022/ngwr-select-testing.mjs +268 -0
  205. package/fesm2022/ngwr-select-testing.mjs.map +1 -0
  206. package/fesm2022/ngwr-select.mjs +87 -16
  207. package/fesm2022/ngwr-select.mjs.map +1 -1
  208. package/fesm2022/ngwr-shiny-text.mjs +2 -2
  209. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  210. package/fesm2022/ngwr-sidebar.mjs +65 -12
  211. package/fesm2022/ngwr-sidebar.mjs.map +1 -1
  212. package/fesm2022/ngwr-slider-testing.mjs +478 -0
  213. package/fesm2022/ngwr-slider-testing.mjs.map +1 -0
  214. package/fesm2022/ngwr-slider.mjs +57 -13
  215. package/fesm2022/ngwr-slider.mjs.map +1 -1
  216. package/fesm2022/ngwr-sparkline.mjs +26 -6
  217. package/fesm2022/ngwr-sparkline.mjs.map +1 -1
  218. package/fesm2022/ngwr-speed-dial.mjs +37 -4
  219. package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
  220. package/fesm2022/ngwr-spinner.mjs +12 -3
  221. package/fesm2022/ngwr-spinner.mjs.map +1 -1
  222. package/fesm2022/ngwr-splash-cursor.mjs +2 -2
  223. package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
  224. package/fesm2022/ngwr-split-text.mjs +2 -2
  225. package/fesm2022/ngwr-split-text.mjs.map +1 -1
  226. package/fesm2022/ngwr-splitter.mjs +70 -9
  227. package/fesm2022/ngwr-splitter.mjs.map +1 -1
  228. package/fesm2022/ngwr-spotlight-card.mjs +2 -2
  229. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  230. package/fesm2022/ngwr-star-border.mjs +2 -2
  231. package/fesm2022/ngwr-star-border.mjs.map +1 -1
  232. package/fesm2022/ngwr-statistic.mjs +24 -7
  233. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  234. package/fesm2022/ngwr-stepper-testing.mjs +477 -0
  235. package/fesm2022/ngwr-stepper-testing.mjs.map +1 -0
  236. package/fesm2022/ngwr-switch-testing.mjs +77 -0
  237. package/fesm2022/ngwr-switch-testing.mjs.map +1 -0
  238. package/fesm2022/ngwr-switch.mjs +9 -3
  239. package/fesm2022/ngwr-switch.mjs.map +1 -1
  240. package/fesm2022/ngwr-table-testing.mjs +580 -0
  241. package/fesm2022/ngwr-table-testing.mjs.map +1 -0
  242. package/fesm2022/ngwr-table.mjs +87 -14
  243. package/fesm2022/ngwr-table.mjs.map +1 -1
  244. package/fesm2022/ngwr-tabs-testing.mjs +617 -0
  245. package/fesm2022/ngwr-tabs-testing.mjs.map +1 -0
  246. package/fesm2022/ngwr-tabs.mjs +38 -6
  247. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  248. package/fesm2022/ngwr-textarea-testing.mjs +238 -0
  249. package/fesm2022/ngwr-textarea-testing.mjs.map +1 -0
  250. package/fesm2022/ngwr-textarea.mjs +32 -4
  251. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  252. package/fesm2022/ngwr-tilt-card.mjs +2 -2
  253. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  254. package/fesm2022/ngwr-toast-testing.mjs +101 -0
  255. package/fesm2022/ngwr-toast-testing.mjs.map +1 -0
  256. package/fesm2022/ngwr-toast.mjs +2 -2
  257. package/fesm2022/ngwr-toast.mjs.map +1 -1
  258. package/fesm2022/ngwr-tour.mjs +61 -9
  259. package/fesm2022/ngwr-tour.mjs.map +1 -1
  260. package/fesm2022/ngwr-transfer-testing.mjs +538 -0
  261. package/fesm2022/ngwr-transfer-testing.mjs.map +1 -0
  262. package/fesm2022/ngwr-transfer.mjs +45 -14
  263. package/fesm2022/ngwr-transfer.mjs.map +1 -1
  264. package/fesm2022/ngwr-tree-testing.mjs +734 -0
  265. package/fesm2022/ngwr-tree-testing.mjs.map +1 -0
  266. package/fesm2022/ngwr-tree.mjs +73 -7
  267. package/fesm2022/ngwr-tree.mjs.map +1 -1
  268. package/fesm2022/ngwr-typewriter.mjs +5 -3
  269. package/fesm2022/ngwr-typewriter.mjs.map +1 -1
  270. package/fesm2022/ngwr-version.mjs +1 -1
  271. package/fesm2022/ngwr-version.mjs.map +1 -1
  272. package/fesm2022/ngwr-virtual-scroll.mjs +31 -5
  273. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  274. package/fesm2022/ngwr-waves.mjs +3 -3
  275. package/fesm2022/ngwr-waves.mjs.map +1 -1
  276. package/fesm2022/ngwr-window.mjs +8 -0
  277. package/fesm2022/ngwr-window.mjs.map +1 -1
  278. package/gauge/styles/_index.scss +1 -1
  279. package/glitch-text/styles/_index.scss +4 -0
  280. package/i18n/en.json +48 -0
  281. package/i18n/ru.json +48 -0
  282. package/image-cropper/styles/_index.scss +13 -1
  283. package/input/styles/_index.scss +2 -2
  284. package/input-number/styles/_index.scss +7 -2
  285. package/knob/styles/_index.scss +8 -1
  286. package/layout/styles/_index.scss +3 -3
  287. package/lightbox/styles/_index.scss +10 -2
  288. package/line-chart/styles/_index.scss +6 -0
  289. package/llms-full.txt +151 -4
  290. package/llms.txt +57 -8
  291. package/loading-bar/styles/_index.scss +1 -2
  292. package/markdown/styles/_index.scss +296 -0
  293. package/marquee/styles/_index.scss +12 -0
  294. package/mcp/api.js +512 -0
  295. package/mcp/catalog.js +157 -0
  296. package/mcp/server.js +273 -0
  297. package/mcp/tools.js +366 -0
  298. package/meter-group/styles/_index.scss +1 -1
  299. package/package.json +186 -35
  300. package/pagination/styles/_index.scss +6 -6
  301. package/popover/styles/_index.scss +37 -5
  302. package/rating/styles/_index.scss +10 -0
  303. package/schematics/use/symbol-map.json +2 -0
  304. package/segmented/styles/_index.scss +7 -0
  305. package/select/styles/_index.scss +29 -9
  306. package/sidebar/styles/_index.scss +30 -5
  307. package/slider/styles/_index.scss +15 -0
  308. package/speed-dial/styles/_index.scss +20 -0
  309. package/split-text/styles/_index.scss +13 -0
  310. package/star-border/styles/_index.scss +2 -0
  311. package/stepper/styles/_index.scss +1 -1
  312. package/styles/_grid.scss +4 -4
  313. package/styles.scss +1 -0
  314. package/switch/styles/_index.scss +5 -3
  315. package/table/styles/_index.scss +22 -11
  316. package/tabs/styles/_index.scss +11 -1
  317. package/textarea/styles/_index.scss +5 -0
  318. package/theme/styles/_colors.scss +29 -13
  319. package/theme/styles/_dark.scss +11 -3
  320. package/theme/styles/_mixins.scss +3 -0
  321. package/timeline/styles/_index.scss +2 -2
  322. package/toast/styles/_index.scss +17 -8
  323. package/toolbar/styles/_index.scss +3 -3
  324. package/tour/styles/_index.scss +7 -1
  325. package/tree/styles/_index.scss +5 -3
  326. package/types/ngwr-action-sheet.d.ts +9 -1
  327. package/types/ngwr-affix.d.ts +7 -1
  328. package/types/ngwr-anchor.d.ts +8 -1
  329. package/types/ngwr-avatar.d.ts +13 -3
  330. package/types/ngwr-bar-chart.d.ts +16 -0
  331. package/types/ngwr-burger.d.ts +6 -2
  332. package/types/ngwr-button-testing.d.ts +85 -0
  333. package/types/ngwr-button.d.ts +26 -10
  334. package/types/ngwr-calendar-heatmap.d.ts +16 -2
  335. package/types/ngwr-calendar.d.ts +10 -0
  336. package/types/ngwr-carousel-testing.d.ts +257 -0
  337. package/types/ngwr-carousel.d.ts +20 -4
  338. package/types/ngwr-cascader-testing.d.ts +392 -0
  339. package/types/ngwr-checkbox-testing.d.ts +77 -0
  340. package/types/ngwr-checkbox.d.ts +7 -2
  341. package/types/ngwr-collapse-testing.d.ts +290 -0
  342. package/types/ngwr-color-picker.d.ts +20 -11
  343. package/types/ngwr-command-palette-testing.d.ts +437 -0
  344. package/types/ngwr-command-palette.d.ts +25 -2
  345. package/types/ngwr-compare.d.ts +50 -2
  346. package/types/ngwr-config.d.ts +176 -0
  347. package/types/ngwr-context-menu-testing.d.ts +401 -0
  348. package/types/ngwr-context-menu.d.ts +65 -17
  349. package/types/ngwr-counter.d.ts +6 -1
  350. package/types/ngwr-date-adapter-luxon.d.ts +26 -0
  351. package/types/ngwr-date-picker-testing.d.ts +518 -0
  352. package/types/ngwr-date-picker.d.ts +4 -0
  353. package/types/ngwr-dialog-testing.d.ts +79 -0
  354. package/types/ngwr-directives.d.ts +10 -1
  355. package/types/ngwr-donut-chart.d.ts +8 -1
  356. package/types/ngwr-drawer-testing.d.ts +196 -0
  357. package/types/ngwr-dropdown-testing.d.ts +202 -0
  358. package/types/ngwr-dropdown.d.ts +7 -1
  359. package/types/ngwr-empty.d.ts +19 -4
  360. package/types/ngwr-event-calendar.d.ts +26 -1
  361. package/types/ngwr-file-upload-testing.d.ts +194 -0
  362. package/types/ngwr-form-testing.d.ts +379 -0
  363. package/types/ngwr-form.d.ts +17 -0
  364. package/types/ngwr-gauge.d.ts +13 -1
  365. package/types/ngwr-image-cropper.d.ts +10 -0
  366. package/types/ngwr-input-number-testing.d.ts +226 -0
  367. package/types/ngwr-input-number.d.ts +29 -1
  368. package/types/ngwr-input-otp-testing.d.ts +299 -0
  369. package/types/ngwr-input-otp.d.ts +23 -2
  370. package/types/ngwr-input-testing.d.ts +84 -0
  371. package/types/ngwr-input.d.ts +20 -6
  372. package/types/ngwr-knob.d.ts +18 -0
  373. package/types/ngwr-layout.d.ts +1 -0
  374. package/types/ngwr-lightbox.d.ts +17 -3
  375. package/types/ngwr-line-chart.d.ts +9 -2
  376. package/types/ngwr-markdown-testing.d.ts +462 -0
  377. package/types/ngwr-markdown.d.ts +534 -0
  378. package/types/ngwr-marquee.d.ts +12 -2
  379. package/types/ngwr-mention-testing.d.ts +359 -0
  380. package/types/ngwr-meta.d.ts +4 -2
  381. package/types/ngwr-meter-group.d.ts +11 -1
  382. package/types/ngwr-overlay.d.ts +33 -2
  383. package/types/ngwr-pagination-testing.d.ts +291 -0
  384. package/types/ngwr-pagination.d.ts +1 -0
  385. package/types/ngwr-popconfirm-testing.d.ts +235 -0
  386. package/types/ngwr-popconfirm.d.ts +31 -21
  387. package/types/ngwr-popover-testing.d.ts +221 -0
  388. package/types/ngwr-popover.d.ts +9 -0
  389. package/types/ngwr-pull-to-refresh.d.ts +7 -0
  390. package/types/ngwr-qr.d.ts +9 -1
  391. package/types/ngwr-radio-testing.d.ts +296 -0
  392. package/types/ngwr-radio.d.ts +8 -2
  393. package/types/ngwr-rating-testing.d.ts +291 -0
  394. package/types/ngwr-rating.d.ts +23 -0
  395. package/types/ngwr-segmented-testing.d.ts +401 -0
  396. package/types/ngwr-select-testing.d.ts +175 -0
  397. package/types/ngwr-select.d.ts +45 -4
  398. package/types/ngwr-sidebar.d.ts +17 -2
  399. package/types/ngwr-slider-testing.d.ts +329 -0
  400. package/types/ngwr-slider.d.ts +35 -1
  401. package/types/ngwr-sparkline.d.ts +12 -2
  402. package/types/ngwr-speed-dial.d.ts +17 -18
  403. package/types/ngwr-spinner.d.ts +8 -1
  404. package/types/ngwr-splitter.d.ts +24 -1
  405. package/types/ngwr-statistic.d.ts +12 -2
  406. package/types/ngwr-stepper-testing.d.ts +346 -0
  407. package/types/ngwr-switch-testing.d.ts +66 -0
  408. package/types/ngwr-switch.d.ts +7 -2
  409. package/types/ngwr-table-testing.d.ts +423 -0
  410. package/types/ngwr-table.d.ts +42 -0
  411. package/types/ngwr-tabs-testing.d.ts +470 -0
  412. package/types/ngwr-tabs.d.ts +9 -0
  413. package/types/ngwr-textarea-testing.d.ts +184 -0
  414. package/types/ngwr-textarea.d.ts +7 -2
  415. package/types/ngwr-toast-testing.d.ts +80 -0
  416. package/types/ngwr-tour.d.ts +27 -0
  417. package/types/ngwr-transfer-testing.d.ts +444 -0
  418. package/types/ngwr-transfer.d.ts +16 -1
  419. package/types/ngwr-tree-testing.d.ts +501 -0
  420. package/types/ngwr-tree.d.ts +33 -0
  421. package/types/ngwr-version.d.ts +1 -1
  422. package/types/ngwr-virtual-scroll.d.ts +13 -1
  423. package/typewriter/styles/_index.scss +1 -1
  424. package/typography/styles/_index.scss +1 -1
  425. package/window/styles/_index.scss +32 -9
@@ -0,0 +1,384 @@
1
+ import { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';
2
+
3
+ /**
4
+ * @license
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
8
+ */
9
+ /**
10
+ * Test harness for one star of a `<wr-rating>`.
11
+ *
12
+ * A star is invisible to a screen reader — the row above it is the `slider` and
13
+ * owns the whole accessible story — but it carries the state the eye reads: how
14
+ * far it is filled, whether it is still a click target, and, while the pointer is
15
+ * over the row, the PREVIEW rather than the committed value. That is the reason
16
+ * this exists as a harness of its own.
17
+ *
18
+ * The fill is read from `--wr-rating-fill`, the per-star custom property the
19
+ * component sets and the stylesheet clips the filled glyph with — a public token,
20
+ * and the only place a half star exists in the DOM.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * const rating = await loader.getHarness(WrRatingHarness.with({ label: 'Overall' }));
25
+ * const [, , third] = await rating.getItems();
26
+ *
27
+ * expect(await third.isPartiallyFilled()).toBe(true);
28
+ * ```
29
+ *
30
+ * @see https://ngwr.dev/guides/testing
31
+ */
32
+ class WrRatingItemHarness extends ComponentHarness {
33
+ static hostSelector = '.wr-rating__slot';
34
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
35
+ static with(options = {}) {
36
+ return new HarnessPredicate(WrRatingItemHarness, options)
37
+ .addOption('fill', options.fill, async (harness, fill) => (await harness.getFill()) === fill)
38
+ .addOption('interactive', options.interactive, async (harness, interactive) => (await harness.isInteractive()) === interactive);
39
+ }
40
+ /**
41
+ * How much of this star is painted, `0` to `1`.
42
+ *
43
+ * While the pointer is over the rating this is the PREVIEW — the component
44
+ * paints `hoverValue ?? value`, so a hovered star reads full before anything is
45
+ * committed. `WrRatingHarness.getValue()` is the committed one.
46
+ */
47
+ async getFill() {
48
+ const raw = (await (await this.host()).getCssValue('--wr-rating-fill')).trim();
49
+ const fill = Number.parseFloat(raw);
50
+ if (Number.isNaN(fill)) {
51
+ throw new Error(`WrRatingItemHarness: could not read this star's fill — \`--wr-rating-fill\` computed to "${raw}". ` +
52
+ 'The rating sets it per star; an environment that drops custom properties cannot answer this.');
53
+ }
54
+ return fill;
55
+ }
56
+ /** Whether the star is painted whole. */
57
+ async isFilled() {
58
+ return (await this.getFill()) >= 1;
59
+ }
60
+ /**
61
+ * Whether the star is painted part-way — a half star.
62
+ *
63
+ * Any fractional value paints one, not only `step="0.5"`: the step governs the
64
+ * keyboard and the pointer, but a fraction written straight into `value` is only
65
+ * clamped to `[0, count]`, never snapped — so `[value]="3.5"` half-fills star four
66
+ * on a whole-star rating.
67
+ */
68
+ async isPartiallyFilled() {
69
+ const fill = await this.getFill();
70
+ return fill > 0 && fill < 1;
71
+ }
72
+ /** Whether the star still takes the pointer — a readonly or disabled rating drops the modifier. */
73
+ async isInteractive() {
74
+ return (await this.host()).hasClass('wr-rating__slot--interactive');
75
+ }
76
+ /**
77
+ * Click this star, picking it whole — star three sets the value to `3`.
78
+ *
79
+ * Clicking the value the rating ALREADY holds clears it instead; that is the
80
+ * component's toggle-off, not an accident of this harness.
81
+ *
82
+ * Needs real layout: the component snaps the value from where the pointer sits
83
+ * inside the star, so this aims at the star's inline-END edge. In jsdom every
84
+ * element is 0×0 and a pointer position over one cannot mean anything — this
85
+ * throws rather than committing the `NaN` such a click computes. Reach for
86
+ * `WrRatingHarness.setValue()` there, which drives the keyboard.
87
+ */
88
+ async click() {
89
+ const { width, height } = await this.box();
90
+ await (await this.host()).click(await this.inlineEndX(width), height / 2);
91
+ }
92
+ /**
93
+ * Click the leading half of this star — `2.5` on star three.
94
+ *
95
+ * On a whole-star rating this is the same as {@link click}: the component snaps
96
+ * UP to its `step`, so half of star three is still three stars. Carries the same
97
+ * layout requirement.
98
+ */
99
+ async clickHalf() {
100
+ const { width, height } = await this.box();
101
+ await (await this.host()).click(width / 2, height / 2);
102
+ }
103
+ /**
104
+ * Move the pointer onto this star, previewing it whole.
105
+ *
106
+ * Sends `mousemove` rather than the `TestElement.hover()` pair: the rating
107
+ * tracks the pointer's x across a star to decide whether it is over the half or
108
+ * the whole, so `mouseenter` alone tells it nothing and leaves the preview
109
+ * unchanged. `WrRatingHarness.unhover()` ends it. Carries the same layout
110
+ * requirement as {@link click}.
111
+ */
112
+ async hover() {
113
+ const { left, top, width, height } = await this.box();
114
+ const clientX = left + (await this.inlineEndX(width));
115
+ await (await this.host()).dispatchEvent('mousemove', { clientX, clientY: top + height / 2 });
116
+ }
117
+ /**
118
+ * The x, relative to the star's own box, that lands on its inline-END edge —
119
+ * the far side of the star, where the rating reads a whole one.
120
+ *
121
+ * The component measures the pointer from the star's inline-START edge, which
122
+ * is the right one once `dir="rtl"` mirrors the row; aiming at the physical
123
+ * right edge there reads ratio 0 and picks one star FEWER. So the side is asked
124
+ * for rather than assumed: `direction` is a computed style, which the harness
125
+ * can read in every environment — jsdom included, where it inherits from an
126
+ * ancestor `dir` attribute like any other browser.
127
+ */
128
+ async inlineEndX(width) {
129
+ const direction = await (await this.host()).getCssValue('direction');
130
+ return direction === 'rtl' ? 0 : width;
131
+ }
132
+ /** The star's box, or a failure that names the reason it has none. */
133
+ async box() {
134
+ const { left, top, width, height } = await (await this.host()).getDimensions();
135
+ if (!width) {
136
+ throw new Error('WrRatingItemHarness: this star has no layout, so a pointer position over it means nothing — the ' +
137
+ 'rating reads the value off where the pointer sits INSIDE the star. Every element is 0×0 in jsdom: ' +
138
+ 'use `WrRatingHarness.setValue()`, which drives the keyboard, or stub `getBoundingClientRect`.');
139
+ }
140
+ return { left, top, width, height };
141
+ }
142
+ }
143
+
144
+ /**
145
+ * @license
146
+ *
147
+ * Use of this source code is governed by an MIT-style license that can be
148
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
149
+ */
150
+ /**
151
+ * Test harness for `<wr-rating>` — the root of a two-class family, since a star
152
+ * carries state of its own: {@link WrRatingItemHarness}.
153
+ *
154
+ * The stars are decoration. Everything a screen reader is told lives on the
155
+ * `.wr-rating__row` inside them, which is the `slider`: `aria-valuenow` is the
156
+ * committed value, `aria-valuemax` the top of the range, and the row — not the
157
+ * host — is the tab stop. So this harness reads the row and, for writes, drives
158
+ * its KEYBOARD: arrows step by the rating's own `step`, `Home` / `End` jump to
159
+ * the ends, `Delete` clears. That is the accessible path, and it is the only one a
160
+ * unit test can take unaided, because the pointer path snaps the value from where
161
+ * the cursor sits inside a star — which needs layout jsdom does not have, so a
162
+ * spec that wants it has to stub the star's box (see
163
+ * {@link WrRatingItemHarness.click}).
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * const rating = await loader.getHarness(WrRatingHarness.with({ label: 'Overall' }));
168
+ *
169
+ * await rating.setValue(4);
170
+ * expect(await rating.getValue()).toBe(4);
171
+ * ```
172
+ *
173
+ * @see https://ngwr.dev/guides/testing
174
+ */
175
+ class WrRatingHarness extends ComponentHarness {
176
+ static hostSelector = 'wr-rating';
177
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
178
+ static with(options = {}) {
179
+ return new HarnessPredicate(WrRatingHarness, options)
180
+ .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))
181
+ .addOption('value', options.value, async (harness, value) => (await harness.getValue()) === value)
182
+ .addOption('readonly', options.readonly, async (harness, readonly) => (await harness.isReadonly()) === readonly)
183
+ .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);
184
+ }
185
+ row = this.locatorFor('.wr-rating__row');
186
+ /**
187
+ * What the control announces itself as — `slider`.
188
+ *
189
+ * Not a `radiogroup`: the value is a number on a continuum with a `step`, the
190
+ * arrows move it and `Home` / `End` bound it, and that is a slider's contract
191
+ * rather than a group of one-of-N choices.
192
+ */
193
+ async getRole() {
194
+ return (await this.row()).getAttribute('role');
195
+ }
196
+ /**
197
+ * The rating's accessible name, from `ariaLabel` or the i18n catalogue.
198
+ *
199
+ * A rating projects no text, so this is the only name it has — and it sits on
200
+ * the row, not on the host, because the row is what carries the role.
201
+ */
202
+ async getLabel() {
203
+ return (await this.row()).getAttribute('aria-label');
204
+ }
205
+ /**
206
+ * The committed value, from `aria-valuenow` — what a screen reader is told, not
207
+ * what is painted, which during a hover is the preview instead.
208
+ *
209
+ * A CLEARED rating is announced as `0`, exactly like a rating of zero stars:
210
+ * `value` is `number | null` and ARIA has no null. So `0` here means "zero or
211
+ * nothing" — assert the bound model when the difference matters, and see
212
+ * {@link clear}.
213
+ */
214
+ async getValue() {
215
+ const raw = await (await this.row()).getAttribute('aria-valuenow');
216
+ const value = Number.parseFloat(raw ?? '');
217
+ if (Number.isNaN(value)) {
218
+ throw new Error(`WrRatingHarness: the slider announces aria-valuenow="${raw}", which is not a number.`);
219
+ }
220
+ return value;
221
+ }
222
+ /** The top of the range, from `aria-valuemax` — the `count` of stars. */
223
+ async getMax() {
224
+ const raw = await (await this.row()).getAttribute('aria-valuemax');
225
+ return Number.parseFloat(raw ?? '');
226
+ }
227
+ /** How many stars are painted. Should always agree with {@link getMax}. */
228
+ async getCount() {
229
+ return (await this.getItems()).length;
230
+ }
231
+ /** The stars, left to right. */
232
+ async getItems(filters = {}) {
233
+ return this.locatorForAll(WrRatingItemHarness.with(filters))();
234
+ }
235
+ /**
236
+ * Each star's fill ratio, left to right — `[1, 1, 0.5, 0, 0]` for two and a
237
+ * half stars out of five.
238
+ *
239
+ * This is what the eye sees, so it follows the hover preview while there is one;
240
+ * {@link getValue} stays on the committed value throughout.
241
+ */
242
+ async getFills() {
243
+ const items = await this.getItems();
244
+ return Promise.all(items.map(item => item.getFill()));
245
+ }
246
+ /** The control size. `'md'` is the default and paints no modifier of its own. */
247
+ async getSize() {
248
+ const host = await this.host();
249
+ if (await host.hasClass('wr-rating--sm'))
250
+ return 'sm';
251
+ if (await host.hasClass('wr-rating--lg'))
252
+ return 'lg';
253
+ return 'md';
254
+ }
255
+ /**
256
+ * Whether the rating displays a value it will not let you change.
257
+ *
258
+ * Read from `aria-readonly` rather than from the `wr-rating--readonly` class:
259
+ * both are public, but the attribute is the one a screen reader acts on, and a
260
+ * rating that looks read-only without saying so is the bug worth catching.
261
+ */
262
+ async isReadonly() {
263
+ return (await (await this.row()).getAttribute('aria-readonly')) === 'true';
264
+ }
265
+ /** Whether the rating refuses interaction — `aria-disabled`, for the same reason. */
266
+ async isDisabled() {
267
+ return (await (await this.row()).getAttribute('aria-disabled')) === 'true';
268
+ }
269
+ /**
270
+ * Whether the rating is in the tab order.
271
+ *
272
+ * A rating that takes no input takes itself out of it (`tabindex="-1"`), so this
273
+ * is `false` while readonly or disabled.
274
+ */
275
+ async isFocusable() {
276
+ const tabIndex = await (await this.row()).getAttribute('tabindex');
277
+ return Number.parseInt(tabIndex ?? '-1', 10) >= 0;
278
+ }
279
+ /**
280
+ * Set the rating, from the keyboard.
281
+ *
282
+ * `Home` first, then one `ArrowUp` per step — the step is not in the DOM, so
283
+ * the only honest way to reach a value is to walk to it and watch where the
284
+ * rating lands. (The top of the range takes `End` instead of walking there.) A
285
+ * host counting value changes therefore sees the intermediate ones, which is what
286
+ * a keyboard user produces too.
287
+ *
288
+ * The BLOCK-axis arrow, deliberately: the stars lie on the inline axis, so
289
+ * `ArrowRight` raises the value in LTR and lowers it under `dir="rtl"`, where
290
+ * the arrows follow visual order. `ArrowUp` means "more" in both, so a spec
291
+ * written against this harness reads the same either way.
292
+ *
293
+ * Throws rather than settling for a near miss: on a value outside `[0, max]`, on
294
+ * one the step cannot land on (`2.5` on a whole-star rating), and on a rating
295
+ * that took no input at all because it is readonly or disabled.
296
+ *
297
+ * `setValue(0)` commits ZERO. It is {@link clear} that returns the model to
298
+ * `null`, and the two are indistinguishable from the DOM.
299
+ */
300
+ async setValue(value) {
301
+ const max = await this.getMax();
302
+ if (!Number.isFinite(value) || value < 0 || value > max) {
303
+ throw new Error(`WrRatingHarness: ${value} is outside this rating's range of [0, ${max}].`);
304
+ }
305
+ const row = await this.row();
306
+ await row.sendKeys(TestKey.HOME);
307
+ if (value === max) {
308
+ await row.sendKeys(TestKey.END);
309
+ }
310
+ else {
311
+ let current = await this.getValue();
312
+ while (current < value) {
313
+ await row.sendKeys(TestKey.UP_ARROW);
314
+ const next = await this.getValue();
315
+ // Standing still means the rating is not listening; the check below says why.
316
+ if (next === current)
317
+ break;
318
+ if (next > value) {
319
+ throw new Error(`WrRatingHarness: this rating cannot land on ${value} — one step took it from ${current} to ` +
320
+ `${next}, so ${value} is not a multiple of its \`step\`.`);
321
+ }
322
+ current = next;
323
+ }
324
+ }
325
+ const landed = await this.getValue();
326
+ if (landed !== value) {
327
+ throw new Error(`WrRatingHarness: asked for ${value}, but the rating reads ${landed} — a readonly or disabled ` +
328
+ 'rating takes no input.');
329
+ }
330
+ }
331
+ /**
332
+ * Clear the rating, the way `Delete` does — the bound value becomes `null`, not
333
+ * `0`.
334
+ *
335
+ * The slider then announces `aria-valuenow="0"` and every star empties, so
336
+ * {@link getValue} cannot tell you this happened. Assert the model.
337
+ */
338
+ async clear() {
339
+ await (await this.row()).sendKeys(TestKey.DELETE);
340
+ }
341
+ /**
342
+ * Bump the rating up by one step — one `ArrowUp`, the arrow that means "more"
343
+ * in both reading directions (see {@link setValue}).
344
+ *
345
+ * The step is the rating's, not this harness's, so this is also how a spec finds
346
+ * out what it is: clear the rating, step up once, read the value.
347
+ * Already at the top, this does nothing; the value clamps rather than wrapping.
348
+ */
349
+ async stepUp() {
350
+ await (await this.row()).sendKeys(TestKey.UP_ARROW);
351
+ }
352
+ /** Bump the rating down by one step — one `ArrowDown`. Clamps at `0`. */
353
+ async stepDown() {
354
+ await (await this.row()).sendKeys(TestKey.DOWN_ARROW);
355
+ }
356
+ /**
357
+ * End a hover preview, dropping the stars back to the committed value.
358
+ *
359
+ * It lives here rather than on the star because the component listens for
360
+ * `mouseleave` on the ROW: leaving one star for the next is not leaving the
361
+ * rating.
362
+ */
363
+ async unhover() {
364
+ await (await this.row()).mouseAway();
365
+ }
366
+ /** Move keyboard focus to the rating — onto the row, which is the tab stop. */
367
+ async focus() {
368
+ return (await this.row()).focus();
369
+ }
370
+ /** Blur the rating. This is what emits `touch`, so a bound field marks itself touched. */
371
+ async blur() {
372
+ return (await this.row()).blur();
373
+ }
374
+ async isFocused() {
375
+ return (await this.row()).isFocused();
376
+ }
377
+ }
378
+
379
+ /**
380
+ * Generated bundle index. Do not edit.
381
+ */
382
+
383
+ export { WrRatingHarness, WrRatingItemHarness };
384
+ //# sourceMappingURL=ngwr-rating-testing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngwr-rating-testing.mjs","sources":["../../../projects/lib/rating/testing/wr-rating-item-harness.ts","../../../projects/lib/rating/testing/wr-rating-harness.ts","../../../projects/lib/rating/testing/ngwr-rating-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 { WrRatingItemHarnessFilters } from './interfaces';\n\n/** The star's own box, once it is known to have one. */\ninterface WrRatingItemBox {\n readonly left: number;\n readonly top: number;\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Test harness for one star of a `<wr-rating>`.\n *\n * A star is invisible to a screen reader — the row above it is the `slider` and\n * owns the whole accessible story — but it carries the state the eye reads: how\n * far it is filled, whether it is still a click target, and, while the pointer is\n * over the row, the PREVIEW rather than the committed value. That is the reason\n * this exists as a harness of its own.\n *\n * The fill is read from `--wr-rating-fill`, the per-star custom property the\n * component sets and the stylesheet clips the filled glyph with — a public token,\n * and the only place a half star exists in the DOM.\n *\n * @example\n * ```ts\n * const rating = await loader.getHarness(WrRatingHarness.with({ label: 'Overall' }));\n * const [, , third] = await rating.getItems();\n *\n * expect(await third.isPartiallyFilled()).toBe(true);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrRatingItemHarness extends ComponentHarness {\n static hostSelector = '.wr-rating__slot';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrRatingItemHarnessFilters = {}): HarnessPredicate<WrRatingItemHarness> {\n return new HarnessPredicate(WrRatingItemHarness, options)\n .addOption('fill', options.fill, async (harness, fill) => (await harness.getFill()) === fill)\n .addOption(\n 'interactive',\n options.interactive,\n async (harness, interactive) => (await harness.isInteractive()) === interactive\n );\n }\n\n /**\n * How much of this star is painted, `0` to `1`.\n *\n * While the pointer is over the rating this is the PREVIEW — the component\n * paints `hoverValue ?? value`, so a hovered star reads full before anything is\n * committed. `WrRatingHarness.getValue()` is the committed one.\n */\n async getFill(): Promise<number> {\n const raw = (await (await this.host()).getCssValue('--wr-rating-fill')).trim();\n const fill = Number.parseFloat(raw);\n if (Number.isNaN(fill)) {\n throw new Error(\n `WrRatingItemHarness: could not read this star's fill — \\`--wr-rating-fill\\` computed to \"${raw}\". ` +\n 'The rating sets it per star; an environment that drops custom properties cannot answer this.'\n );\n }\n return fill;\n }\n\n /** Whether the star is painted whole. */\n async isFilled(): Promise<boolean> {\n return (await this.getFill()) >= 1;\n }\n\n /**\n * Whether the star is painted part-way — a half star.\n *\n * Any fractional value paints one, not only `step=\"0.5\"`: the step governs the\n * keyboard and the pointer, but a fraction written straight into `value` is only\n * clamped to `[0, count]`, never snapped — so `[value]=\"3.5\"` half-fills star four\n * on a whole-star rating.\n */\n async isPartiallyFilled(): Promise<boolean> {\n const fill = await this.getFill();\n return fill > 0 && fill < 1;\n }\n\n /** Whether the star still takes the pointer — a readonly or disabled rating drops the modifier. */\n async isInteractive(): Promise<boolean> {\n return (await this.host()).hasClass('wr-rating__slot--interactive');\n }\n\n /**\n * Click this star, picking it whole — star three sets the value to `3`.\n *\n * Clicking the value the rating ALREADY holds clears it instead; that is the\n * component's toggle-off, not an accident of this harness.\n *\n * Needs real layout: the component snaps the value from where the pointer sits\n * inside the star, so this aims at the star's inline-END edge. In jsdom every\n * element is 0×0 and a pointer position over one cannot mean anything — this\n * throws rather than committing the `NaN` such a click computes. Reach for\n * `WrRatingHarness.setValue()` there, which drives the keyboard.\n */\n async click(): Promise<void> {\n const { width, height } = await this.box();\n await (await this.host()).click(await this.inlineEndX(width), height / 2);\n }\n\n /**\n * Click the leading half of this star — `2.5` on star three.\n *\n * On a whole-star rating this is the same as {@link click}: the component snaps\n * UP to its `step`, so half of star three is still three stars. Carries the same\n * layout requirement.\n */\n async clickHalf(): Promise<void> {\n const { width, height } = await this.box();\n await (await this.host()).click(width / 2, height / 2);\n }\n\n /**\n * Move the pointer onto this star, previewing it whole.\n *\n * Sends `mousemove` rather than the `TestElement.hover()` pair: the rating\n * tracks the pointer's x across a star to decide whether it is over the half or\n * the whole, so `mouseenter` alone tells it nothing and leaves the preview\n * unchanged. `WrRatingHarness.unhover()` ends it. Carries the same layout\n * requirement as {@link click}.\n */\n async hover(): Promise<void> {\n const { left, top, width, height } = await this.box();\n const clientX = left + (await this.inlineEndX(width));\n await (await this.host()).dispatchEvent('mousemove', { clientX, clientY: top + height / 2 });\n }\n\n /**\n * The x, relative to the star's own box, that lands on its inline-END edge —\n * the far side of the star, where the rating reads a whole one.\n *\n * The component measures the pointer from the star's inline-START edge, which\n * is the right one once `dir=\"rtl\"` mirrors the row; aiming at the physical\n * right edge there reads ratio 0 and picks one star FEWER. So the side is asked\n * for rather than assumed: `direction` is a computed style, which the harness\n * can read in every environment — jsdom included, where it inherits from an\n * ancestor `dir` attribute like any other browser.\n */\n private async inlineEndX(width: number): Promise<number> {\n const direction = await (await this.host()).getCssValue('direction');\n return direction === 'rtl' ? 0 : width;\n }\n\n /** The star's box, or a failure that names the reason it has none. */\n private async box(): Promise<WrRatingItemBox> {\n const { left, top, width, height } = await (await this.host()).getDimensions();\n if (!width) {\n throw new Error(\n 'WrRatingItemHarness: this star has no layout, so a pointer position over it means nothing — the ' +\n 'rating reads the value off where the pointer sits INSIDE the star. Every element is 0×0 in jsdom: ' +\n 'use `WrRatingHarness.setValue()`, which drives the keyboard, or stub `getBoundingClientRect`.'\n );\n }\n return { left, top, width, height };\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 { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';\n\nimport type { WrRatingSize } from 'ngwr/rating';\n\nimport type { WrRatingHarnessFilters, WrRatingItemHarnessFilters } from './interfaces';\nimport { WrRatingItemHarness } from './wr-rating-item-harness';\n\n/**\n * Test harness for `<wr-rating>` — the root of a two-class family, since a star\n * carries state of its own: {@link WrRatingItemHarness}.\n *\n * The stars are decoration. Everything a screen reader is told lives on the\n * `.wr-rating__row` inside them, which is the `slider`: `aria-valuenow` is the\n * committed value, `aria-valuemax` the top of the range, and the row — not the\n * host — is the tab stop. So this harness reads the row and, for writes, drives\n * its KEYBOARD: arrows step by the rating's own `step`, `Home` / `End` jump to\n * the ends, `Delete` clears. That is the accessible path, and it is the only one a\n * unit test can take unaided, because the pointer path snaps the value from where\n * the cursor sits inside a star — which needs layout jsdom does not have, so a\n * spec that wants it has to stub the star's box (see\n * {@link WrRatingItemHarness.click}).\n *\n * @example\n * ```ts\n * const rating = await loader.getHarness(WrRatingHarness.with({ label: 'Overall' }));\n *\n * await rating.setValue(4);\n * expect(await rating.getValue()).toBe(4);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrRatingHarness extends ComponentHarness {\n static hostSelector = 'wr-rating';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrRatingHarnessFilters = {}): HarnessPredicate<WrRatingHarness> {\n return new HarnessPredicate(WrRatingHarness, 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('readonly', options.readonly, async (harness, readonly) => (await harness.isReadonly()) === readonly)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n private readonly row = this.locatorFor('.wr-rating__row');\n\n /**\n * What the control announces itself as — `slider`.\n *\n * Not a `radiogroup`: the value is a number on a continuum with a `step`, the\n * arrows move it and `Home` / `End` bound it, and that is a slider's contract\n * rather than a group of one-of-N choices.\n */\n async getRole(): Promise<string | null> {\n return (await this.row()).getAttribute('role');\n }\n\n /**\n * The rating's accessible name, from `ariaLabel` or the i18n catalogue.\n *\n * A rating projects no text, so this is the only name it has — and it sits on\n * the row, not on the host, because the row is what carries the role.\n */\n async getLabel(): Promise<string | null> {\n return (await this.row()).getAttribute('aria-label');\n }\n\n /**\n * The committed value, from `aria-valuenow` — what a screen reader is told, not\n * what is painted, which during a hover is the preview instead.\n *\n * A CLEARED rating is announced as `0`, exactly like a rating of zero stars:\n * `value` is `number | null` and ARIA has no null. So `0` here means \"zero or\n * nothing\" — assert the bound model when the difference matters, and see\n * {@link clear}.\n */\n async getValue(): Promise<number> {\n const raw = await (await this.row()).getAttribute('aria-valuenow');\n const value = Number.parseFloat(raw ?? '');\n if (Number.isNaN(value)) {\n throw new Error(`WrRatingHarness: the slider announces aria-valuenow=\"${raw}\", which is not a number.`);\n }\n return value;\n }\n\n /** The top of the range, from `aria-valuemax` — the `count` of stars. */\n async getMax(): Promise<number> {\n const raw = await (await this.row()).getAttribute('aria-valuemax');\n return Number.parseFloat(raw ?? '');\n }\n\n /** How many stars are painted. Should always agree with {@link getMax}. */\n async getCount(): Promise<number> {\n return (await this.getItems()).length;\n }\n\n /** The stars, left to right. */\n async getItems(filters: WrRatingItemHarnessFilters = {}): Promise<WrRatingItemHarness[]> {\n return this.locatorForAll(WrRatingItemHarness.with(filters))();\n }\n\n /**\n * Each star's fill ratio, left to right — `[1, 1, 0.5, 0, 0]` for two and a\n * half stars out of five.\n *\n * This is what the eye sees, so it follows the hover preview while there is one;\n * {@link getValue} stays on the committed value throughout.\n */\n async getFills(): Promise<number[]> {\n const items = await this.getItems();\n return Promise.all(items.map(item => item.getFill()));\n }\n\n /** The control size. `'md'` is the default and paints no modifier of its own. */\n async getSize(): Promise<WrRatingSize> {\n const host = await this.host();\n if (await host.hasClass('wr-rating--sm')) return 'sm';\n if (await host.hasClass('wr-rating--lg')) return 'lg';\n return 'md';\n }\n\n /**\n * Whether the rating displays a value it will not let you change.\n *\n * Read from `aria-readonly` rather than from the `wr-rating--readonly` class:\n * both are public, but the attribute is the one a screen reader acts on, and a\n * rating that looks read-only without saying so is the bug worth catching.\n */\n async isReadonly(): Promise<boolean> {\n return (await (await this.row()).getAttribute('aria-readonly')) === 'true';\n }\n\n /** Whether the rating refuses interaction — `aria-disabled`, for the same reason. */\n async isDisabled(): Promise<boolean> {\n return (await (await this.row()).getAttribute('aria-disabled')) === 'true';\n }\n\n /**\n * Whether the rating is in the tab order.\n *\n * A rating that takes no input takes itself out of it (`tabindex=\"-1\"`), so this\n * is `false` while readonly or disabled.\n */\n async isFocusable(): Promise<boolean> {\n const tabIndex = await (await this.row()).getAttribute('tabindex');\n return Number.parseInt(tabIndex ?? '-1', 10) >= 0;\n }\n\n /**\n * Set the rating, from the keyboard.\n *\n * `Home` first, then one `ArrowUp` per step — the step is not in the DOM, so\n * the only honest way to reach a value is to walk to it and watch where the\n * rating lands. (The top of the range takes `End` instead of walking there.) A\n * host counting value changes therefore sees the intermediate ones, which is what\n * a keyboard user produces too.\n *\n * The BLOCK-axis arrow, deliberately: the stars lie on the inline axis, so\n * `ArrowRight` raises the value in LTR and lowers it under `dir=\"rtl\"`, where\n * the arrows follow visual order. `ArrowUp` means \"more\" in both, so a spec\n * written against this harness reads the same either way.\n *\n * Throws rather than settling for a near miss: on a value outside `[0, max]`, on\n * one the step cannot land on (`2.5` on a whole-star rating), and on a rating\n * that took no input at all because it is readonly or disabled.\n *\n * `setValue(0)` commits ZERO. It is {@link clear} that returns the model to\n * `null`, and the two are indistinguishable from the DOM.\n */\n async setValue(value: number): Promise<void> {\n const max = await this.getMax();\n if (!Number.isFinite(value) || value < 0 || value > max) {\n throw new Error(`WrRatingHarness: ${value} is outside this rating's range of [0, ${max}].`);\n }\n\n const row = await this.row();\n await row.sendKeys(TestKey.HOME);\n\n if (value === max) {\n await row.sendKeys(TestKey.END);\n } else {\n let current = await this.getValue();\n while (current < value) {\n await row.sendKeys(TestKey.UP_ARROW);\n const next = await this.getValue();\n // Standing still means the rating is not listening; the check below says why.\n if (next === current) break;\n if (next > value) {\n throw new Error(\n `WrRatingHarness: this rating cannot land on ${value} — one step took it from ${current} to ` +\n `${next}, so ${value} is not a multiple of its \\`step\\`.`\n );\n }\n current = next;\n }\n }\n\n const landed = await this.getValue();\n if (landed !== value) {\n throw new Error(\n `WrRatingHarness: asked for ${value}, but the rating reads ${landed} — a readonly or disabled ` +\n 'rating takes no input.'\n );\n }\n }\n\n /**\n * Clear the rating, the way `Delete` does — the bound value becomes `null`, not\n * `0`.\n *\n * The slider then announces `aria-valuenow=\"0\"` and every star empties, so\n * {@link getValue} cannot tell you this happened. Assert the model.\n */\n async clear(): Promise<void> {\n await (await this.row()).sendKeys(TestKey.DELETE);\n }\n\n /**\n * Bump the rating up by one step — one `ArrowUp`, the arrow that means \"more\"\n * in both reading directions (see {@link setValue}).\n *\n * The step is the rating's, not this harness's, so this is also how a spec finds\n * out what it is: clear the rating, step up once, read the value.\n * Already at the top, this does nothing; the value clamps rather than wrapping.\n */\n async stepUp(): Promise<void> {\n await (await this.row()).sendKeys(TestKey.UP_ARROW);\n }\n\n /** Bump the rating down by one step — one `ArrowDown`. Clamps at `0`. */\n async stepDown(): Promise<void> {\n await (await this.row()).sendKeys(TestKey.DOWN_ARROW);\n }\n\n /**\n * End a hover preview, dropping the stars back to the committed value.\n *\n * It lives here rather than on the star because the component listens for\n * `mouseleave` on the ROW: leaving one star for the next is not leaving the\n * rating.\n */\n async unhover(): Promise<void> {\n await (await this.row()).mouseAway();\n }\n\n /** Move keyboard focus to the rating — onto the row, which is the tab stop. */\n async focus(): Promise<void> {\n return (await this.row()).focus();\n }\n\n /** Blur the rating. This is what emits `touch`, so a bound field marks itself touched. */\n async blur(): Promise<void> {\n return (await this.row()).blur();\n }\n\n async isFocused(): Promise<boolean> {\n return (await this.row()).isFocused();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
+ import { Directionality } from '@angular/cdk/bidi';
1
2
  import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion';
2
3
  import * as i0 from '@angular/core';
3
- import { input, model, output, signal, computed, effect, ViewEncapsulation, Component } from '@angular/core';
4
+ import { input, model, output, signal, computed, inject, effect, ViewEncapsulation, Component } from '@angular/core';
4
5
  import { useI18nText } from 'ngwr/i18n';
5
6
  import { clamp } from 'ngwr/utils';
6
7
 
@@ -46,6 +47,16 @@ class WrRating {
46
47
  ...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
47
48
  slots = computed(() => Array.from({ length: this.count() }, (_, i) => i), /* @ts-ignore */
48
49
  ...(ngDevMode ? [{ debugName: "slots" }] : /* istanbul ignore next */ []));
50
+ /**
51
+ * Reading direction, for the two places it changes the answer: the arrows and
52
+ * the pointer ratio inside a star.
53
+ *
54
+ * `optional` because a consumer who never set a direction should not have to
55
+ * provide anything — `Directionality` is root-provided, so this only resolves
56
+ * to `null` in a bare `TestBed`, where LTR is the right assumption. Read per
57
+ * interaction rather than cached, so a runtime flip needs no subscription.
58
+ */
59
+ directionality = inject(Directionality, { optional: true });
49
60
  classes = computed(() => {
50
61
  const parts = ['wr-rating'];
51
62
  const size = this.size();
@@ -98,13 +109,23 @@ class WrRating {
98
109
  const max = this.count();
99
110
  const step = this.step();
100
111
  const current = this.value() ?? 0;
112
+ // Arrows follow VISUAL order (WAI-ARIA APG). The row lays its stars along the
113
+ // inline axis, so under `dir="rtl"` the first star is the RIGHTMOST one and
114
+ // `→` walks down the scale. Up / Down are the block axis and never flip;
115
+ // Home / End mean first / last, a semantic position rather than a physical
116
+ // one, so they don't either.
117
+ const inline = this.isRtl() ? -step : step;
101
118
  let next;
102
119
  switch (event.key) {
103
120
  case 'ArrowRight':
121
+ next = clamp(current + inline, 0, max);
122
+ break;
104
123
  case 'ArrowUp':
105
124
  next = clamp(current + step, 0, max);
106
125
  break;
107
126
  case 'ArrowLeft':
127
+ next = clamp(current - inline, 0, max);
128
+ break;
108
129
  case 'ArrowDown':
109
130
  next = clamp(current - step, 0, max);
110
131
  break;
@@ -128,11 +149,25 @@ class WrRating {
128
149
  this.touch.emit();
129
150
  }
130
151
  // Internals
152
+ /** Whether the row reads right-to-left. */
153
+ isRtl() {
154
+ return this.directionality?.value === 'rtl';
155
+ }
156
+ /**
157
+ * How far into the star the pointer sits, `0` to `1`, measured from its
158
+ * INLINE-start edge — the left one in LTR, the right one in RTL, where the row
159
+ * is mirrored. Taken from `rect.left` alone it reads 1 exactly where an RTL
160
+ * user sees the start of the star, which inverts every half step.
161
+ */
162
+ inlineRatio(clientX, rect) {
163
+ const offset = this.isRtl() ? rect.right - clientX : clientX - rect.left;
164
+ return clamp(offset / rect.width, 0, 1);
165
+ }
131
166
  /** Convert a mouse position over slot `index` to a snapped value. */
132
167
  computeValue(event, index) {
133
168
  const target = event.currentTarget;
134
169
  const rect = target.getBoundingClientRect();
135
- const ratio = clamp((event.clientX - rect.left) / rect.width, 0, 1);
170
+ const ratio = this.inlineRatio(event.clientX, rect);
136
171
  const raw = index + ratio;
137
172
  const step = this.step();
138
173
  const snapped = Math.ceil(raw / step) * step;
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-rating.mjs","sources":["../../../projects/lib/rating/rating.ts","../../../projects/lib/rating/rating.html","../../../projects/lib/rating/ngwr-rating.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, effect, input, model, output, signal } from '@angular/core';\nimport type { FormValueControl } from '@angular/forms/signals';\n\nimport { useI18nText } from 'ngwr/i18n';\nimport { clamp } from 'ngwr/utils';\n\n/**\n * Star rating input. Click or hover to set a value; supports half-star\n * increments via `step=\"0.5\"`. Value is `number | null` (clamped to\n * `[0, count]`).\n *\n * A signal-forms native control: it implements `FormValueControl<number | null>`,\n * so `[formField]` binds straight to its `value` model — no\n * `ControlValueAccessor` in between. `[(value)]` works standalone.\n *\n * Keyboard: `←` / `→` bump by `step`, `Home` / `End` jump to 0 / max.\n * Clicking the current value clears it (toggle off).\n *\n * @example\n * ```html\n * <!-- signal forms -->\n * <wr-rating [formField]=\"form.score\" />\n *\n * <!-- standalone two-way binding -->\n * <wr-rating [(value)]=\"score\" [count]=\"10\" step=\"0.5\" />\n * <wr-rating [value]=\"4.5\" [readonly]=\"true\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/rating\n */\nexport type WrRatingSize = 'sm' | 'md' | 'lg';\n\n@Component({\n selector: 'wr-rating',\n templateUrl: './rating.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n})\nexport class WrRating implements FormValueControl<number | null> {\n /** Total number of slots. @default 5 */\n readonly count = input(5, { transform: (v: unknown): number => Math.max(1, coerceNumberProperty(v, 5)) });\n\n /** Step granularity — `1` for whole stars, `0.5` for halves. @default 1 */\n readonly step = input(1 as 0.5 | 1, {\n transform: (v: unknown): 0.5 | 1 => (Number(v) === 0.5 ? 0.5 : 1),\n });\n\n /** Read-only — value is displayed but not interactive. @default false */\n readonly readonly = 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 /** Control size — scales the icons + gaps. @default 'md' */\n readonly size = input<WrRatingSize>('md');\n\n /** Accessible label. Falls back to `rating.label`, then `'Rating'`. */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'rating.label', 'Rating');\n\n /** The rating. Bound by `[formField]`, or two-way via `[(value)]`. */\n readonly value = model<number | null>(null);\n\n /** Emitted on blur so a bound field can mark itself touched. */\n readonly touch = output<void>();\n\n /** Transient hover preview — overrides `value` for display when set. */\n protected readonly hoverValue = signal<number | null>(null);\n\n protected readonly interactive = computed(() => !this.disabled() && !this.readonly());\n\n /** What we actually render — hover wins while hovering. */\n protected readonly displayValue = computed(() => this.hoverValue() ?? this.value() ?? 0);\n\n protected readonly slots = computed(() => Array.from({ length: this.count() }, (_, i) => i));\n\n protected readonly classes = computed(() => {\n const parts = ['wr-rating'];\n const size = this.size();\n if (size !== 'md') parts.push(`wr-rating--${size}`);\n if (this.readonly()) parts.push('wr-rating--readonly');\n if (this.disabled()) parts.push('wr-rating--disabled');\n return parts.join(' ');\n });\n\n constructor() {\n // A model can be written to anything (`[formField]` / `[(value)]`); keep the\n // rating in range by re-clamping out-of-bounds external writes to `[0, count]`.\n // (This is the clamp the old CVA `writeValue` used to apply.)\n effect(() => {\n const v = this.value();\n if (v === null || v === undefined) return;\n const clamped = clamp(Number(v), 0, this.count());\n if (clamped !== v) this.value.set(clamped);\n });\n }\n\n /** Fill ratio for slot `i` in `[0, 1]` — drives the CSS clip width. */\n protected fillFor(i: number): number {\n return clamp(this.displayValue() - i, 0, 1);\n }\n\n // Template handlers\n\n protected onSlotMove(event: MouseEvent, index: number): void {\n if (!this.interactive()) return;\n this.hoverValue.set(this.computeValue(event, index));\n }\n\n protected onLeave(): void {\n this.hoverValue.set(null);\n }\n\n protected onSlotClick(event: MouseEvent, index: number): void {\n if (!this.interactive()) return;\n const next = this.computeValue(event, index);\n // Click the current value → clear it.\n const final = next === this.value() ? null : next;\n this.commit(final);\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (!this.interactive()) return;\n const max = this.count();\n const step = this.step();\n const current = this.value() ?? 0;\n let next: number | null;\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = clamp(current + step, 0, max);\n break;\n case 'ArrowLeft':\n case 'ArrowDown':\n next = clamp(current - step, 0, max);\n break;\n case 'Home':\n next = 0;\n break;\n case 'End':\n next = max;\n break;\n case 'Delete':\n case 'Backspace':\n next = null;\n break;\n default:\n return;\n }\n event.preventDefault();\n this.commit(next);\n }\n\n protected onBlur(): void {\n this.touch.emit();\n }\n\n // Internals\n\n /** Convert a mouse position over slot `index` to a snapped value. */\n private computeValue(event: MouseEvent, index: number): number {\n const target = event.currentTarget as HTMLElement;\n const rect = target.getBoundingClientRect();\n const ratio = clamp((event.clientX - rect.left) / rect.width, 0, 1);\n const raw = index + ratio;\n const step = this.step();\n const snapped = Math.ceil(raw / step) * step;\n return clamp(snapped, step, this.count());\n }\n\n private commit(value: number | null): void {\n this.value.set(value);\n this.hoverValue.set(null);\n }\n}\n","<div\n class=\"wr-rating__row\"\n role=\"slider\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"count()\"\n [attr.aria-valuenow]=\"value() ?? 0\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"interactive() ? 0 : -1\"\n (keydown)=\"onKeydown($event)\"\n (mouseleave)=\"onLeave()\"\n (blur)=\"onBlur()\"\n>\n @for (slot of slots(); track $index) {\n <!-- The parent row owns keyboard focus + handlers; slots are pointer-only\n click targets, so the a11y rules below are intentionally suppressed. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <span\n class=\"wr-rating__slot\"\n [class.wr-rating__slot--interactive]=\"interactive()\"\n [style.--wr-rating-fill]=\"fillFor($index)\"\n (mousemove)=\"onSlotMove($event, $index)\"\n (click)=\"onSlotClick($event, $index)\"\n >\n <!-- Outline (always visible) -->\n <svg class=\"wr-rating__icon wr-rating__icon--bg\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n d=\"M12 2.5l2.95 5.98 6.6.96-4.78 4.66 1.13 6.58L12 17.6l-5.9 3.08 1.13-6.58L2.45 9.44l6.6-.96L12 2.5z\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <!-- Filled overlay, clipped by --wr-rating-fill (0..1) -->\n <svg class=\"wr-rating__icon wr-rating__icon--fg\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n d=\"M12 2.5l2.95 5.98 6.6.96-4.78 4.66 1.13 6.58L12 17.6l-5.9 3.08 1.13-6.58L2.45 9.44l6.6-.96L12 2.5z\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n }\n</div>\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-rating.mjs","sources":["../../../projects/lib/rating/rating.ts","../../../projects/lib/rating/rating.html","../../../projects/lib/rating/ngwr-rating.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 { Component, ViewEncapsulation, computed, effect, inject, input, model, output, signal } from '@angular/core';\nimport type { FormValueControl } from '@angular/forms/signals';\n\nimport { useI18nText } from 'ngwr/i18n';\nimport { clamp } from 'ngwr/utils';\n\n/**\n * Star rating input. Click or hover to set a value; supports half-star\n * increments via `step=\"0.5\"`. Value is `number | null` (clamped to\n * `[0, count]`).\n *\n * A signal-forms native control: it implements `FormValueControl<number | null>`,\n * so `[formField]` binds straight to its `value` model — no\n * `ControlValueAccessor` in between. `[(value)]` works standalone.\n *\n * Keyboard: `←` / `→` bump by `step`, `Home` / `End` jump to 0 / max.\n * Clicking the current value clears it (toggle off).\n *\n * The stars sit on the inline axis, so under `dir=\"rtl\"` the row is mirrored and\n * both halves of the input mirror with it: `→` walks toward the low end, and a\n * click is measured from the star's inline-start (right) edge.\n *\n * @example\n * ```html\n * <!-- signal forms -->\n * <wr-rating [formField]=\"form.score\" />\n *\n * <!-- standalone two-way binding -->\n * <wr-rating [(value)]=\"score\" [count]=\"10\" step=\"0.5\" />\n * <wr-rating [value]=\"4.5\" [readonly]=\"true\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/rating\n */\nexport type WrRatingSize = 'sm' | 'md' | 'lg';\n\n@Component({\n selector: 'wr-rating',\n templateUrl: './rating.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n})\nexport class WrRating implements FormValueControl<number | null> {\n /** Total number of slots. @default 5 */\n readonly count = input(5, { transform: (v: unknown): number => Math.max(1, coerceNumberProperty(v, 5)) });\n\n /** Step granularity — `1` for whole stars, `0.5` for halves. @default 1 */\n readonly step = input(1 as 0.5 | 1, {\n transform: (v: unknown): 0.5 | 1 => (Number(v) === 0.5 ? 0.5 : 1),\n });\n\n /** Read-only — value is displayed but not interactive. @default false */\n readonly readonly = 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 /** Control size — scales the icons + gaps. @default 'md' */\n readonly size = input<WrRatingSize>('md');\n\n /** Accessible label. Falls back to `rating.label`, then `'Rating'`. */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'rating.label', 'Rating');\n\n /** The rating. Bound by `[formField]`, or two-way via `[(value)]`. */\n readonly value = model<number | null>(null);\n\n /** Emitted on blur so a bound field can mark itself touched. */\n readonly touch = output<void>();\n\n /** Transient hover preview — overrides `value` for display when set. */\n protected readonly hoverValue = signal<number | null>(null);\n\n protected readonly interactive = computed(() => !this.disabled() && !this.readonly());\n\n /** What we actually render — hover wins while hovering. */\n protected readonly displayValue = computed(() => this.hoverValue() ?? this.value() ?? 0);\n\n protected readonly slots = computed(() => Array.from({ length: this.count() }, (_, i) => i));\n\n /**\n * Reading direction, for the two places it changes the answer: the arrows and\n * the pointer ratio inside a star.\n *\n * `optional` because a consumer who never set a direction should not have to\n * provide anything — `Directionality` is root-provided, so this only resolves\n * to `null` in a bare `TestBed`, where LTR is the right assumption. Read per\n * interaction rather than cached, so a runtime flip needs no subscription.\n */\n private readonly directionality = inject(Directionality, { optional: true });\n\n protected readonly classes = computed(() => {\n const parts = ['wr-rating'];\n const size = this.size();\n if (size !== 'md') parts.push(`wr-rating--${size}`);\n if (this.readonly()) parts.push('wr-rating--readonly');\n if (this.disabled()) parts.push('wr-rating--disabled');\n return parts.join(' ');\n });\n\n constructor() {\n // A model can be written to anything (`[formField]` / `[(value)]`); keep the\n // rating in range by re-clamping out-of-bounds external writes to `[0, count]`.\n // (This is the clamp the old CVA `writeValue` used to apply.)\n effect(() => {\n const v = this.value();\n if (v === null || v === undefined) return;\n const clamped = clamp(Number(v), 0, this.count());\n if (clamped !== v) this.value.set(clamped);\n });\n }\n\n /** Fill ratio for slot `i` in `[0, 1]` — drives the CSS clip width. */\n protected fillFor(i: number): number {\n return clamp(this.displayValue() - i, 0, 1);\n }\n\n // Template handlers\n\n protected onSlotMove(event: MouseEvent, index: number): void {\n if (!this.interactive()) return;\n this.hoverValue.set(this.computeValue(event, index));\n }\n\n protected onLeave(): void {\n this.hoverValue.set(null);\n }\n\n protected onSlotClick(event: MouseEvent, index: number): void {\n if (!this.interactive()) return;\n const next = this.computeValue(event, index);\n // Click the current value → clear it.\n const final = next === this.value() ? null : next;\n this.commit(final);\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (!this.interactive()) return;\n const max = this.count();\n const step = this.step();\n const current = this.value() ?? 0;\n // Arrows follow VISUAL order (WAI-ARIA APG). The row lays its stars along the\n // inline axis, so under `dir=\"rtl\"` the first star is the RIGHTMOST one and\n // `→` walks down the scale. Up / Down are the block axis and never flip;\n // Home / End mean first / last, a semantic position rather than a physical\n // one, so they don't either.\n const inline = this.isRtl() ? -step : step;\n let next: number | null;\n switch (event.key) {\n case 'ArrowRight':\n next = clamp(current + inline, 0, max);\n break;\n case 'ArrowUp':\n next = clamp(current + step, 0, max);\n break;\n case 'ArrowLeft':\n next = clamp(current - inline, 0, max);\n break;\n case 'ArrowDown':\n next = clamp(current - step, 0, max);\n break;\n case 'Home':\n next = 0;\n break;\n case 'End':\n next = max;\n break;\n case 'Delete':\n case 'Backspace':\n next = null;\n break;\n default:\n return;\n }\n event.preventDefault();\n this.commit(next);\n }\n\n protected onBlur(): void {\n this.touch.emit();\n }\n\n // Internals\n\n /** Whether the row reads right-to-left. */\n private isRtl(): boolean {\n return this.directionality?.value === 'rtl';\n }\n\n /**\n * How far into the star the pointer sits, `0` to `1`, measured from its\n * INLINE-start edge — the left one in LTR, the right one in RTL, where the row\n * is mirrored. Taken from `rect.left` alone it reads 1 exactly where an RTL\n * user sees the start of the star, which inverts every half step.\n */\n private inlineRatio(clientX: number, rect: DOMRect): number {\n const offset = this.isRtl() ? rect.right - clientX : clientX - rect.left;\n return clamp(offset / rect.width, 0, 1);\n }\n\n /** Convert a mouse position over slot `index` to a snapped value. */\n private computeValue(event: MouseEvent, index: number): number {\n const target = event.currentTarget as HTMLElement;\n const rect = target.getBoundingClientRect();\n const ratio = this.inlineRatio(event.clientX, rect);\n const raw = index + ratio;\n const step = this.step();\n const snapped = Math.ceil(raw / step) * step;\n return clamp(snapped, step, this.count());\n }\n\n private commit(value: number | null): void {\n this.value.set(value);\n this.hoverValue.set(null);\n }\n}\n","<div\n class=\"wr-rating__row\"\n role=\"slider\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"count()\"\n [attr.aria-valuenow]=\"value() ?? 0\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"interactive() ? 0 : -1\"\n (keydown)=\"onKeydown($event)\"\n (mouseleave)=\"onLeave()\"\n (blur)=\"onBlur()\"\n>\n @for (slot of slots(); track $index) {\n <!-- The parent row owns keyboard focus + handlers; slots are pointer-only\n click targets, so the a11y rules below are intentionally suppressed. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <span\n class=\"wr-rating__slot\"\n [class.wr-rating__slot--interactive]=\"interactive()\"\n [style.--wr-rating-fill]=\"fillFor($index)\"\n (mousemove)=\"onSlotMove($event, $index)\"\n (click)=\"onSlotClick($event, $index)\"\n >\n <!-- Outline (always visible) -->\n <svg class=\"wr-rating__icon wr-rating__icon--bg\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n d=\"M12 2.5l2.95 5.98 6.6.96-4.78 4.66 1.13 6.58L12 17.6l-5.9 3.08 1.13-6.58L2.45 9.44l6.6-.96L12 2.5z\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <!-- Filled overlay, clipped by --wr-rating-fill (0..1) -->\n <svg class=\"wr-rating__icon wr-rating__icon--fg\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n d=\"M12 2.5l2.95 5.98 6.6.96-4.78 4.66 1.13 6.58L12 17.6l-5.9 3.08 1.13-6.58L2.45 9.44l6.6-.96L12 2.5z\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n stroke-width=\"1.4\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}