ngwr 10.2.1 → 11.1.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 (431) hide show
  1. package/README.md +39 -19
  2. package/action-sheet/styles/_index.scss +4 -1
  3. package/anchor/styles/_index.scss +6 -5
  4. package/back-top/styles/_index.scss +6 -1
  5. package/blur-text/styles/_index.scss +13 -0
  6. package/button/styles/_index.scss +11 -6
  7. package/calendar/styles/_index.scss +11 -2
  8. package/carousel/styles/_index.scss +13 -2
  9. package/cascader/styles/_index.scss +5 -3
  10. package/circular-text/styles/_index.scss +2 -0
  11. package/collapse/styles/_index.scss +1 -1
  12. package/color-picker/styles/_index.scss +6 -1
  13. package/command-palette/styles/_index.scss +2 -1
  14. package/compare/styles/_index.scss +1 -2
  15. package/context-menu/styles/_index.scss +8 -2
  16. package/descriptions/styles/_index.scss +2 -2
  17. package/dialog/styles/_index.scss +7 -0
  18. package/drawer/styles/_index.scss +20 -1
  19. package/dropdown/styles/_index.scss +19 -5
  20. package/empty/styles/_index.scss +10 -0
  21. package/falling-text/styles/_index.scss +2 -1
  22. package/fesm2022/ngwr-action-sheet.mjs +13 -3
  23. package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
  24. package/fesm2022/ngwr-affix.mjs +40 -13
  25. package/fesm2022/ngwr-affix.mjs.map +1 -1
  26. package/fesm2022/ngwr-anchor.mjs +18 -6
  27. package/fesm2022/ngwr-anchor.mjs.map +1 -1
  28. package/fesm2022/ngwr-aurora.mjs +2 -2
  29. package/fesm2022/ngwr-aurora.mjs.map +1 -1
  30. package/fesm2022/ngwr-avatar.mjs +31 -7
  31. package/fesm2022/ngwr-avatar.mjs.map +1 -1
  32. package/fesm2022/ngwr-back-top.mjs +6 -2
  33. package/fesm2022/ngwr-back-top.mjs.map +1 -1
  34. package/fesm2022/ngwr-badge.mjs +1 -1
  35. package/fesm2022/ngwr-badge.mjs.map +1 -1
  36. package/fesm2022/ngwr-bar-chart.mjs +30 -9
  37. package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
  38. package/fesm2022/ngwr-blur-text.mjs +2 -2
  39. package/fesm2022/ngwr-blur-text.mjs.map +1 -1
  40. package/fesm2022/ngwr-border-glow.mjs +2 -2
  41. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  42. package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
  43. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  44. package/fesm2022/ngwr-burger.mjs +9 -4
  45. package/fesm2022/ngwr-burger.mjs.map +1 -1
  46. package/fesm2022/ngwr-button-testing.mjs +96 -0
  47. package/fesm2022/ngwr-button-testing.mjs.map +1 -0
  48. package/fesm2022/ngwr-button.mjs +31 -14
  49. package/fesm2022/ngwr-button.mjs.map +1 -1
  50. package/fesm2022/ngwr-calendar-heatmap.mjs +40 -8
  51. package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
  52. package/fesm2022/ngwr-calendar.mjs +20 -1
  53. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  54. package/fesm2022/ngwr-card.mjs +2 -2
  55. package/fesm2022/ngwr-card.mjs.map +1 -1
  56. package/fesm2022/ngwr-carousel-testing.mjs +377 -0
  57. package/fesm2022/ngwr-carousel-testing.mjs.map +1 -0
  58. package/fesm2022/ngwr-carousel.mjs +67 -13
  59. package/fesm2022/ngwr-carousel.mjs.map +1 -1
  60. package/fesm2022/ngwr-cascader-testing.mjs +534 -0
  61. package/fesm2022/ngwr-cascader-testing.mjs.map +1 -0
  62. package/fesm2022/ngwr-cascader.mjs +2 -2
  63. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  64. package/fesm2022/ngwr-checkbox-testing.mjs +90 -0
  65. package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -0
  66. package/fesm2022/ngwr-checkbox.mjs +9 -3
  67. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  68. package/fesm2022/ngwr-circular-text.mjs +2 -2
  69. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  70. package/fesm2022/ngwr-click-spark.mjs +2 -2
  71. package/fesm2022/ngwr-click-spark.mjs.map +1 -1
  72. package/fesm2022/ngwr-collapse-testing.mjs +368 -0
  73. package/fesm2022/ngwr-collapse-testing.mjs.map +1 -0
  74. package/fesm2022/ngwr-color-picker.mjs +134 -14
  75. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  76. package/fesm2022/ngwr-command-palette-testing.mjs +589 -0
  77. package/fesm2022/ngwr-command-palette-testing.mjs.map +1 -0
  78. package/fesm2022/ngwr-command-palette.mjs +58 -8
  79. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  80. package/fesm2022/ngwr-compare.mjs +103 -13
  81. package/fesm2022/ngwr-compare.mjs.map +1 -1
  82. package/fesm2022/ngwr-config.mjs +106 -0
  83. package/fesm2022/ngwr-config.mjs.map +1 -0
  84. package/fesm2022/ngwr-context-menu-testing.mjs +631 -0
  85. package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -0
  86. package/fesm2022/ngwr-context-menu.mjs +94 -8
  87. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  88. package/fesm2022/ngwr-cookie.mjs +5 -1
  89. package/fesm2022/ngwr-cookie.mjs.map +1 -1
  90. package/fesm2022/ngwr-counter.mjs +11 -3
  91. package/fesm2022/ngwr-counter.mjs.map +1 -1
  92. package/fesm2022/ngwr-date-adapter-luxon.mjs +52 -4
  93. package/fesm2022/ngwr-date-adapter-luxon.mjs.map +1 -1
  94. package/fesm2022/ngwr-date-adapter.mjs +54 -8
  95. package/fesm2022/ngwr-date-adapter.mjs.map +1 -1
  96. package/fesm2022/ngwr-date-picker-testing.mjs +766 -0
  97. package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -0
  98. package/fesm2022/ngwr-date-picker.mjs +73 -3
  99. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  100. package/fesm2022/ngwr-decrypt-text.mjs +27 -9
  101. package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
  102. package/fesm2022/ngwr-dialog-testing.mjs +89 -0
  103. package/fesm2022/ngwr-dialog-testing.mjs.map +1 -0
  104. package/fesm2022/ngwr-directives.mjs +36 -12
  105. package/fesm2022/ngwr-directives.mjs.map +1 -1
  106. package/fesm2022/ngwr-donut-chart.mjs +22 -5
  107. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  108. package/fesm2022/ngwr-drag-drop.mjs +2 -2
  109. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  110. package/fesm2022/ngwr-drawer-testing.mjs +250 -0
  111. package/fesm2022/ngwr-drawer-testing.mjs.map +1 -0
  112. package/fesm2022/ngwr-dropdown-testing.mjs +291 -0
  113. package/fesm2022/ngwr-dropdown-testing.mjs.map +1 -0
  114. package/fesm2022/ngwr-dropdown.mjs +10 -2
  115. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  116. package/fesm2022/ngwr-empty.mjs +24 -7
  117. package/fesm2022/ngwr-empty.mjs.map +1 -1
  118. package/fesm2022/ngwr-event-calendar.mjs +57 -10
  119. package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
  120. package/fesm2022/ngwr-falling-text.mjs +2 -2
  121. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  122. package/fesm2022/ngwr-file-upload-testing.mjs +332 -0
  123. package/fesm2022/ngwr-file-upload-testing.mjs.map +1 -0
  124. package/fesm2022/ngwr-form-testing.mjs +451 -0
  125. package/fesm2022/ngwr-form-testing.mjs.map +1 -0
  126. package/fesm2022/ngwr-form.mjs +19 -3
  127. package/fesm2022/ngwr-form.mjs.map +1 -1
  128. package/fesm2022/ngwr-fuzzy-text.mjs +9 -2
  129. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  130. package/fesm2022/ngwr-gauge.mjs +19 -5
  131. package/fesm2022/ngwr-gauge.mjs.map +1 -1
  132. package/fesm2022/ngwr-glitch-text.mjs +2 -2
  133. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  134. package/fesm2022/ngwr-gradient-text.mjs +2 -2
  135. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  136. package/fesm2022/ngwr-i18n-en.mjs +50 -0
  137. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  138. package/fesm2022/ngwr-i18n-ru.mjs +48 -0
  139. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  140. package/fesm2022/ngwr-image-cropper.mjs +23 -0
  141. package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
  142. package/fesm2022/ngwr-input-number-testing.mjs +306 -0
  143. package/fesm2022/ngwr-input-number-testing.mjs.map +1 -0
  144. package/fesm2022/ngwr-input-number.mjs +35 -3
  145. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  146. package/fesm2022/ngwr-input-otp-testing.mjs +419 -0
  147. package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -0
  148. package/fesm2022/ngwr-input-otp.mjs +36 -5
  149. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  150. package/fesm2022/ngwr-input-testing.mjs +102 -0
  151. package/fesm2022/ngwr-input-testing.mjs.map +1 -0
  152. package/fesm2022/ngwr-input.mjs +47 -10
  153. package/fesm2022/ngwr-input.mjs.map +1 -1
  154. package/fesm2022/ngwr-knob.mjs +44 -8
  155. package/fesm2022/ngwr-knob.mjs.map +1 -1
  156. package/fesm2022/ngwr-layout.mjs +21 -5
  157. package/fesm2022/ngwr-layout.mjs.map +1 -1
  158. package/fesm2022/ngwr-lightbox.mjs +33 -6
  159. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  160. package/fesm2022/ngwr-line-chart.mjs +17 -4
  161. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  162. package/fesm2022/ngwr-list.mjs +2 -2
  163. package/fesm2022/ngwr-list.mjs.map +1 -1
  164. package/fesm2022/ngwr-loading-bar.mjs +2 -2
  165. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  166. package/fesm2022/ngwr-markdown-testing.mjs +516 -0
  167. package/fesm2022/ngwr-markdown-testing.mjs.map +1 -0
  168. package/fesm2022/ngwr-markdown.mjs +1492 -0
  169. package/fesm2022/ngwr-markdown.mjs.map +1 -0
  170. package/fesm2022/ngwr-marquee.mjs +17 -6
  171. package/fesm2022/ngwr-marquee.mjs.map +1 -1
  172. package/fesm2022/ngwr-mention-testing.mjs +513 -0
  173. package/fesm2022/ngwr-mention-testing.mjs.map +1 -0
  174. package/fesm2022/ngwr-mention.mjs +10 -1
  175. package/fesm2022/ngwr-mention.mjs.map +1 -1
  176. package/fesm2022/ngwr-meta.mjs +22 -7
  177. package/fesm2022/ngwr-meta.mjs.map +1 -1
  178. package/fesm2022/ngwr-meter-group.mjs +19 -5
  179. package/fesm2022/ngwr-meter-group.mjs.map +1 -1
  180. package/fesm2022/ngwr-overlay.mjs +41 -1
  181. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  182. package/fesm2022/ngwr-pagination-testing.mjs +389 -0
  183. package/fesm2022/ngwr-pagination-testing.mjs.map +1 -0
  184. package/fesm2022/ngwr-pagination.mjs +14 -2
  185. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  186. package/fesm2022/ngwr-popconfirm-testing.mjs +309 -0
  187. package/fesm2022/ngwr-popconfirm-testing.mjs.map +1 -0
  188. package/fesm2022/ngwr-popconfirm.mjs +95 -17
  189. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  190. package/fesm2022/ngwr-popover-testing.mjs +316 -0
  191. package/fesm2022/ngwr-popover-testing.mjs.map +1 -0
  192. package/fesm2022/ngwr-popover.mjs +21 -3
  193. package/fesm2022/ngwr-popover.mjs.map +1 -1
  194. package/fesm2022/ngwr-pull-to-refresh.mjs +17 -2
  195. package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -1
  196. package/fesm2022/ngwr-qr.mjs +13 -3
  197. package/fesm2022/ngwr-qr.mjs.map +1 -1
  198. package/fesm2022/ngwr-radio-testing.mjs +392 -0
  199. package/fesm2022/ngwr-radio-testing.mjs.map +1 -0
  200. package/fesm2022/ngwr-radio.mjs +10 -3
  201. package/fesm2022/ngwr-radio.mjs.map +1 -1
  202. package/fesm2022/ngwr-rating-testing.mjs +384 -0
  203. package/fesm2022/ngwr-rating-testing.mjs.map +1 -0
  204. package/fesm2022/ngwr-rating.mjs +37 -2
  205. package/fesm2022/ngwr-rating.mjs.map +1 -1
  206. package/fesm2022/ngwr-segmented-testing.mjs +512 -0
  207. package/fesm2022/ngwr-segmented-testing.mjs.map +1 -0
  208. package/fesm2022/ngwr-select-testing.mjs +268 -0
  209. package/fesm2022/ngwr-select-testing.mjs.map +1 -0
  210. package/fesm2022/ngwr-select.mjs +87 -16
  211. package/fesm2022/ngwr-select.mjs.map +1 -1
  212. package/fesm2022/ngwr-shiny-text.mjs +2 -2
  213. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  214. package/fesm2022/ngwr-sidebar.mjs +65 -12
  215. package/fesm2022/ngwr-sidebar.mjs.map +1 -1
  216. package/fesm2022/ngwr-slider-testing.mjs +478 -0
  217. package/fesm2022/ngwr-slider-testing.mjs.map +1 -0
  218. package/fesm2022/ngwr-slider.mjs +57 -13
  219. package/fesm2022/ngwr-slider.mjs.map +1 -1
  220. package/fesm2022/ngwr-sparkline.mjs +26 -6
  221. package/fesm2022/ngwr-sparkline.mjs.map +1 -1
  222. package/fesm2022/ngwr-speed-dial.mjs +37 -4
  223. package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
  224. package/fesm2022/ngwr-spinner.mjs +12 -3
  225. package/fesm2022/ngwr-spinner.mjs.map +1 -1
  226. package/fesm2022/ngwr-splash-cursor.mjs +2 -2
  227. package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
  228. package/fesm2022/ngwr-split-text.mjs +2 -2
  229. package/fesm2022/ngwr-split-text.mjs.map +1 -1
  230. package/fesm2022/ngwr-splitter.mjs +70 -9
  231. package/fesm2022/ngwr-splitter.mjs.map +1 -1
  232. package/fesm2022/ngwr-spotlight-card.mjs +2 -2
  233. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  234. package/fesm2022/ngwr-star-border.mjs +2 -2
  235. package/fesm2022/ngwr-star-border.mjs.map +1 -1
  236. package/fesm2022/ngwr-statistic.mjs +24 -7
  237. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  238. package/fesm2022/ngwr-stepper-testing.mjs +477 -0
  239. package/fesm2022/ngwr-stepper-testing.mjs.map +1 -0
  240. package/fesm2022/ngwr-switch-testing.mjs +77 -0
  241. package/fesm2022/ngwr-switch-testing.mjs.map +1 -0
  242. package/fesm2022/ngwr-switch.mjs +9 -3
  243. package/fesm2022/ngwr-switch.mjs.map +1 -1
  244. package/fesm2022/ngwr-table-testing.mjs +580 -0
  245. package/fesm2022/ngwr-table-testing.mjs.map +1 -0
  246. package/fesm2022/ngwr-table.mjs +87 -14
  247. package/fesm2022/ngwr-table.mjs.map +1 -1
  248. package/fesm2022/ngwr-tabs-testing.mjs +617 -0
  249. package/fesm2022/ngwr-tabs-testing.mjs.map +1 -0
  250. package/fesm2022/ngwr-tabs.mjs +38 -6
  251. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  252. package/fesm2022/ngwr-textarea-testing.mjs +238 -0
  253. package/fesm2022/ngwr-textarea-testing.mjs.map +1 -0
  254. package/fesm2022/ngwr-textarea.mjs +32 -4
  255. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  256. package/fesm2022/ngwr-tilt-card.mjs +2 -2
  257. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  258. package/fesm2022/ngwr-toast-testing.mjs +101 -0
  259. package/fesm2022/ngwr-toast-testing.mjs.map +1 -0
  260. package/fesm2022/ngwr-toast.mjs +2 -2
  261. package/fesm2022/ngwr-toast.mjs.map +1 -1
  262. package/fesm2022/ngwr-tour.mjs +61 -9
  263. package/fesm2022/ngwr-tour.mjs.map +1 -1
  264. package/fesm2022/ngwr-transfer-testing.mjs +538 -0
  265. package/fesm2022/ngwr-transfer-testing.mjs.map +1 -0
  266. package/fesm2022/ngwr-transfer.mjs +45 -14
  267. package/fesm2022/ngwr-transfer.mjs.map +1 -1
  268. package/fesm2022/ngwr-tree-testing.mjs +734 -0
  269. package/fesm2022/ngwr-tree-testing.mjs.map +1 -0
  270. package/fesm2022/ngwr-tree.mjs +73 -7
  271. package/fesm2022/ngwr-tree.mjs.map +1 -1
  272. package/fesm2022/ngwr-typewriter.mjs +5 -3
  273. package/fesm2022/ngwr-typewriter.mjs.map +1 -1
  274. package/fesm2022/ngwr-version.mjs +1 -1
  275. package/fesm2022/ngwr-version.mjs.map +1 -1
  276. package/fesm2022/ngwr-virtual-scroll.mjs +31 -5
  277. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  278. package/fesm2022/ngwr-waves.mjs +3 -3
  279. package/fesm2022/ngwr-waves.mjs.map +1 -1
  280. package/fesm2022/ngwr-window.mjs +8 -0
  281. package/fesm2022/ngwr-window.mjs.map +1 -1
  282. package/file-upload/styles/_index.scss +7 -2
  283. package/gauge/styles/_index.scss +1 -1
  284. package/glitch-text/styles/_index.scss +4 -0
  285. package/i18n/en.json +48 -0
  286. package/i18n/ru.json +48 -0
  287. package/image-cropper/styles/_index.scss +13 -1
  288. package/input/styles/_index.scss +2 -2
  289. package/input-number/styles/_index.scss +7 -2
  290. package/knob/styles/_index.scss +8 -1
  291. package/layout/styles/_index.scss +3 -3
  292. package/lightbox/styles/_index.scss +10 -2
  293. package/line-chart/styles/_index.scss +6 -0
  294. package/llms-full.txt +151 -4
  295. package/llms.txt +57 -8
  296. package/loading-bar/styles/_index.scss +1 -2
  297. package/markdown/styles/_index.scss +296 -0
  298. package/marquee/styles/_index.scss +12 -0
  299. package/mcp/api.js +512 -0
  300. package/mcp/catalog.js +157 -0
  301. package/mcp/server.js +273 -0
  302. package/mcp/tools.js +366 -0
  303. package/meter-group/styles/_index.scss +1 -1
  304. package/package.json +186 -35
  305. package/pagination/styles/_index.scss +6 -6
  306. package/popover/styles/_index.scss +37 -5
  307. package/rating/styles/_index.scss +10 -0
  308. package/result/styles/_index.scss +3 -1
  309. package/schematics/use/symbol-map.json +2 -0
  310. package/segmented/styles/_index.scss +12 -1
  311. package/select/styles/_index.scss +32 -10
  312. package/sidebar/styles/_index.scss +30 -5
  313. package/slider/styles/_index.scss +15 -0
  314. package/speed-dial/styles/_index.scss +20 -0
  315. package/split-text/styles/_index.scss +13 -0
  316. package/star-border/styles/_index.scss +2 -0
  317. package/stepper/styles/_index.scss +19 -3
  318. package/styles/_grid.scss +4 -4
  319. package/styles.scss +1 -0
  320. package/switch/styles/_index.scss +5 -3
  321. package/table/styles/_index.scss +25 -12
  322. package/tabs/styles/_index.scss +11 -1
  323. package/textarea/styles/_index.scss +5 -0
  324. package/theme/styles/_colors.scss +44 -15
  325. package/theme/styles/_dark.scss +35 -15
  326. package/theme/styles/_mixins.scss +3 -0
  327. package/timeline/styles/_index.scss +2 -2
  328. package/toast/styles/_index.scss +17 -8
  329. package/toolbar/styles/_index.scss +3 -3
  330. package/tour/styles/_index.scss +7 -1
  331. package/tree/styles/_index.scss +9 -5
  332. package/types/ngwr-action-sheet.d.ts +9 -1
  333. package/types/ngwr-affix.d.ts +7 -1
  334. package/types/ngwr-anchor.d.ts +8 -1
  335. package/types/ngwr-avatar.d.ts +13 -3
  336. package/types/ngwr-bar-chart.d.ts +16 -0
  337. package/types/ngwr-burger.d.ts +6 -2
  338. package/types/ngwr-button-testing.d.ts +85 -0
  339. package/types/ngwr-button.d.ts +26 -10
  340. package/types/ngwr-calendar-heatmap.d.ts +16 -2
  341. package/types/ngwr-calendar.d.ts +10 -0
  342. package/types/ngwr-carousel-testing.d.ts +257 -0
  343. package/types/ngwr-carousel.d.ts +20 -4
  344. package/types/ngwr-cascader-testing.d.ts +392 -0
  345. package/types/ngwr-checkbox-testing.d.ts +77 -0
  346. package/types/ngwr-checkbox.d.ts +7 -2
  347. package/types/ngwr-collapse-testing.d.ts +290 -0
  348. package/types/ngwr-color-picker.d.ts +20 -11
  349. package/types/ngwr-command-palette-testing.d.ts +437 -0
  350. package/types/ngwr-command-palette.d.ts +25 -2
  351. package/types/ngwr-compare.d.ts +50 -2
  352. package/types/ngwr-config.d.ts +176 -0
  353. package/types/ngwr-context-menu-testing.d.ts +401 -0
  354. package/types/ngwr-context-menu.d.ts +65 -17
  355. package/types/ngwr-counter.d.ts +6 -1
  356. package/types/ngwr-date-adapter-luxon.d.ts +26 -0
  357. package/types/ngwr-date-picker-testing.d.ts +518 -0
  358. package/types/ngwr-date-picker.d.ts +4 -0
  359. package/types/ngwr-dialog-testing.d.ts +79 -0
  360. package/types/ngwr-directives.d.ts +10 -1
  361. package/types/ngwr-donut-chart.d.ts +8 -1
  362. package/types/ngwr-drawer-testing.d.ts +196 -0
  363. package/types/ngwr-dropdown-testing.d.ts +202 -0
  364. package/types/ngwr-dropdown.d.ts +7 -1
  365. package/types/ngwr-empty.d.ts +19 -4
  366. package/types/ngwr-event-calendar.d.ts +26 -1
  367. package/types/ngwr-file-upload-testing.d.ts +194 -0
  368. package/types/ngwr-form-testing.d.ts +379 -0
  369. package/types/ngwr-form.d.ts +17 -0
  370. package/types/ngwr-gauge.d.ts +13 -1
  371. package/types/ngwr-image-cropper.d.ts +10 -0
  372. package/types/ngwr-input-number-testing.d.ts +226 -0
  373. package/types/ngwr-input-number.d.ts +29 -1
  374. package/types/ngwr-input-otp-testing.d.ts +299 -0
  375. package/types/ngwr-input-otp.d.ts +23 -2
  376. package/types/ngwr-input-testing.d.ts +84 -0
  377. package/types/ngwr-input.d.ts +20 -6
  378. package/types/ngwr-knob.d.ts +18 -0
  379. package/types/ngwr-layout.d.ts +1 -0
  380. package/types/ngwr-lightbox.d.ts +17 -3
  381. package/types/ngwr-line-chart.d.ts +9 -2
  382. package/types/ngwr-markdown-testing.d.ts +462 -0
  383. package/types/ngwr-markdown.d.ts +534 -0
  384. package/types/ngwr-marquee.d.ts +12 -2
  385. package/types/ngwr-mention-testing.d.ts +359 -0
  386. package/types/ngwr-meta.d.ts +4 -2
  387. package/types/ngwr-meter-group.d.ts +11 -1
  388. package/types/ngwr-overlay.d.ts +33 -2
  389. package/types/ngwr-pagination-testing.d.ts +291 -0
  390. package/types/ngwr-pagination.d.ts +1 -0
  391. package/types/ngwr-popconfirm-testing.d.ts +235 -0
  392. package/types/ngwr-popconfirm.d.ts +31 -21
  393. package/types/ngwr-popover-testing.d.ts +221 -0
  394. package/types/ngwr-popover.d.ts +9 -0
  395. package/types/ngwr-pull-to-refresh.d.ts +7 -0
  396. package/types/ngwr-qr.d.ts +9 -1
  397. package/types/ngwr-radio-testing.d.ts +296 -0
  398. package/types/ngwr-radio.d.ts +8 -2
  399. package/types/ngwr-rating-testing.d.ts +291 -0
  400. package/types/ngwr-rating.d.ts +23 -0
  401. package/types/ngwr-segmented-testing.d.ts +401 -0
  402. package/types/ngwr-select-testing.d.ts +175 -0
  403. package/types/ngwr-select.d.ts +45 -4
  404. package/types/ngwr-sidebar.d.ts +17 -2
  405. package/types/ngwr-slider-testing.d.ts +329 -0
  406. package/types/ngwr-slider.d.ts +35 -1
  407. package/types/ngwr-sparkline.d.ts +12 -2
  408. package/types/ngwr-speed-dial.d.ts +17 -18
  409. package/types/ngwr-spinner.d.ts +8 -1
  410. package/types/ngwr-splitter.d.ts +24 -1
  411. package/types/ngwr-statistic.d.ts +12 -2
  412. package/types/ngwr-stepper-testing.d.ts +346 -0
  413. package/types/ngwr-switch-testing.d.ts +66 -0
  414. package/types/ngwr-switch.d.ts +7 -2
  415. package/types/ngwr-table-testing.d.ts +423 -0
  416. package/types/ngwr-table.d.ts +42 -0
  417. package/types/ngwr-tabs-testing.d.ts +470 -0
  418. package/types/ngwr-tabs.d.ts +9 -0
  419. package/types/ngwr-textarea-testing.d.ts +184 -0
  420. package/types/ngwr-textarea.d.ts +7 -2
  421. package/types/ngwr-toast-testing.d.ts +80 -0
  422. package/types/ngwr-tour.d.ts +27 -0
  423. package/types/ngwr-transfer-testing.d.ts +444 -0
  424. package/types/ngwr-transfer.d.ts +16 -1
  425. package/types/ngwr-tree-testing.d.ts +501 -0
  426. package/types/ngwr-tree.d.ts +33 -0
  427. package/types/ngwr-version.d.ts +1 -1
  428. package/types/ngwr-virtual-scroll.d.ts +13 -1
  429. package/typewriter/styles/_index.scss +1 -1
  430. package/typography/styles/_index.scss +1 -1
  431. package/window/styles/_index.scss +32 -9
@@ -0,0 +1,538 @@
1
+ import { ComponentHarness, HarnessPredicate } 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 row of a `<wr-transfer>` pane.
11
+ *
12
+ * A row is a `<li>` holding a `<wr-checkbox>`, and the checkbox is the thing the
13
+ * user operates — so the state is read from the native `<input type="checkbox">`
14
+ * inside it, and {@link toggle} clicks that. The pane is deliberately NOT a
15
+ * `role="listbox"` of `role="option"` rows (an option may not contain an
16
+ * interactive control, and the axe gate says so), which is why there is no
17
+ * `aria-selected` here to read: the checkbox's own state IS the announcement.
18
+ *
19
+ * **Checked is not the value.** A tick stages the row for the next move and
20
+ * nothing more; which pane the row sits in is what `[(value)]` carries. Staging is
21
+ * spent — and cleared — by the move that commits it.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const source = await transfer.getPane('source');
26
+ * await (await source.getItem({ label: 'Read' })).check();
27
+ *
28
+ * await transfer.moveTo('target');
29
+ * ```
30
+ *
31
+ * @see https://ngwr.dev/guides/testing
32
+ */
33
+ class WrTransferItemHarness extends ComponentHarness {
34
+ /**
35
+ * `.wr-transfer__item` is a DATA row and nothing else.
36
+ *
37
+ * An empty pane renders an `<li class="wr-transfer__empty">` for its placeholder,
38
+ * so querying `li` would hand that back as a row with no checkbox to read.
39
+ */
40
+ static hostSelector = '.wr-transfer__item';
41
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
42
+ static with(options = {}) {
43
+ return new HarnessPredicate(WrTransferItemHarness, options)
44
+ .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))
45
+ .addOption('checked', options.checked, async (harness, checked) => (await harness.isChecked()) === checked)
46
+ .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);
47
+ }
48
+ input = this.locatorFor('input.wr-checkbox__input');
49
+ /** The row's label, trimmed — the `WrTransferItem.label` the pane shows and the search matches. */
50
+ async getLabel() {
51
+ return (await this.locatorFor('.wr-checkbox__text')()).text();
52
+ }
53
+ /**
54
+ * Whether the row is STAGED for the next move.
55
+ *
56
+ * Not "selected": a row's pane is what the value says, and the tick is transient
57
+ * staging the move spends. `WrTransferPaneHarness.getCheckedLabels()` reads the
58
+ * whole staged set of a pane.
59
+ */
60
+ async isChecked() {
61
+ return (await this.input()).getProperty('checked');
62
+ }
63
+ /**
64
+ * Whether the row refuses staging.
65
+ *
66
+ * The native input's `disabled` — the state a screen reader is given and the one
67
+ * that decides whether a click does anything. It answers `true` for BOTH reasons a
68
+ * row can be inert: the item's own `disabled` flag, and a disabled transfer, which
69
+ * disables every row. The `wr-transfer__item--disabled` modifier only marks the
70
+ * first of those, so it is the narrower question and not the one that predicts
71
+ * behaviour.
72
+ */
73
+ async isDisabled() {
74
+ return (await this.input()).getProperty('disabled');
75
+ }
76
+ /**
77
+ * Flip the row's staging.
78
+ *
79
+ * Refuses a disabled row rather than clicking into the void: the component drops
80
+ * the toggle outright, so the click would resolve having changed nothing and the
81
+ * failure would surface as an unexplained empty move two assertions later.
82
+ */
83
+ async toggle() {
84
+ if (await this.isDisabled()) {
85
+ const label = await this.getLabel();
86
+ throw new Error(`WrTransferItemHarness.toggle(): "${label}" is disabled and the component refuses to stage it. ` +
87
+ 'Either the item carries `disabled`, or the whole transfer does — check isDisabled() on the transfer too.');
88
+ }
89
+ await (await this.input()).click();
90
+ }
91
+ /** Stage the row if it is not already staged. */
92
+ async check() {
93
+ if (!(await this.isChecked()))
94
+ await this.toggle();
95
+ }
96
+ /** Unstage the row if it is staged. */
97
+ async uncheck() {
98
+ if (await this.isChecked())
99
+ await this.toggle();
100
+ }
101
+ /** Move keyboard focus onto the row's checkbox — the row's only tab stop. */
102
+ async focus() {
103
+ return (await this.input()).focus();
104
+ }
105
+ /** Whether the row's checkbox has focus. */
106
+ async isFocused() {
107
+ return (await this.input()).isFocused();
108
+ }
109
+ }
110
+
111
+ /**
112
+ * @license
113
+ *
114
+ * Use of this source code is governed by an MIT-style license that can be
115
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
116
+ */
117
+ /**
118
+ * Test harness for ONE pane of a `<wr-transfer>` — reached with
119
+ * `WrTransferHarness.getPane('source' | 'target')`.
120
+ *
121
+ * The two panes are the same block rendered twice (the component's template
122
+ * iterates them), so they are one harness class keyed by side rather than two sets
123
+ * of `…Source` / `…Target` methods: the side is named once, at `getPane()`, and
124
+ * every question after that is asked of a pane without repeating which one. It also
125
+ * means the symmetry cannot rot — a method that only works on the left is
126
+ * impossible to write here.
127
+ *
128
+ * What a pane SHOWS is the honest scope of everything below. `[items]` minus the
129
+ * value on the left, the value on the right, and then the pane's own filter on top:
130
+ * rows a filter has hidden are not rendered at all, are not counted by the header,
131
+ * and — the component's own rule — are not moved either, however they were staged.
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * const source = await transfer.getPane('source');
136
+ *
137
+ * await source.search('adm');
138
+ * await source.checkAll();
139
+ * expect(await source.getCheckedLabels()).toEqual(['Admin']);
140
+ * ```
141
+ *
142
+ * @see https://ngwr.dev/guides/testing
143
+ */
144
+ class WrTransferPaneHarness extends ComponentHarness {
145
+ /**
146
+ * The pane is a plain `<div>` with no role of its own — the heading names the
147
+ * list, and the checkbox in each row carries the semantics — so its BEM class is
148
+ * the only handle, and being `ViewEncapsulation.None` that class is public API.
149
+ */
150
+ static hostSelector = '.wr-transfer__pane';
151
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
152
+ static with(options = {}) {
153
+ return new HarnessPredicate(WrTransferPaneHarness, options)
154
+ .addOption('side', options.side, async (harness, side) => (await harness.getSide()) === side)
155
+ .addOption('title', options.title, (harness, title) => HarnessPredicate.stringMatches(harness.getTitle(), title));
156
+ }
157
+ list = this.locatorFor('ul.wr-transfer__list');
158
+ selectAllBox = this.locatorFor('.wr-transfer__head input.wr-checkbox__input');
159
+ searchBox = this.locatorForOptional('.wr-transfer__search input');
160
+ /**
161
+ * Which side this pane is.
162
+ *
163
+ * From the `--target` modifier rather than from DOM order: order is a layout fact
164
+ * that `dir="rtl"` and any future reflow are free to change, while the modifier is
165
+ * what the component says the pane MEANS.
166
+ */
167
+ async getSide() {
168
+ return (await (await this.host()).hasClass('wr-transfer__pane--target')) ? 'target' : 'source';
169
+ }
170
+ /** The pane's heading — `[sourceTitle]` / `[targetTitle]`, or the i18n fallback. */
171
+ async getTitle() {
172
+ return (await this.locatorFor('.wr-transfer__title')()).text();
173
+ }
174
+ /**
175
+ * The count beside the heading, verbatim — `'1 / 4'` with the built-in copy.
176
+ *
177
+ * Deliberately not parsed into numbers: it is an i18n FORMAT
178
+ * (`transfer.count`) a consuming app can replace wholesale, so a harness that
179
+ * split it on `/` would answer for the default catalog and break on a translated
180
+ * one. Its two numbers are `(await getCheckedLabels()).length` and
181
+ * `(await getItems()).length` — both of which this harness reads from the rendered
182
+ * rows, so a spec can assert the header agrees with them.
183
+ */
184
+ async getCountText() {
185
+ return (await this.locatorFor('.wr-transfer__count')()).text();
186
+ }
187
+ /**
188
+ * The list's accessible name — the `aria-label` on the `<ul>`, which repeats the
189
+ * heading so that a row announced in isolation still says which pane it is in.
190
+ */
191
+ async getListLabel() {
192
+ return (await this.list()).getAttribute('aria-label');
193
+ }
194
+ /**
195
+ * The explicit `role` on the pane's list, which is `null` — and that `null` is the
196
+ * ANSWER, not a gap worth fixing.
197
+ *
198
+ * The pane is a plain `<ul>` of checkboxes on purpose. Dressing it as a
199
+ * `role="listbox"` of `role="option"` rows reads better in the abstract but is
200
+ * invalid: an option may not contain an interactive control, and the axe gate
201
+ * rejects it. Pinning this is what keeps that "improvement" from looking like a
202
+ * win.
203
+ */
204
+ async getListRole() {
205
+ return (await this.list()).getAttribute('role');
206
+ }
207
+ /** The rows the pane is showing, in render order. */
208
+ async getItems(filters = {}) {
209
+ return this.locatorForAll(WrTransferItemHarness.with(filters))();
210
+ }
211
+ /**
212
+ * The labels the pane is showing, in render order.
213
+ *
214
+ * On the right that is the value, in the order the user built it — not `[items]`
215
+ * order, which the component deliberately does not impose.
216
+ */
217
+ async getItemLabels() {
218
+ const items = await this.getItems();
219
+ return Promise.all(items.map(item => item.getLabel()));
220
+ }
221
+ /** The first row matching the filters, or a failure that says what the pane is showing. */
222
+ async getItem(filters) {
223
+ const [item] = await this.getItems(filters);
224
+ if (!item) {
225
+ const showing = await this.getItemLabels();
226
+ const side = await this.getSide();
227
+ throw new Error(`WrTransferPaneHarness.getItem(): no row matched ${JSON.stringify(filters)} in the ${side} pane, ` +
228
+ `which is showing [${showing.join(', ')}]. A row in the other pane, or one this pane's search has ` +
229
+ 'filtered out, is not here.');
230
+ }
231
+ return item;
232
+ }
233
+ /**
234
+ * The labels of the rows STAGED for the next move, in render order.
235
+ *
236
+ * The staged set and the value are different things, and this is the one the pane
237
+ * shows: read from the rendered rows, so a row staged before a search hid it is
238
+ * absent — exactly as the header count and the move itself treat it.
239
+ */
240
+ async getCheckedLabels() {
241
+ const items = await this.getItems({ checked: true });
242
+ return Promise.all(items.map(item => item.getLabel()));
243
+ }
244
+ /** The placeholder shown in a pane with no rows, or `null` while it has some. */
245
+ async getEmptyText() {
246
+ const empty = await this.locatorForOptional('.wr-transfer__empty')();
247
+ return empty ? empty.text() : null;
248
+ }
249
+ /** Whether this pane has a filter box — `[searchable]` puts one above both panes. */
250
+ async hasSearch() {
251
+ return (await this.searchBox()) !== null;
252
+ }
253
+ /**
254
+ * Type into the pane's filter box, narrowing it to the rows whose label contains
255
+ * the query (case-insensitively).
256
+ *
257
+ * Pass `''` to clear it. No `change` is dispatched — `input` is the event the
258
+ * component listens for, and the one a real keystroke carries; a browser defers
259
+ * `change` on a text field to the commit, so nothing here depends on it. (The
260
+ * keystrokes themselves come with the `keydown` / `keypress` / `keyup` the CDK
261
+ * sends alongside, which this component ignores.)
262
+ */
263
+ async search(query) {
264
+ const box = await this.searchBox();
265
+ if (!box) {
266
+ throw new Error(`WrTransferPaneHarness.search(): the ${await this.getSide()} pane has no filter box — ` +
267
+ '`searchable` is off on the transfer, and it turns them on for both panes at once.');
268
+ }
269
+ // `clear()` dispatches `input` on its own, and `sendKeys('')` throws, so an empty
270
+ // query is the clear and nothing else.
271
+ await box.clear();
272
+ if (query.length > 0)
273
+ await box.sendKeys(query);
274
+ }
275
+ /** What is currently typed in the pane's filter box, or `''`. Throws when there is none. */
276
+ async getSearchValue() {
277
+ return (await this.searchOrThrow('getSearchValue')).getProperty('value');
278
+ }
279
+ /** The filter box's placeholder — `[searchPlaceholder]`, or the i18n fallback. */
280
+ async getSearchPlaceholder() {
281
+ return (await this.searchOrThrow('getSearchPlaceholder')).getProperty('placeholder');
282
+ }
283
+ /**
284
+ * The filter box's accessible name.
285
+ *
286
+ * Composed with the pane heading by the component, and it has to be: both panes
287
+ * carry the same placeholder, so an unnamed pair announces as two identical
288
+ * "Search" fields with no way to tell which list either one filters.
289
+ */
290
+ async getSearchLabel() {
291
+ return (await this.searchOrThrow('getSearchLabel')).getAttribute('aria-label');
292
+ }
293
+ /**
294
+ * The select-all box's accessible name.
295
+ *
296
+ * It has one of its own — the heading names the LIST, so reusing it here would
297
+ * leave a screen reader announcing two different controls identically.
298
+ */
299
+ async getSelectAllLabel() {
300
+ return (await this.selectAllBox()).getAttribute('aria-label');
301
+ }
302
+ /** Whether every row the pane is showing that CAN be staged is staged. */
303
+ async isAllChecked() {
304
+ return (await this.selectAllBox()).getProperty('checked');
305
+ }
306
+ /**
307
+ * Whether some of the pane's stageable rows are staged and others are not.
308
+ *
309
+ * `indeterminate` is a DOM PROPERTY, not an attribute — reading the attribute
310
+ * would report `null` for a box that is visibly dashed.
311
+ */
312
+ async isPartiallyChecked() {
313
+ return (await this.selectAllBox()).getProperty('indeterminate');
314
+ }
315
+ /**
316
+ * Whether the select-all box refuses interaction — a disabled transfer, or a pane
317
+ * with nothing stageable in it (empty, filtered to nothing, or showing only
318
+ * disabled rows).
319
+ */
320
+ async isSelectAllDisabled() {
321
+ return (await this.selectAllBox()).getProperty('disabled');
322
+ }
323
+ /**
324
+ * Click the select-all box once.
325
+ *
326
+ * Its scope is the rows the pane is SHOWING and can stage: a filtered-out row and
327
+ * a disabled row are both outside it. Worth knowing before asserting on a partial
328
+ * pane — the box reads UNchecked while the staging is partial, so one click there
329
+ * stages everything rather than clearing it. {@link uncheckAll} handles that.
330
+ */
331
+ async toggleSelectAll() {
332
+ if (await this.isSelectAllDisabled()) {
333
+ throw new Error(`WrTransferPaneHarness.toggleSelectAll(): the ${await this.getSide()} pane's select-all is disabled, ` +
334
+ 'so the click would change nothing — the transfer is disabled, or this pane shows no row that can be ' +
335
+ 'staged (empty, filtered to nothing, or every row disabled).');
336
+ }
337
+ await (await this.selectAllBox()).click();
338
+ }
339
+ /** Stage every row the pane shows that can be staged. A pane already fully staged is left alone. */
340
+ async checkAll() {
341
+ if (!(await this.isAllChecked()))
342
+ await this.toggleSelectAll();
343
+ }
344
+ /** Clear the pane's staging. */
345
+ async uncheckAll() {
346
+ if (await this.isAllChecked()) {
347
+ await this.toggleSelectAll();
348
+ return;
349
+ }
350
+ // Two clicks from a partial pane, and there is no shortcut: the box is UNchecked
351
+ // there, so the first click stages the rest and only the second clears the lot.
352
+ if (await this.isPartiallyChecked()) {
353
+ await this.toggleSelectAll();
354
+ await this.toggleSelectAll();
355
+ }
356
+ }
357
+ /** The filter box, or a failure naming the input that turns it on. */
358
+ async searchOrThrow(method) {
359
+ const box = await this.searchBox();
360
+ if (!box) {
361
+ throw new Error(`WrTransferPaneHarness.${method}(): the ${await this.getSide()} pane has no filter box — ` +
362
+ '`searchable` is off on the transfer.');
363
+ }
364
+ return box;
365
+ }
366
+ }
367
+
368
+ /**
369
+ * @license
370
+ *
371
+ * Use of this source code is governed by an MIT-style license that can be
372
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
373
+ */
374
+ /**
375
+ * Test harness for `<wr-transfer>` — the root of a small family, since a dual
376
+ * listbox is three things and not one control: {@link WrTransferPaneHarness} for one
377
+ * pane and {@link WrTransferItemHarness} for one row inside it.
378
+ *
379
+ * **Everything is keyed by SIDE, never duplicated per pane.** The two panes are the
380
+ * same block rendered twice, so a `…Source` / `…Target` method pair for each
381
+ * question would double the surface and let the halves drift; instead
382
+ * {@link getPane} takes the side once and the pane answers, and the two whole-
383
+ * control operations that are inherently directional — the move buttons — take the
384
+ * side they move rows INTO. `moveTo('target')` is the right-facing button in an LTR
385
+ * layout, and stays the correct one under `dir="rtl"`, where "right" is not.
386
+ *
387
+ * **The staged ticks are not the value.** `[(value)]` is the RIGHT pane's
388
+ * membership; a tick inside either pane is transient staging that the next move
389
+ * spends and clears. Conflating them is the failure this component invites, so the
390
+ * two are separate questions here: {@link WrTransferPaneHarness.getItemLabels} is
391
+ * what a pane HOLDS (the value, on the right) and
392
+ * {@link WrTransferPaneHarness.getCheckedLabels} is what it has STAGED.
393
+ *
394
+ * Both are scoped to what a pane is showing, which is also the component's own rule
395
+ * for a move: a row staged before a search hid it is no longer counted, no longer
396
+ * ticked, and does not travel.
397
+ *
398
+ * @example
399
+ * ```ts
400
+ * const transfer = await loader.getHarness(WrTransferHarness);
401
+ * const source = await transfer.getPane('source');
402
+ *
403
+ * await (await source.getItem({ label: 'Read' })).check();
404
+ * await transfer.moveTo('target');
405
+ *
406
+ * expect(await (await transfer.getPane('target')).getItemLabels()).toEqual(['Read']);
407
+ * ```
408
+ *
409
+ * @see https://ngwr.dev/guides/testing
410
+ */
411
+ class WrTransferHarness extends ComponentHarness {
412
+ static hostSelector = 'wr-transfer';
413
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
414
+ static with(options = {}) {
415
+ return new HarnessPredicate(WrTransferHarness, options)
416
+ .addOption('sourceTitle', options.sourceTitle, (harness, title) => HarnessPredicate.stringMatches(harness.paneTitle('source'), title))
417
+ .addOption('targetTitle', options.targetTitle, (harness, title) => HarnessPredicate.stringMatches(harness.paneTitle('target'), title))
418
+ .addOption('itemLabel', options.itemLabel, async (harness, label) => {
419
+ for (const shown of await harness.shownLabels()) {
420
+ if (await HarnessPredicate.stringMatches(shown, label))
421
+ return true;
422
+ }
423
+ return false;
424
+ })
425
+ .addOption('searchable', options.searchable, async (harness, searchable) => (await harness.isSearchable()) === searchable)
426
+ .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);
427
+ }
428
+ /**
429
+ * One of the two panes — `'source'` is the left one (the rows outside the value),
430
+ * `'target'` the right one (the value).
431
+ *
432
+ * The side is named here and nowhere else; see the class note.
433
+ */
434
+ async getPane(side) {
435
+ return this.locatorFor(WrTransferPaneHarness.with({ side }))();
436
+ }
437
+ /**
438
+ * Whether the whole control refuses interaction.
439
+ *
440
+ * From the host modifier, which is the only signal the host itself carries: a
441
+ * `<wr-transfer>` element is not a control and publishes no `aria-disabled` of its
442
+ * own — the state reaches assistive tech through the checkboxes, the buttons and
443
+ * the filter boxes it disables, which is where
444
+ * {@link WrTransferItemHarness.isDisabled} and {@link canMoveTo} read it.
445
+ */
446
+ async isDisabled() {
447
+ return (await this.host()).hasClass('wr-transfer--disabled');
448
+ }
449
+ /** Whether the panes have filter boxes — `[searchable]` gives both one or neither. */
450
+ async isSearchable() {
451
+ return (await this.host()).hasClass('wr-transfer--searchable');
452
+ }
453
+ /**
454
+ * Whether the button that moves rows INTO `side` is offering itself.
455
+ *
456
+ * It is enabled only while the OTHER pane has something staged and showing, so
457
+ * this is also the readable way to assert that staging landed — and that a search
458
+ * which hid a staged row took the move away again.
459
+ *
460
+ * Read from the native `disabled` attribute: these are `button[wr-btn]`, the
461
+ * native shape, where that attribute is the state. (`wr-btn` adds `aria-disabled`
462
+ * only for its custom-element shape, on which `disabled` is inert.)
463
+ */
464
+ async canMoveTo(side) {
465
+ return (await (await this.moveButton(side)).getAttribute('disabled')) === null;
466
+ }
467
+ /**
468
+ * The accessible name of the button that moves rows INTO `side` —
469
+ * `[toTargetLabel]` / `[toSourceLabel]`, or the i18n fallback.
470
+ *
471
+ * Worth pinning: the button's only content is an `aria-hidden` chevron, so this
472
+ * `aria-label` is the entire announcement. Lose it and the pair becomes two
473
+ * unnamed buttons.
474
+ */
475
+ async getMoveLabel(side) {
476
+ return (await this.moveButton(side)).getAttribute('aria-label');
477
+ }
478
+ /**
479
+ * Press the button that moves the staged rows INTO `side`, committing them to the
480
+ * value.
481
+ *
482
+ * Only the rows the other pane is SHOWING as staged travel, and the staging is
483
+ * cleared afterwards — the component's rule, not this harness's.
484
+ *
485
+ * Refuses a disabled button rather than pressing it: a native disabled `<button>`
486
+ * swallows the click before Angular's listener sees it, so the call would resolve
487
+ * having moved nothing at all.
488
+ */
489
+ async moveTo(side) {
490
+ if (!(await this.canMoveTo(side))) {
491
+ const from = side === 'target' ? 'source' : 'target';
492
+ throw new Error(`WrTransferHarness.moveTo('${side}'): the button is disabled, so nothing would move. The ${from} pane ` +
493
+ 'has nothing staged and showing — a row staged before a search hid it no longer counts — or the whole ' +
494
+ 'transfer is disabled.');
495
+ }
496
+ await (await this.moveButton(side)).click();
497
+ }
498
+ /**
499
+ * Stage everything the other pane can stage, then move it INTO `side`.
500
+ *
501
+ * "Everything" is the pane's own scope: the rows it is SHOWING, disabled ones
502
+ * excluded. A search narrows it, and with a filter typed this moves what is
503
+ * visible rather than the whole pane.
504
+ */
505
+ async moveAllTo(side) {
506
+ const from = await this.getPane(side === 'target' ? 'source' : 'target');
507
+ await from.checkAll();
508
+ await this.moveTo(side);
509
+ }
510
+ /** The heading of one pane — the `sourceTitle` / `targetTitle` filters run through this. */
511
+ async paneTitle(side) {
512
+ return (await this.getPane(side)).getTitle();
513
+ }
514
+ /** Every label rendered in either pane, for the `itemLabel` filter. */
515
+ async shownLabels() {
516
+ const items = await this.locatorForAll(WrTransferItemHarness)();
517
+ return Promise.all(items.map(item => item.getLabel()));
518
+ }
519
+ /**
520
+ * The move button for a direction, addressed by its `--to-source` / `--to-target`
521
+ * modifier.
522
+ *
523
+ * Not by DOM order, and that is the point: two identically classed buttons whose
524
+ * only difference was their position would let a template reshuffle silently
525
+ * reverse every `moveTo()` in every consumer's suite, with both directions still
526
+ * green. Not by the `aria-label` either — that string is localizable.
527
+ */
528
+ async moveButton(side) {
529
+ return this.locatorFor(`.wr-transfer__move--to-${side}`)();
530
+ }
531
+ }
532
+
533
+ /**
534
+ * Generated bundle index. Do not edit.
535
+ */
536
+
537
+ export { WrTransferHarness, WrTransferItemHarness, WrTransferPaneHarness };
538
+ //# sourceMappingURL=ngwr-transfer-testing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngwr-transfer-testing.mjs","sources":["../../../projects/lib/transfer/testing/wr-transfer-item-harness.ts","../../../projects/lib/transfer/testing/wr-transfer-pane-harness.ts","../../../projects/lib/transfer/testing/wr-transfer-harness.ts","../../../projects/lib/transfer/testing/ngwr-transfer-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 { WrTransferItemHarnessFilters } from './interfaces';\n\n/**\n * Test harness for one row of a `<wr-transfer>` pane.\n *\n * A row is a `<li>` holding a `<wr-checkbox>`, and the checkbox is the thing the\n * user operates — so the state is read from the native `<input type=\"checkbox\">`\n * inside it, and {@link toggle} clicks that. The pane is deliberately NOT a\n * `role=\"listbox\"` of `role=\"option\"` rows (an option may not contain an\n * interactive control, and the axe gate says so), which is why there is no\n * `aria-selected` here to read: the checkbox's own state IS the announcement.\n *\n * **Checked is not the value.** A tick stages the row for the next move and\n * nothing more; which pane the row sits in is what `[(value)]` carries. Staging is\n * spent — and cleared — by the move that commits it.\n *\n * @example\n * ```ts\n * const source = await transfer.getPane('source');\n * await (await source.getItem({ label: 'Read' })).check();\n *\n * await transfer.moveTo('target');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrTransferItemHarness extends ComponentHarness {\n /**\n * `.wr-transfer__item` is a DATA row and nothing else.\n *\n * An empty pane renders an `<li class=\"wr-transfer__empty\">` for its placeholder,\n * so querying `li` would hand that back as a row with no checkbox to read.\n */\n static hostSelector = '.wr-transfer__item';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrTransferItemHarnessFilters = {}): HarnessPredicate<WrTransferItemHarness> {\n return new HarnessPredicate(WrTransferItemHarness, options)\n .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))\n .addOption('checked', options.checked, async (harness, checked) => (await harness.isChecked()) === checked)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n private readonly input = this.locatorFor('input.wr-checkbox__input');\n\n /** The row's label, trimmed — the `WrTransferItem.label` the pane shows and the search matches. */\n async getLabel(): Promise<string> {\n return (await this.locatorFor('.wr-checkbox__text')()).text();\n }\n\n /**\n * Whether the row is STAGED for the next move.\n *\n * Not \"selected\": a row's pane is what the value says, and the tick is transient\n * staging the move spends. `WrTransferPaneHarness.getCheckedLabels()` reads the\n * whole staged set of a pane.\n */\n async isChecked(): Promise<boolean> {\n return (await this.input()).getProperty<boolean>('checked');\n }\n\n /**\n * Whether the row refuses staging.\n *\n * The native input's `disabled` — the state a screen reader is given and the one\n * that decides whether a click does anything. It answers `true` for BOTH reasons a\n * row can be inert: the item's own `disabled` flag, and a disabled transfer, which\n * disables every row. The `wr-transfer__item--disabled` modifier only marks the\n * first of those, so it is the narrower question and not the one that predicts\n * behaviour.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.input()).getProperty<boolean>('disabled');\n }\n\n /**\n * Flip the row's staging.\n *\n * Refuses a disabled row rather than clicking into the void: the component drops\n * the toggle outright, so the click would resolve having changed nothing and the\n * failure would surface as an unexplained empty move two assertions later.\n */\n async toggle(): Promise<void> {\n if (await this.isDisabled()) {\n const label = await this.getLabel();\n throw new Error(\n `WrTransferItemHarness.toggle(): \"${label}\" is disabled and the component refuses to stage it. ` +\n 'Either the item carries `disabled`, or the whole transfer does — check isDisabled() on the transfer too.'\n );\n }\n await (await this.input()).click();\n }\n\n /** Stage the row if it is not already staged. */\n async check(): Promise<void> {\n if (!(await this.isChecked())) await this.toggle();\n }\n\n /** Unstage the row if it is staged. */\n async uncheck(): Promise<void> {\n if (await this.isChecked()) await this.toggle();\n }\n\n /** Move keyboard focus onto the row's checkbox — the row's only tab stop. */\n async focus(): Promise<void> {\n return (await this.input()).focus();\n }\n\n /** Whether the row's checkbox has focus. */\n async isFocused(): Promise<boolean> {\n return (await this.input()).isFocused();\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, type TestElement } from '@angular/cdk/testing';\n\nimport type { WrTransferItemHarnessFilters, WrTransferPaneHarnessFilters, WrTransferSide } from './interfaces';\nimport { WrTransferItemHarness } from './wr-transfer-item-harness';\n\n/**\n * Test harness for ONE pane of a `<wr-transfer>` — reached with\n * `WrTransferHarness.getPane('source' | 'target')`.\n *\n * The two panes are the same block rendered twice (the component's template\n * iterates them), so they are one harness class keyed by side rather than two sets\n * of `…Source` / `…Target` methods: the side is named once, at `getPane()`, and\n * every question after that is asked of a pane without repeating which one. It also\n * means the symmetry cannot rot — a method that only works on the left is\n * impossible to write here.\n *\n * What a pane SHOWS is the honest scope of everything below. `[items]` minus the\n * value on the left, the value on the right, and then the pane's own filter on top:\n * rows a filter has hidden are not rendered at all, are not counted by the header,\n * and — the component's own rule — are not moved either, however they were staged.\n *\n * @example\n * ```ts\n * const source = await transfer.getPane('source');\n *\n * await source.search('adm');\n * await source.checkAll();\n * expect(await source.getCheckedLabels()).toEqual(['Admin']);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrTransferPaneHarness extends ComponentHarness {\n /**\n * The pane is a plain `<div>` with no role of its own — the heading names the\n * list, and the checkbox in each row carries the semantics — so its BEM class is\n * the only handle, and being `ViewEncapsulation.None` that class is public API.\n */\n static hostSelector = '.wr-transfer__pane';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrTransferPaneHarnessFilters = {}): HarnessPredicate<WrTransferPaneHarness> {\n return new HarnessPredicate(WrTransferPaneHarness, options)\n .addOption('side', options.side, async (harness, side) => (await harness.getSide()) === side)\n .addOption('title', options.title, (harness, title) => HarnessPredicate.stringMatches(harness.getTitle(), title));\n }\n\n private readonly list = this.locatorFor('ul.wr-transfer__list');\n private readonly selectAllBox = this.locatorFor('.wr-transfer__head input.wr-checkbox__input');\n private readonly searchBox = this.locatorForOptional('.wr-transfer__search input');\n\n /**\n * Which side this pane is.\n *\n * From the `--target` modifier rather than from DOM order: order is a layout fact\n * that `dir=\"rtl\"` and any future reflow are free to change, while the modifier is\n * what the component says the pane MEANS.\n */\n async getSide(): Promise<WrTransferSide> {\n return (await (await this.host()).hasClass('wr-transfer__pane--target')) ? 'target' : 'source';\n }\n\n /** The pane's heading — `[sourceTitle]` / `[targetTitle]`, or the i18n fallback. */\n async getTitle(): Promise<string> {\n return (await this.locatorFor('.wr-transfer__title')()).text();\n }\n\n /**\n * The count beside the heading, verbatim — `'1 / 4'` with the built-in copy.\n *\n * Deliberately not parsed into numbers: it is an i18n FORMAT\n * (`transfer.count`) a consuming app can replace wholesale, so a harness that\n * split it on `/` would answer for the default catalog and break on a translated\n * one. Its two numbers are `(await getCheckedLabels()).length` and\n * `(await getItems()).length` — both of which this harness reads from the rendered\n * rows, so a spec can assert the header agrees with them.\n */\n async getCountText(): Promise<string> {\n return (await this.locatorFor('.wr-transfer__count')()).text();\n }\n\n /**\n * The list's accessible name — the `aria-label` on the `<ul>`, which repeats the\n * heading so that a row announced in isolation still says which pane it is in.\n */\n async getListLabel(): Promise<string | null> {\n return (await this.list()).getAttribute('aria-label');\n }\n\n /**\n * The explicit `role` on the pane's list, which is `null` — and that `null` is the\n * ANSWER, not a gap worth fixing.\n *\n * The pane is a plain `<ul>` of checkboxes on purpose. Dressing it as a\n * `role=\"listbox\"` of `role=\"option\"` rows reads better in the abstract but is\n * invalid: an option may not contain an interactive control, and the axe gate\n * rejects it. Pinning this is what keeps that \"improvement\" from looking like a\n * win.\n */\n async getListRole(): Promise<string | null> {\n return (await this.list()).getAttribute('role');\n }\n\n /** The rows the pane is showing, in render order. */\n async getItems(filters: WrTransferItemHarnessFilters = {}): Promise<WrTransferItemHarness[]> {\n return this.locatorForAll(WrTransferItemHarness.with(filters))();\n }\n\n /**\n * The labels the pane is showing, in render order.\n *\n * On the right that is the value, in the order the user built it — not `[items]`\n * order, which the component deliberately does not impose.\n */\n async getItemLabels(): Promise<string[]> {\n const items = await this.getItems();\n return Promise.all(items.map(item => item.getLabel()));\n }\n\n /** The first row matching the filters, or a failure that says what the pane is showing. */\n async getItem(filters: WrTransferItemHarnessFilters): Promise<WrTransferItemHarness> {\n const [item] = await this.getItems(filters);\n if (!item) {\n const showing = await this.getItemLabels();\n const side = await this.getSide();\n throw new Error(\n `WrTransferPaneHarness.getItem(): no row matched ${JSON.stringify(filters)} in the ${side} pane, ` +\n `which is showing [${showing.join(', ')}]. A row in the other pane, or one this pane's search has ` +\n 'filtered out, is not here.'\n );\n }\n return item;\n }\n\n /**\n * The labels of the rows STAGED for the next move, in render order.\n *\n * The staged set and the value are different things, and this is the one the pane\n * shows: read from the rendered rows, so a row staged before a search hid it is\n * absent — exactly as the header count and the move itself treat it.\n */\n async getCheckedLabels(): Promise<string[]> {\n const items = await this.getItems({ checked: true });\n return Promise.all(items.map(item => item.getLabel()));\n }\n\n /** The placeholder shown in a pane with no rows, or `null` while it has some. */\n async getEmptyText(): Promise<string | null> {\n const empty = await this.locatorForOptional('.wr-transfer__empty')();\n return empty ? empty.text() : null;\n }\n\n /** Whether this pane has a filter box — `[searchable]` puts one above both panes. */\n async hasSearch(): Promise<boolean> {\n return (await this.searchBox()) !== null;\n }\n\n /**\n * Type into the pane's filter box, narrowing it to the rows whose label contains\n * the query (case-insensitively).\n *\n * Pass `''` to clear it. No `change` is dispatched — `input` is the event the\n * component listens for, and the one a real keystroke carries; a browser defers\n * `change` on a text field to the commit, so nothing here depends on it. (The\n * keystrokes themselves come with the `keydown` / `keypress` / `keyup` the CDK\n * sends alongside, which this component ignores.)\n */\n async search(query: string): Promise<void> {\n const box = await this.searchBox();\n if (!box) {\n throw new Error(\n `WrTransferPaneHarness.search(): the ${await this.getSide()} pane has no filter box — ` +\n '`searchable` is off on the transfer, and it turns them on for both panes at once.'\n );\n }\n\n // `clear()` dispatches `input` on its own, and `sendKeys('')` throws, so an empty\n // query is the clear and nothing else.\n await box.clear();\n if (query.length > 0) await box.sendKeys(query);\n }\n\n /** What is currently typed in the pane's filter box, or `''`. Throws when there is none. */\n async getSearchValue(): Promise<string> {\n return (await this.searchOrThrow('getSearchValue')).getProperty<string>('value');\n }\n\n /** The filter box's placeholder — `[searchPlaceholder]`, or the i18n fallback. */\n async getSearchPlaceholder(): Promise<string> {\n return (await this.searchOrThrow('getSearchPlaceholder')).getProperty<string>('placeholder');\n }\n\n /**\n * The filter box's accessible name.\n *\n * Composed with the pane heading by the component, and it has to be: both panes\n * carry the same placeholder, so an unnamed pair announces as two identical\n * \"Search\" fields with no way to tell which list either one filters.\n */\n async getSearchLabel(): Promise<string | null> {\n return (await this.searchOrThrow('getSearchLabel')).getAttribute('aria-label');\n }\n\n /**\n * The select-all box's accessible name.\n *\n * It has one of its own — the heading names the LIST, so reusing it here would\n * leave a screen reader announcing two different controls identically.\n */\n async getSelectAllLabel(): Promise<string | null> {\n return (await this.selectAllBox()).getAttribute('aria-label');\n }\n\n /** Whether every row the pane is showing that CAN be staged is staged. */\n async isAllChecked(): Promise<boolean> {\n return (await this.selectAllBox()).getProperty<boolean>('checked');\n }\n\n /**\n * Whether some of the pane's stageable rows are staged and others are not.\n *\n * `indeterminate` is a DOM PROPERTY, not an attribute — reading the attribute\n * would report `null` for a box that is visibly dashed.\n */\n async isPartiallyChecked(): Promise<boolean> {\n return (await this.selectAllBox()).getProperty<boolean>('indeterminate');\n }\n\n /**\n * Whether the select-all box refuses interaction — a disabled transfer, or a pane\n * with nothing stageable in it (empty, filtered to nothing, or showing only\n * disabled rows).\n */\n async isSelectAllDisabled(): Promise<boolean> {\n return (await this.selectAllBox()).getProperty<boolean>('disabled');\n }\n\n /**\n * Click the select-all box once.\n *\n * Its scope is the rows the pane is SHOWING and can stage: a filtered-out row and\n * a disabled row are both outside it. Worth knowing before asserting on a partial\n * pane — the box reads UNchecked while the staging is partial, so one click there\n * stages everything rather than clearing it. {@link uncheckAll} handles that.\n */\n async toggleSelectAll(): Promise<void> {\n if (await this.isSelectAllDisabled()) {\n throw new Error(\n `WrTransferPaneHarness.toggleSelectAll(): the ${await this.getSide()} pane's select-all is disabled, ` +\n 'so the click would change nothing — the transfer is disabled, or this pane shows no row that can be ' +\n 'staged (empty, filtered to nothing, or every row disabled).'\n );\n }\n await (await this.selectAllBox()).click();\n }\n\n /** Stage every row the pane shows that can be staged. A pane already fully staged is left alone. */\n async checkAll(): Promise<void> {\n if (!(await this.isAllChecked())) await this.toggleSelectAll();\n }\n\n /** Clear the pane's staging. */\n async uncheckAll(): Promise<void> {\n if (await this.isAllChecked()) {\n await this.toggleSelectAll();\n return;\n }\n // Two clicks from a partial pane, and there is no shortcut: the box is UNchecked\n // there, so the first click stages the rest and only the second clears the lot.\n if (await this.isPartiallyChecked()) {\n await this.toggleSelectAll();\n await this.toggleSelectAll();\n }\n }\n\n /** The filter box, or a failure naming the input that turns it on. */\n private async searchOrThrow(method: string): Promise<TestElement> {\n const box = await this.searchBox();\n if (!box) {\n throw new Error(\n `WrTransferPaneHarness.${method}(): the ${await this.getSide()} pane has no filter box — ` +\n '`searchable` is off on the transfer.'\n );\n }\n return box;\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, type TestElement } from '@angular/cdk/testing';\n\nimport type { WrTransferHarnessFilters, WrTransferSide } from './interfaces';\nimport { WrTransferItemHarness } from './wr-transfer-item-harness';\nimport { WrTransferPaneHarness } from './wr-transfer-pane-harness';\n\n/**\n * Test harness for `<wr-transfer>` — the root of a small family, since a dual\n * listbox is three things and not one control: {@link WrTransferPaneHarness} for one\n * pane and {@link WrTransferItemHarness} for one row inside it.\n *\n * **Everything is keyed by SIDE, never duplicated per pane.** The two panes are the\n * same block rendered twice, so a `…Source` / `…Target` method pair for each\n * question would double the surface and let the halves drift; instead\n * {@link getPane} takes the side once and the pane answers, and the two whole-\n * control operations that are inherently directional — the move buttons — take the\n * side they move rows INTO. `moveTo('target')` is the right-facing button in an LTR\n * layout, and stays the correct one under `dir=\"rtl\"`, where \"right\" is not.\n *\n * **The staged ticks are not the value.** `[(value)]` is the RIGHT pane's\n * membership; a tick inside either pane is transient staging that the next move\n * spends and clears. Conflating them is the failure this component invites, so the\n * two are separate questions here: {@link WrTransferPaneHarness.getItemLabels} is\n * what a pane HOLDS (the value, on the right) and\n * {@link WrTransferPaneHarness.getCheckedLabels} is what it has STAGED.\n *\n * Both are scoped to what a pane is showing, which is also the component's own rule\n * for a move: a row staged before a search hid it is no longer counted, no longer\n * ticked, and does not travel.\n *\n * @example\n * ```ts\n * const transfer = await loader.getHarness(WrTransferHarness);\n * const source = await transfer.getPane('source');\n *\n * await (await source.getItem({ label: 'Read' })).check();\n * await transfer.moveTo('target');\n *\n * expect(await (await transfer.getPane('target')).getItemLabels()).toEqual(['Read']);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrTransferHarness extends ComponentHarness {\n static hostSelector = 'wr-transfer';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrTransferHarnessFilters = {}): HarnessPredicate<WrTransferHarness> {\n return new HarnessPredicate(WrTransferHarness, options)\n .addOption('sourceTitle', options.sourceTitle, (harness, title) =>\n HarnessPredicate.stringMatches(harness.paneTitle('source'), title)\n )\n .addOption('targetTitle', options.targetTitle, (harness, title) =>\n HarnessPredicate.stringMatches(harness.paneTitle('target'), title)\n )\n .addOption('itemLabel', options.itemLabel, async (harness, label) => {\n for (const shown of await harness.shownLabels()) {\n if (await HarnessPredicate.stringMatches(shown, label)) return true;\n }\n return false;\n })\n .addOption(\n 'searchable',\n options.searchable,\n async (harness, searchable) => (await harness.isSearchable()) === searchable\n )\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n /**\n * One of the two panes — `'source'` is the left one (the rows outside the value),\n * `'target'` the right one (the value).\n *\n * The side is named here and nowhere else; see the class note.\n */\n async getPane(side: WrTransferSide): Promise<WrTransferPaneHarness> {\n return this.locatorFor(WrTransferPaneHarness.with({ side }))();\n }\n\n /**\n * Whether the whole control refuses interaction.\n *\n * From the host modifier, which is the only signal the host itself carries: a\n * `<wr-transfer>` element is not a control and publishes no `aria-disabled` of its\n * own — the state reaches assistive tech through the checkboxes, the buttons and\n * the filter boxes it disables, which is where\n * {@link WrTransferItemHarness.isDisabled} and {@link canMoveTo} read it.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.host()).hasClass('wr-transfer--disabled');\n }\n\n /** Whether the panes have filter boxes — `[searchable]` gives both one or neither. */\n async isSearchable(): Promise<boolean> {\n return (await this.host()).hasClass('wr-transfer--searchable');\n }\n\n /**\n * Whether the button that moves rows INTO `side` is offering itself.\n *\n * It is enabled only while the OTHER pane has something staged and showing, so\n * this is also the readable way to assert that staging landed — and that a search\n * which hid a staged row took the move away again.\n *\n * Read from the native `disabled` attribute: these are `button[wr-btn]`, the\n * native shape, where that attribute is the state. (`wr-btn` adds `aria-disabled`\n * only for its custom-element shape, on which `disabled` is inert.)\n */\n async canMoveTo(side: WrTransferSide): Promise<boolean> {\n return (await (await this.moveButton(side)).getAttribute('disabled')) === null;\n }\n\n /**\n * The accessible name of the button that moves rows INTO `side` —\n * `[toTargetLabel]` / `[toSourceLabel]`, or the i18n fallback.\n *\n * Worth pinning: the button's only content is an `aria-hidden` chevron, so this\n * `aria-label` is the entire announcement. Lose it and the pair becomes two\n * unnamed buttons.\n */\n async getMoveLabel(side: WrTransferSide): Promise<string | null> {\n return (await this.moveButton(side)).getAttribute('aria-label');\n }\n\n /**\n * Press the button that moves the staged rows INTO `side`, committing them to the\n * value.\n *\n * Only the rows the other pane is SHOWING as staged travel, and the staging is\n * cleared afterwards — the component's rule, not this harness's.\n *\n * Refuses a disabled button rather than pressing it: a native disabled `<button>`\n * swallows the click before Angular's listener sees it, so the call would resolve\n * having moved nothing at all.\n */\n async moveTo(side: WrTransferSide): Promise<void> {\n if (!(await this.canMoveTo(side))) {\n const from: WrTransferSide = side === 'target' ? 'source' : 'target';\n throw new Error(\n `WrTransferHarness.moveTo('${side}'): the button is disabled, so nothing would move. The ${from} pane ` +\n 'has nothing staged and showing — a row staged before a search hid it no longer counts — or the whole ' +\n 'transfer is disabled.'\n );\n }\n await (await this.moveButton(side)).click();\n }\n\n /**\n * Stage everything the other pane can stage, then move it INTO `side`.\n *\n * \"Everything\" is the pane's own scope: the rows it is SHOWING, disabled ones\n * excluded. A search narrows it, and with a filter typed this moves what is\n * visible rather than the whole pane.\n */\n async moveAllTo(side: WrTransferSide): Promise<void> {\n const from = await this.getPane(side === 'target' ? 'source' : 'target');\n await from.checkAll();\n await this.moveTo(side);\n }\n\n /** The heading of one pane — the `sourceTitle` / `targetTitle` filters run through this. */\n private async paneTitle(side: WrTransferSide): Promise<string> {\n return (await this.getPane(side)).getTitle();\n }\n\n /** Every label rendered in either pane, for the `itemLabel` filter. */\n private async shownLabels(): Promise<string[]> {\n const items = await this.locatorForAll(WrTransferItemHarness)();\n return Promise.all(items.map(item => item.getLabel()));\n }\n\n /**\n * The move button for a direction, addressed by its `--to-source` / `--to-target`\n * modifier.\n *\n * Not by DOM order, and that is the point: two identically classed buttons whose\n * only difference was their position would let a template reshuffle silently\n * reverse every `moveTo()` in every consumer's suite, with both directions still\n * green. Not by the `aria-label` either — that string is localizable.\n */\n private async moveButton(side: WrTransferSide): Promise<TestElement> {\n return this.locatorFor(`.wr-transfer__move--to-${side}`)();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}