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,734 @@
1
+ import { ComponentHarness, HarnessPredicate, ContentContainerComponentHarness, 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 node of a `<wr-tree>` — a `role="treeitem"` row.
11
+ *
12
+ * Everything about a tree's shape that a screen reader gets lives on these rows:
13
+ * the list itself is FLAT, with no `role="group"` and no nesting, so `aria-level`,
14
+ * `aria-posinset` and `aria-setsize` are the only place the hierarchy exists. The
15
+ * indent is decoration.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const src = await tree.getNode({ label: 'src' });
20
+ *
21
+ * await src.expand();
22
+ * expect(await src.getLevel()).toBe(1);
23
+ * ```
24
+ *
25
+ * @see https://ngwr.dev/guides/testing
26
+ */
27
+ class WrTreeNodeHarness extends ComponentHarness {
28
+ /**
29
+ * The row, and nothing else the list can hold.
30
+ *
31
+ * A windowed tree pads its list with `<li class="wr-tree__spacer" role="presentation">`
32
+ * at each end, so `li` would hand back up to two "nodes" with no label and no
33
+ * state. `[role="treeitem"]` selects exactly the same set as this class.
34
+ */
35
+ static hostSelector = '.wr-tree__row';
36
+ /** Build a predicate that narrows the query. */
37
+ static with(options = {}) {
38
+ return new HarnessPredicate(WrTreeNodeHarness, options)
39
+ .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))
40
+ .addOption('selected', options.selected, async (harness, selected) => (await harness.isSelected()) === selected)
41
+ .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)
42
+ .addOption('expanded', options.expanded,
43
+ // A leaf is not a closed branch: it announces no `aria-expanded` at all, so
44
+ // it matches neither value rather than answering `false` and turning
45
+ // `{ expanded: false }` into "every row that is not open".
46
+ async (harness, expanded) => (await harness.isExpandable()) && (await harness.isExpanded()) === expanded)
47
+ .addOption('level', options.level, async (harness, level) => (await harness.getLevel()) === level);
48
+ }
49
+ /**
50
+ * The node's label.
51
+ *
52
+ * Read from `.wr-tree__label` rather than from the row's text, so the answer stays
53
+ * the label alone however the row is decorated around it.
54
+ */
55
+ async getLabel() {
56
+ return (await this.locatorFor('.wr-tree__label')()).text();
57
+ }
58
+ /** The node's 1-based depth, as the row announces it (`aria-level`). */
59
+ async getLevel() {
60
+ return this.announcedNumber('aria-level');
61
+ }
62
+ /**
63
+ * The node's 1-based position within its SIBLING GROUP (`aria-posinset`) — not its
64
+ * position in the flat list of visible rows.
65
+ *
66
+ * `src`'s first child is `posinset` 1 even though it is the second row on screen.
67
+ * That is what ARIA asks for, and the whole reason the attribute is needed here:
68
+ * the rendered list cannot express the nesting on its own.
69
+ */
70
+ async getPosInSet() {
71
+ return this.announcedNumber('aria-posinset');
72
+ }
73
+ /** How many nodes are in this node's sibling group, itself included (`aria-setsize`). */
74
+ async getSetSize() {
75
+ return this.announcedNumber('aria-setsize');
76
+ }
77
+ /**
78
+ * The node's index in the full list of VISIBLE nodes — every rendered row plus the
79
+ * ones a window left out, in the order the tree would show them.
80
+ *
81
+ * It is the index the tree's own keyboard code addresses rows by, and while the
82
+ * tree is windowed it is the only way to place a row: DOM order then says nothing,
83
+ * because the rows in the DOM are a slice.
84
+ */
85
+ async getIndex() {
86
+ return this.announcedNumber('data-tree-index');
87
+ }
88
+ /**
89
+ * The row's DOM id, or `null`.
90
+ *
91
+ * Only a windowed tree gives its rows ids, because that is the shape where the
92
+ * list keeps focus and names the cursor row with `aria-activedescendant` — the id
93
+ * exists to be pointed at.
94
+ */
95
+ async getId() {
96
+ return (await this.host()).getAttribute('id');
97
+ }
98
+ /**
99
+ * Whether the node is a branch — it has children, whether or not they are showing.
100
+ *
101
+ * From `aria-expanded`: only a branch carries it, and a branch that does not is
102
+ * announced as a leaf, so the user never learns there is anything underneath. The
103
+ * toggle element cannot answer this — a leaf renders a `<span>` with the same
104
+ * `.wr-tree__toggle` class purely to hold the indent.
105
+ */
106
+ async isExpandable() {
107
+ return (await (await this.host()).getAttribute('aria-expanded')) !== null;
108
+ }
109
+ /** Whether the branch is open. A leaf is never expanded. */
110
+ async isExpanded() {
111
+ return (await (await this.host()).getAttribute('aria-expanded')) === 'true';
112
+ }
113
+ /** Open the branch. Already-open branches are left alone; a leaf throws. */
114
+ async expand() {
115
+ if (await this.isExpanded())
116
+ return;
117
+ await this.toggleExpand();
118
+ if (!(await this.isExpanded())) {
119
+ throw new Error(`WrTreeNodeHarness.expand(): "${await this.getLabel()}" did not open. A disabled node ignores its ` +
120
+ 'own toggle, and so does every node of a disabled tree.');
121
+ }
122
+ }
123
+ /** Close the branch. Already-closed branches are left alone; a leaf throws. */
124
+ async collapse() {
125
+ if (!(await this.isExpanded())) {
126
+ // A closed branch is fine to ask twice; a leaf is a mistake worth naming.
127
+ await this.toggleElement();
128
+ return;
129
+ }
130
+ await this.toggleExpand();
131
+ if (await this.isExpanded()) {
132
+ throw new Error(`WrTreeNodeHarness.collapse(): "${await this.getLabel()}" did not close. A disabled node ignores ` +
133
+ 'its own toggle, and so does every node of a disabled tree.');
134
+ }
135
+ }
136
+ /**
137
+ * Click the branch's expand toggle.
138
+ *
139
+ * Expanding is the TOGGLE's job and not the row's: a click anywhere else in the row
140
+ * selects instead, which is the one thing a spec driving this by hand tends to get
141
+ * wrong.
142
+ */
143
+ async toggleExpand() {
144
+ await (await this.toggleElement()).click();
145
+ }
146
+ /**
147
+ * Whether the node is selected.
148
+ *
149
+ * From `aria-selected` rather than the `--selected` modifier: both are public, but
150
+ * the attribute is what a screen reader acts on, and a row that looks selected
151
+ * without saying so is the bug worth catching.
152
+ */
153
+ async isSelected() {
154
+ return (await (await this.host()).getAttribute('aria-selected')) === 'true';
155
+ }
156
+ /**
157
+ * Whether the tree offers selection at all.
158
+ *
159
+ * A `selectionMode="none"` tree announces NO `aria-selected` on its rows, which is
160
+ * how an unselectable node differs from one that is merely unselected — the two
161
+ * look identical otherwise.
162
+ */
163
+ async isSelectable() {
164
+ return (await (await this.host()).getAttribute('aria-selected')) !== null;
165
+ }
166
+ /**
167
+ * Whether the node refuses interaction (`aria-disabled`).
168
+ *
169
+ * True for EVERY node while the whole tree is disabled, not just for the ones the
170
+ * data marks — the row announces the effective state, which is the one a user runs
171
+ * into.
172
+ */
173
+ async isDisabled() {
174
+ return (await (await this.host()).getAttribute('aria-disabled')) === 'true';
175
+ }
176
+ /**
177
+ * Whether the node is where the keyboard cursor sits.
178
+ *
179
+ * The two patterns publish the cursor differently, and this covers both: a tree
180
+ * that renders every row hands the single tab stop to the cursor row (roving
181
+ * tabindex), while a windowed one keeps focus on the list and marks the row with
182
+ * the `--active` modifier plus the list's `aria-activedescendant`.
183
+ * `WrTreeHarness.getActiveNodeLabel()` reads that reference itself.
184
+ */
185
+ async isActive() {
186
+ const host = await this.host();
187
+ return (await host.getAttribute('tabindex')) === '0' || host.hasClass('wr-tree__row--active');
188
+ }
189
+ /**
190
+ * Whether the row holds real DOM focus.
191
+ *
192
+ * Deliberately separate from {@link isActive}: in a windowed tree the two DIVERGE
193
+ * by design — focus stays on the `role="tree"` list and only the announced cursor
194
+ * moves — so a spec asserting that a key press moved focus needs to know which of
195
+ * the two it is asking about.
196
+ */
197
+ async isFocused() {
198
+ return (await this.host()).isFocused();
199
+ }
200
+ /**
201
+ * Click the node — which SELECTS it. A disabled node, and any node of a
202
+ * `selectionMode="none"` tree, ignores the click.
203
+ *
204
+ * In multi mode a plain click REPLACES the selection rather than adding to it (the
205
+ * component's deliberate choice: one selected node clicked again clears it, and any
206
+ * other click starts over from that node). {@link ctrlClick} is how a selection is
207
+ * accumulated.
208
+ */
209
+ async click() {
210
+ return (await this.host()).click();
211
+ }
212
+ /**
213
+ * Ctrl-click the node — ADDS it to the selection, or removes it, in multi mode.
214
+ *
215
+ * The component takes Cmd as well as Ctrl; the harness sends Ctrl because a unit
216
+ * test has no platform. In single mode it behaves exactly like {@link click}.
217
+ */
218
+ async ctrlClick() {
219
+ return (await this.host()).click({ control: true });
220
+ }
221
+ /** The branch's toggle button, or a failure that says this row is a leaf. */
222
+ async toggleElement() {
223
+ // `button` is load-bearing: a leaf renders a `<span>` with the same
224
+ // `.wr-tree__toggle` class to hold the indent, and taking that for a control
225
+ // would report every leaf as a branch that refused to open.
226
+ const toggle = await this.locatorForOptional('button.wr-tree__toggle')();
227
+ if (!toggle) {
228
+ throw new Error(`WrTreeNodeHarness: "${await this.getLabel()}" is a leaf — there is no branch to open or close.`);
229
+ }
230
+ return toggle;
231
+ }
232
+ /** A numeric attribute every row carries, or a failure that says the row is broken. */
233
+ async announcedNumber(attribute) {
234
+ const value = await (await this.host()).getAttribute(attribute);
235
+ if (value === null) {
236
+ throw new Error(`WrTreeNodeHarness: this row announces no \`${attribute}\`. Every row of a \`<wr-tree>\` carries ` +
237
+ 'one, so a missing value is a rendering fault rather than a state worth reporting as null.');
238
+ }
239
+ return Number.parseInt(value, 10);
240
+ }
241
+ }
242
+
243
+ /**
244
+ * @license
245
+ *
246
+ * Use of this source code is governed by an MIT-style license that can be
247
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
248
+ */
249
+ /** How many levels {@link WrTreeHarness.expandAll} is willing to walk. */
250
+ const MAX_EXPAND_PASSES = 20;
251
+ /**
252
+ * Test harness for `<wr-tree>`, with {@link WrTreeNodeHarness} for one row.
253
+ *
254
+ * The component has two render shapes and this harness covers both:
255
+ * - `openOn="inline"` (default) — the rows live in the host, and the tree is always
256
+ * showing them.
257
+ * - `openOn="overlay"` — a `role="combobox"` trigger opens a panel that is a template
258
+ * portal in the shared overlay container, a sibling of the whole app. Nothing in it
259
+ * is a descendant of the host, so every row is read through the document root,
260
+ * SCOPED by the `aria-controls` id the trigger publishes — which is what keeps two
261
+ * trees on one page from answering with each other's nodes.
262
+ *
263
+ * A tree is data-driven and projects nothing, so the scoped loader exists to point the
264
+ * node queries at the right shape rather than to reach a consumer's own components: the
265
+ * inherited `getHarness(…)` resolves wherever THIS tree's rows are, and there is nothing
266
+ * else in there.
267
+ *
268
+ * Two things the harness cannot do, both jsdom rather than the component:
269
+ * - it never clicks a row by coordinate, and it drives the cursor with the KEYBOARD,
270
+ * which is the accessible path anyway. There is no layout in a unit test, so a
271
+ * hit test would answer with nothing.
272
+ * - it offers no SCROLL for a windowed tree. jsdom does remember a `scrollTop` write,
273
+ * but it fires no `scroll` event for it, so the tree — which learns its offset from
274
+ * that event — would not move until the caller also dispatched one and waited a
275
+ * frame: a scroll gesture that only works because the test faked the notification.
276
+ * The keyboard moves the window honestly instead — see {@link focusLast}. (jsdom has
277
+ * no `Element.scrollTo` at all, which the tree calls while windowed, so a spec for
278
+ * that shape has to stub it.)
279
+ *
280
+ * @example
281
+ * ```ts
282
+ * const tree = await loader.getHarness(WrTreeHarness);
283
+ *
284
+ * await (await tree.getNode({ label: 'src' })).expand();
285
+ * await tree.selectNode({ label: 'main.ts' });
286
+ *
287
+ * expect(await tree.getSelectedLabels()).toEqual(['main.ts']);
288
+ * ```
289
+ *
290
+ * @see https://ngwr.dev/guides/testing
291
+ */
292
+ class WrTreeHarness extends ContentContainerComponentHarness {
293
+ static hostSelector = 'wr-tree';
294
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
295
+ static with(options = {}) {
296
+ return new HarnessPredicate(WrTreeHarness, options)
297
+ .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.triggerTextIfAny(), text))
298
+ .addOption('nodeLabel', options.nodeLabel, async (harness, label) => {
299
+ for (const shown of await harness.nodeLabelsIfShowing()) {
300
+ if (await HarnessPredicate.stringMatches(shown, label))
301
+ return true;
302
+ }
303
+ return false;
304
+ })
305
+ .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)
306
+ .addOption('open', options.open, async (harness, open) => (await harness.isOpen()) === open);
307
+ }
308
+ /** Whether this tree is the combobox shape (`openOn="overlay"`) rather than inline. */
309
+ async isOverlay() {
310
+ return (await this.host()).hasClass('wr-tree--combobox');
311
+ }
312
+ /**
313
+ * Whether the rows are showing.
314
+ *
315
+ * From the trigger's `aria-expanded` rather than the `--open` modifier: both are
316
+ * public, but that attribute is the promise the combobox makes to a screen reader.
317
+ * An inline tree is always open — its rows are part of the host and there is
318
+ * nothing to open or close.
319
+ */
320
+ async isOpen() {
321
+ if (!(await this.isOverlay()))
322
+ return true;
323
+ return (await (await this.trigger()).getAttribute('aria-expanded')) === 'true';
324
+ }
325
+ /**
326
+ * Open the panel. An already-open tree — and every inline one — is left alone.
327
+ *
328
+ * Note for a spec with two overlay trees: this clicks, and a click is an outside
329
+ * pointer event for every other open overlay, so it closes any panel already up.
330
+ * There is no second gesture to swap in: the trigger is opened by its `click`
331
+ * handler, and while a real keyboard user reaches that through a `<button>`'s native
332
+ * activation, a SYNTHETIC Enter / Space never produces a click — so a harness cannot
333
+ * open a panel any other way.
334
+ */
335
+ async open() {
336
+ if (await this.isOpen())
337
+ return;
338
+ await (await this.trigger()).click();
339
+ if (await this.isOpen())
340
+ return;
341
+ throw new Error('WrTreeHarness.open(): the panel did not open. A disabled tree refuses the trigger and closes any ' +
342
+ 'panel that was up, so check `disabled` first.');
343
+ }
344
+ /** Close the panel with Escape. An already-closed tree is left alone. */
345
+ async close() {
346
+ // Not a no-op for an inline tree: asking to close one means the spec believes it
347
+ // has a panel, and it does not.
348
+ const trigger = await this.trigger();
349
+ if (!(await this.isOpen()))
350
+ return;
351
+ // Escape reaches the tree through the CDK's keyboard dispatcher, which hands it to
352
+ // the top-most overlay — so it does not matter that focus may be on a row inside.
353
+ await trigger.sendKeys(TestKey.ESCAPE);
354
+ }
355
+ /**
356
+ * Whether the tree refuses interaction.
357
+ *
358
+ * The host modifier is the only answer both shapes carry: an inline tree has no
359
+ * control of its own to mark `disabled`, and a closed overlay tree has no rows to
360
+ * read `aria-disabled` from. The rows do announce it — see
361
+ * {@link WrTreeNodeHarness.isDisabled}.
362
+ */
363
+ async isDisabled() {
364
+ return (await this.host()).hasClass('wr-tree--disabled');
365
+ }
366
+ /**
367
+ * Whether the tree takes more than one selected node.
368
+ *
369
+ * From the list's `aria-multiselectable`, which is what a screen reader acts on. The
370
+ * list does not exist while an overlay panel is closed, so the host modifier answers
371
+ * then — it is only painted in the combobox shape, which is exactly the shape that
372
+ * can be asked while closed.
373
+ */
374
+ async isMultiple() {
375
+ if (await this.isOpen()) {
376
+ return (await (await this.list()).getAttribute('aria-multiselectable')) === 'true';
377
+ }
378
+ return (await this.host()).hasClass('wr-tree--multi');
379
+ }
380
+ /**
381
+ * How much the tree lets you select.
382
+ *
383
+ * `'none'` is not "nothing selected": it is a tree whose rows announce no
384
+ * `aria-selected` at all, and telling that from `'single'` needs a row — so an empty
385
+ * tree throws rather than guessing.
386
+ */
387
+ async getSelectionMode() {
388
+ if (await this.isMultiple())
389
+ return 'multi';
390
+ const [first] = await this.getNodes();
391
+ if (!first) {
392
+ throw new Error('WrTreeHarness.getSelectionMode(): this tree renders no nodes, and single vs none is only visible ' +
393
+ 'on a row — `selectionMode="none"` is the absence of `aria-selected`, so there is nothing to read.');
394
+ }
395
+ return (await first.isSelectable()) ? 'single' : 'none';
396
+ }
397
+ /**
398
+ * Whether the list is WINDOWED right now.
399
+ *
400
+ * Read from the list's modifier rather than from the input, and that is the point:
401
+ * `virtualScroll` only takes effect when there is something to window, so an empty
402
+ * tree renders the plain shape however the input is set.
403
+ */
404
+ async isVirtual() {
405
+ return (await this.list()).hasClass('wr-tree__list--virtual');
406
+ }
407
+ /**
408
+ * The role the list announces — `tree`.
409
+ *
410
+ * Worth asking: rendered without it, the rows are a bag of names, identical on
411
+ * screen and structureless to anyone not looking at it.
412
+ */
413
+ async getRole() {
414
+ return (await this.list()).getAttribute('role');
415
+ }
416
+ /**
417
+ * What the trigger shows as the selection: the chip labels joined by `', '` in multi
418
+ * mode, the label in single mode, and `''` when nothing is selected (the placeholder
419
+ * is showing). The `+N more` chip a `maxTagCount` produces is NOT part of it — it is
420
+ * a count rather than a selection, and {@link getOverflowText} reads it. Inline trees
421
+ * have no trigger and throw.
422
+ */
423
+ async getValueText() {
424
+ await this.trigger();
425
+ const chips = await this.getChipLabels();
426
+ if (chips.length > 0)
427
+ return chips.join(', ');
428
+ const value = await this.locatorForOptional('.wr-tree__value')();
429
+ return value ? value.text() : '';
430
+ }
431
+ /** The placeholder, or `null` when a selection is hiding it. */
432
+ async getPlaceholder() {
433
+ await this.trigger();
434
+ const placeholder = await this.locatorForOptional('.wr-tree__placeholder')();
435
+ return placeholder ? placeholder.text() : null;
436
+ }
437
+ /**
438
+ * The chip labels on the trigger, in order (multi mode).
439
+ *
440
+ * The `+N more` overflow chip is not one of them — it is a count, not a selection.
441
+ * {@link getOverflowText} reads it.
442
+ */
443
+ async getChipLabels() {
444
+ await this.trigger();
445
+ const labels = await this.locatorForAll('.wr-tree__chip-label')();
446
+ return Promise.all(labels.map(label => label.text()));
447
+ }
448
+ /**
449
+ * The `+N more` chip's text, or `null` when every selected node has a chip of its
450
+ * own. Only a `maxTagCount` below the number selected produces one.
451
+ */
452
+ async getOverflowText() {
453
+ await this.trigger();
454
+ const more = await this.locatorForOptional('.wr-tree__chip--more')();
455
+ return more ? more.text() : null;
456
+ }
457
+ /** Remove one chip by its label. */
458
+ async removeChip(label) {
459
+ const labels = await this.getChipLabels();
460
+ const index = labels.indexOf(label);
461
+ if (index < 0) {
462
+ throw new Error(`WrTreeHarness.removeChip(): no chip labelled "${label}". The trigger shows [${labels.join(', ')}] — ` +
463
+ 'a selection past `maxTagCount` has no chip to remove.');
464
+ }
465
+ // Label and remove control are emitted once per chip by the same loop, so the two
466
+ // lists line up by index.
467
+ const removes = await this.locatorForAll('.wr-tree__chip-remove')();
468
+ await removes[index].click();
469
+ }
470
+ /** Click the clear (×) control on the trigger. */
471
+ async clear() {
472
+ await this.trigger();
473
+ const clear = await this.locatorForOptional('.wr-tree__clear')();
474
+ if (!clear) {
475
+ throw new Error('WrTreeHarness.clear(): this trigger has no clear control — `clearable` is off, nothing is ' +
476
+ 'selected, or the tree is disabled.');
477
+ }
478
+ await clear.click();
479
+ }
480
+ /**
481
+ * The nodes currently rendered, in the order they are shown.
482
+ *
483
+ * A collapsed branch's children are not rendered at all, so this is the VISIBLE
484
+ * tree — expand first to reach deeper.
485
+ *
486
+ * While {@link isVirtual} is true it is narrower still: the list holds only the
487
+ * window around the scroll offset — padded by a spacer at whichever end has rows
488
+ * outside it, so a window resting at the top has one and a window in the middle has
489
+ * two — and this returns the WINDOW, not the dataset. Nothing in the DOM carries a
490
+ * total —
491
+ * `aria-setsize` counts a SIBLING GROUP, not the flat list — so the harness cannot
492
+ * offer one; {@link WrTreeNodeHarness.getIndex} places each row in the full visible
493
+ * list, and the `[nodes]` data is where the total actually lives.
494
+ *
495
+ * Throws while an overlay panel is closed: the rows do not exist anywhere until it
496
+ * opens, and an empty array reads like a tree that rendered nothing.
497
+ */
498
+ async getNodes(filters = {}) {
499
+ return this.getAllHarnesses(WrTreeNodeHarness.with(filters));
500
+ }
501
+ /** The labels of the nodes currently rendered, in order. */
502
+ async getNodeLabels() {
503
+ const nodes = await this.getNodes();
504
+ return Promise.all(nodes.map(node => node.getLabel()));
505
+ }
506
+ /** The first node matching the filters, or a failure that says what is showing. */
507
+ async getNode(filters) {
508
+ const [node] = await this.getNodes(filters);
509
+ if (!node) {
510
+ const showing = await this.getNodeLabels();
511
+ throw new Error(`WrTreeHarness.getNode(): no node matched ${JSON.stringify(filters)}. The tree is showing ` +
512
+ `[${showing.join(', ')}] — a node inside a collapsed branch is not rendered at all, and a ` +
513
+ 'windowed tree only renders its window.');
514
+ }
515
+ return node;
516
+ }
517
+ /**
518
+ * Open the panel if needed, then select the first node matching the filters.
519
+ *
520
+ * `additive` ctrl-clicks instead, which is how a multi-mode selection is built up: a
521
+ * plain click there REPLACES the selection, by the component's own choice.
522
+ *
523
+ * Throws rather than clicking into the void on a disabled node or a
524
+ * `selectionMode="none"` tree — both ignore the click, and the silence turns into a
525
+ * confusing failure at the next assertion. Reach for `getNode().click()` when
526
+ * proving exactly that.
527
+ */
528
+ async selectNode(filters, options = {}) {
529
+ await this.open();
530
+ const node = await this.getNode(filters);
531
+ const label = await node.getLabel();
532
+ if (!(await node.isSelectable())) {
533
+ throw new Error(`WrTreeHarness.selectNode(): "${label}" announces no selected state, so this tree is in ` +
534
+ 'selectionMode="none" — clicking it cannot select anything.');
535
+ }
536
+ if (await node.isDisabled()) {
537
+ throw new Error(`WrTreeHarness.selectNode(): "${label}" is disabled and the tree ignores the click. A disabled ` +
538
+ 'TREE disables every node — check isDisabled() on the tree too.');
539
+ }
540
+ await (options.additive === true ? node.ctrlClick() : node.click());
541
+ }
542
+ /**
543
+ * The labels of the selected nodes, in row order.
544
+ *
545
+ * Only among the rows that are RENDERED: a selected node inside a collapsed branch,
546
+ * or outside a window, is not here. The `[(selected)]` model is the whole set.
547
+ */
548
+ async getSelectedLabels() {
549
+ const nodes = await this.getNodes({ selected: true });
550
+ return Promise.all(nodes.map(node => node.getLabel()));
551
+ }
552
+ /**
553
+ * Open every branch, level by level — each pass reveals the next one down.
554
+ *
555
+ * Refuses on a windowed tree instead of half-doing it: only the window is rendered,
556
+ * so the branches outside it cannot be reached from the DOM at all. Write the
557
+ * `[(expanded)]` model there.
558
+ */
559
+ async expandAll() {
560
+ if (await this.isVirtual()) {
561
+ throw new Error('WrTreeHarness.expandAll(): a windowed tree renders only its window, so this cannot reach the ' +
562
+ 'branches outside it. Set the `[(expanded)]` model instead.');
563
+ }
564
+ for (let pass = 0; pass < MAX_EXPAND_PASSES; pass++) {
565
+ const collapsed = await this.getNodes({ expanded: false });
566
+ if (collapsed.length === 0)
567
+ return;
568
+ for (const node of collapsed)
569
+ await node.expand();
570
+ }
571
+ throw new Error(`WrTreeHarness.expandAll(): still finding closed branches after ${MAX_EXPAND_PASSES} levels — is the ` +
572
+ 'node data recursive?');
573
+ }
574
+ /**
575
+ * The label of the node the keyboard cursor is on, or `null`.
576
+ *
577
+ * Read the way the shape publishes it: a windowed tree keeps focus on the list and
578
+ * names the row with `aria-activedescendant` (which goes `null` while the cursor has
579
+ * been scrolled out of the window, so the reference never dangles at a row that was
580
+ * removed), while a plain one hands the single tab stop to the cursor row.
581
+ */
582
+ async getActiveNodeLabel() {
583
+ const nodes = await this.getNodes();
584
+ if (await this.isVirtual()) {
585
+ const active = await (await this.list()).getAttribute('aria-activedescendant');
586
+ if (!active)
587
+ return null;
588
+ for (const node of nodes) {
589
+ if ((await node.getId()) === active)
590
+ return node.getLabel();
591
+ }
592
+ return null;
593
+ }
594
+ for (const node of nodes) {
595
+ if (await node.isActive())
596
+ return node.getLabel();
597
+ }
598
+ return null;
599
+ }
600
+ /** Move the cursor down one row — ArrowDown. Stops at the last row. */
601
+ async focusNext() {
602
+ await this.press(TestKey.DOWN_ARROW);
603
+ }
604
+ /** Move the cursor up one row — ArrowUp. Stops at the first row. */
605
+ async focusPrevious() {
606
+ await this.press(TestKey.UP_ARROW);
607
+ }
608
+ /** Move the cursor to the first row — Home. */
609
+ async focusFirst() {
610
+ await this.press(TestKey.HOME);
611
+ }
612
+ /**
613
+ * Move the cursor to the last row — End.
614
+ *
615
+ * On a windowed tree this also moves the WINDOW: the tree writes its scroll offset
616
+ * synchronously so the row it is about to point at exists in the same change
617
+ * detection pass. It is the honest way to reach the far end of a window in a unit
618
+ * test — jsdom keeps a `scrollTop` write but never fires the `scroll` event the tree
619
+ * listens for, so a scroll gesture would move the window only for a test that also
620
+ * dispatched the notification itself.
621
+ */
622
+ async focusLast() {
623
+ await this.press(TestKey.END);
624
+ }
625
+ /**
626
+ * ArrowRight on the cursor row — the APG's one key with two jobs: it OPENS a closed
627
+ * branch, and on an already-open one it steps into the first child. A leaf ignores
628
+ * it.
629
+ *
630
+ * These two send the PHYSICAL key, because that is what a keyboard has. Under
631
+ * `dir="rtl"` the tree follows the indent and swaps the pair, so a spec exercising
632
+ * an RTL tree opens with {@link collapseActive} and closes with this one. The
633
+ * names describe the LTR job, which is the one worth naming.
634
+ */
635
+ async expandActive() {
636
+ await this.press(TestKey.RIGHT_ARROW);
637
+ }
638
+ /**
639
+ * ArrowLeft on the cursor row — CLOSES an open branch, and on anything else steps
640
+ * out to the parent row. A root-level leaf ignores it.
641
+ *
642
+ * Physical, and mirrored by the component under `dir="rtl"` — see
643
+ * {@link expandActive}.
644
+ */
645
+ async collapseActive() {
646
+ await this.press(TestKey.LEFT_ARROW);
647
+ }
648
+ /**
649
+ * Select the cursor row from the keyboard — Enter.
650
+ *
651
+ * `additive` holds Ctrl, the keyboard twin of {@link WrTreeNodeHarness.ctrlClick}:
652
+ * in multi mode a plain Enter replaces the selection, Ctrl-Enter adds to it. A
653
+ * disabled row is skipped by the component, silently — assert the model.
654
+ */
655
+ async selectActive(options = {}) {
656
+ const list = await this.list();
657
+ if (options.additive === true) {
658
+ await list.sendKeys({ control: true }, TestKey.ENTER);
659
+ return;
660
+ }
661
+ await list.sendKeys(TestKey.ENTER);
662
+ }
663
+ /**
664
+ * The loader every node query runs through — the host inline, THIS tree's overlay
665
+ * panel otherwise.
666
+ *
667
+ * Scoped by the published panel id rather than by `.wr-tree-panel`: the overlay
668
+ * container is shared, so a bare class query would answer with whichever tree
669
+ * happened to open first.
670
+ */
671
+ async getRootHarnessLoader() {
672
+ if (!(await this.isOverlay()))
673
+ return super.getRootHarnessLoader();
674
+ return this.documentRootLocatorFactory().harnessLoaderFor(`#${await this.panelId()}`);
675
+ }
676
+ /**
677
+ * Send a key to the `role="tree"` list.
678
+ *
679
+ * The list owns the keydown handler in both patterns — the roving-tabindex one
680
+ * focuses a row, whose event bubbles to exactly here — so this is the honest target
681
+ * either way, and the one that works when jsdom has left real focus on `<body>`.
682
+ */
683
+ async press(key) {
684
+ await (await this.list()).sendKeys(key);
685
+ }
686
+ /**
687
+ * The `<ul role="tree">` of THIS tree — in the host inline, in this tree's own
688
+ * overlay panel otherwise.
689
+ */
690
+ async list() {
691
+ if (!(await this.isOverlay()))
692
+ return this.locatorFor('.wr-tree__list')();
693
+ return this.documentRootLocatorFactory().locatorFor(`#${await this.panelId()} .wr-tree__list`)();
694
+ }
695
+ /** The combobox trigger, or a failure that says this tree renders inline. */
696
+ async trigger() {
697
+ const trigger = await this.locatorForOptional('.wr-tree__trigger')();
698
+ if (!trigger) {
699
+ throw new Error('WrTreeHarness: this tree renders inline, so it has no trigger, no chips and no panel — its rows ' +
700
+ 'are part of the host. `openOn="overlay"` is the combobox shape.');
701
+ }
702
+ return trigger;
703
+ }
704
+ /** The id the trigger publishes as `aria-controls`, which its panel carries. */
705
+ async panelId() {
706
+ const id = await (await this.trigger()).getAttribute('aria-controls');
707
+ if (!id) {
708
+ throw new Error('WrTreeHarness: the trigger publishes no `aria-controls` id, so its panel cannot be told apart ' +
709
+ "from another tree's.");
710
+ }
711
+ if (!(await this.isOpen())) {
712
+ throw new Error('WrTreeHarness: the panel is closed — call open() first. A closed tree renders no rows.');
713
+ }
714
+ return id;
715
+ }
716
+ /** The trigger's text for the `text` filter, or `null` for an inline tree (which never matches). */
717
+ async triggerTextIfAny() {
718
+ const trigger = await this.locatorForOptional('.wr-tree__trigger')();
719
+ return trigger ? this.getValueText() : null;
720
+ }
721
+ /** The rendered labels for the `nodeLabel` filter — a closed tree matches nothing rather than failing. */
722
+ async nodeLabelsIfShowing() {
723
+ if (!(await this.isOpen()))
724
+ return [];
725
+ return this.getNodeLabels();
726
+ }
727
+ }
728
+
729
+ /**
730
+ * Generated bundle index. Do not edit.
731
+ */
732
+
733
+ export { WrTreeHarness, WrTreeNodeHarness };
734
+ //# sourceMappingURL=ngwr-tree-testing.mjs.map