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,631 @@
1
+ import { ComponentHarness, HarnessPredicate, TestKey, ContentContainerComponentHarness } 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
+ /** How long the waiters poll before giving up, in ms. Generous next to the 500ms hold. */
10
+ const DEFAULT_TIMEOUT = 1000;
11
+ /** How often they re-check, in ms. */
12
+ const POLL_STEP = 10;
13
+ /**
14
+ * The real `setTimeout`, captured at module load — before a spec can install
15
+ * fake timers.
16
+ *
17
+ * Every delay in this component family is wall-clock: a plain `setTimeout` inside
18
+ * the directive for the 500ms long-press hold, the 120ms submenu hover and the
19
+ * 220ms exit animation the pane is held alive through, and a `performance.now()`
20
+ * comparison for the 200ms window in which outside presses are ignored — no timer
21
+ * behind that one, just elapsed time. Under zoneless change detection `whenStable()` resolves
22
+ * without waiting for a macrotask, so the waiters have to let REAL time pass —
23
+ * reading a faked global instead would mean the sleep never fires at all, and
24
+ * the harness would hang where it should fail with the message it prepared.
25
+ */
26
+ const realSetTimeout = globalThis.setTimeout;
27
+ /** Let real time pass, whatever a spec has done to the global clock. */
28
+ function sleep(ms) {
29
+ return new Promise(resolve => {
30
+ realSetTimeout(resolve, ms);
31
+ });
32
+ }
33
+
34
+ /**
35
+ * @license
36
+ *
37
+ * Use of this source code is governed by an MIT-style license that can be
38
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
39
+ */
40
+ /**
41
+ * Test harness for one `<wr-context-menu-item>` inside a context menu.
42
+ *
43
+ * The selector is the CLASS rather than the element, matching
44
+ * `.wr-dropdown-item`: it is public API, and it is on the host whichever way the
45
+ * item was written. A `<wr-context-menu-divider>` is deliberately not one of
46
+ * these — it announces `role="separator"` rather than `menuitem`, so it is not
47
+ * something a user can land on and not a member of the item list
48
+ * (`WrContextMenuHarness.getDividerCount()` counts those).
49
+ *
50
+ * An item that owns a `[submenu]` is also the way INTO it: the submenu is a
51
+ * second overlay pane, a sibling of the root menu rather than a child of the
52
+ * item, and it is reached through the id the item publishes as `aria-controls`
53
+ * while it is open. `getSubmenuItems()` answers with these same harnesses, so a
54
+ * chain of any depth is walked by repeating the call.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * const [cut, copy, more] = await menu.getItems();
59
+ *
60
+ * expect(await copy.isDisabled()).toBe(true);
61
+ * await more.openSubmenu();
62
+ * await more.clickSubmenuItem({ text: 'Duplicate' });
63
+ * ```
64
+ *
65
+ * @see https://ngwr.dev/guides/testing
66
+ */
67
+ class WrContextMenuItemHarness extends ComponentHarness {
68
+ /** The class the item paints on its host. */
69
+ static hostSelector = '.wr-context-menu-item';
70
+ /** Build a predicate that narrows the query. */
71
+ static with(options = {}) {
72
+ return new HarnessPredicate(WrContextMenuItemHarness, options)
73
+ .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))
74
+ .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)
75
+ .addOption('hasSubmenu', options.hasSubmenu, async (harness, hasSubmenu) => (await harness.hasSubmenu()) === hasSubmenu);
76
+ }
77
+ /**
78
+ * The item's label, trimmed.
79
+ *
80
+ * Read from the label span, not from the host: a registered icon is written in
81
+ * with `innerHTML`, so an icon carrying a `<title>` would otherwise become
82
+ * part of the answer.
83
+ */
84
+ async getText() {
85
+ return (await this.locatorFor('.wr-context-menu-item__label')()).text();
86
+ }
87
+ /** The role the item announces — `menuitem`. */
88
+ async getRole() {
89
+ return (await this.host()).getAttribute('role');
90
+ }
91
+ /**
92
+ * Whether the item refuses activation.
93
+ *
94
+ * `aria-disabled`, not the `--disabled` modifier class: both are there, and
95
+ * this is the one a screen reader is told.
96
+ */
97
+ async isDisabled() {
98
+ return (await (await this.host()).getAttribute('aria-disabled')) === 'true';
99
+ }
100
+ /**
101
+ * Whether the item owns a nested submenu.
102
+ *
103
+ * Read from `aria-haspopup`, not from the `--has-submenu` class or the
104
+ * `[submenu]` input: the input is always BOUND (it takes a
105
+ * `<wr-context-menu>` reference), so it never reaches the DOM, and the ARIA
106
+ * property is what announces the item as a drill-down.
107
+ */
108
+ async hasSubmenu() {
109
+ return (await (await this.host()).getAttribute('aria-haspopup')) === 'menu';
110
+ }
111
+ /** Whether this item's submenu is showing, per `aria-expanded`. */
112
+ async isSubmenuOpen() {
113
+ return (await (await this.host()).getAttribute('aria-expanded')) === 'true';
114
+ }
115
+ /** Whether the item shows a leading icon. */
116
+ async hasIcon() {
117
+ return (await this.locatorForOptional('.wr-context-menu-item__icon')()) !== null;
118
+ }
119
+ /** The leading icon's registered name, or `null` when the item has no icon. */
120
+ async getIconName() {
121
+ const icon = await this.locatorForOptional('.wr-context-menu-item__icon')();
122
+ // `<wr-icon>` reflects the name it was asked for as `data-icon`, whether or not
123
+ // that name is registered — so this answers what the item MEANT to draw.
124
+ return icon ? icon.getAttribute('data-icon') : null;
125
+ }
126
+ /**
127
+ * Whether the item holds focus.
128
+ *
129
+ * Worth asking, because nothing in this component ever puts it there: unlike
130
+ * `<wr-dropdown-menu>`, a context menu does not focus its first item on open
131
+ * and has no arrow-key cursor between items. Focus lands on an item when
132
+ * something sends it a key — which every keyboard method here does, since the
133
+ * CDK focuses an element before typing into it.
134
+ */
135
+ async isFocused() {
136
+ return (await this.host()).isFocused();
137
+ }
138
+ /**
139
+ * Click the item. A disabled item throws instead.
140
+ *
141
+ * Refusing is the only honest answer. A browser never delivers the click at all:
142
+ * `pointer-events: none` on the `--disabled` modifier takes the row out of the
143
+ * hit test. jsdom loads no stylesheets, so a click dispatched here DOES land on
144
+ * the host, and while the component's own handler refuses it (a disabled item
145
+ * dismisses nothing), the consumer's `(click)` on that same host is a separate
146
+ * listener and runs — so the spec would record an activation that cannot happen
147
+ * in a browser. Assert `isDisabled()` instead.
148
+ *
149
+ * Activating a LEAF item dismisses the whole chain, root menu included. An item
150
+ * that owns a submenu is not a leaf: clicking it does nothing at all (hover or
151
+ * `openSubmenu()` is how it opens).
152
+ */
153
+ async click() {
154
+ if (await this.isDisabled()) {
155
+ throw new Error(`WrContextMenuItemHarness.click(): "${await this.getText()}" is disabled, so clicking it would ` +
156
+ 'report behaviour a browser cannot produce — the pointer is stopped by CSS, which jsdom does ' +
157
+ 'not load. Assert isDisabled() instead.');
158
+ }
159
+ return (await this.host()).click();
160
+ }
161
+ /**
162
+ * Press Enter on the item — the keyboard equivalent of a click, and the route
163
+ * a spec should prefer, since it needs no hit test.
164
+ *
165
+ * Deliberately does NOT refuse a disabled item the way `click()` does: the
166
+ * component guards the keyboard path itself, so the key can be sent honestly
167
+ * and a spec can assert that nothing happened. On an item that owns a submenu
168
+ * this OPENS the submenu rather than activating the row, which is the APG
169
+ * behaviour — activating it would close the menu and leave the submenu
170
+ * unreachable from the keyboard.
171
+ */
172
+ async activateByKeyboard() {
173
+ return (await this.host()).sendKeys(TestKey.ENTER);
174
+ }
175
+ /**
176
+ * Open this item's submenu with the right arrow and wait until it says so.
177
+ *
178
+ * The keyboard, not the pointer: it opens with no delay (hover waits out
179
+ * 120ms — `openSubmenuByHover()` covers that path) and needs no coordinates,
180
+ * which jsdom could not supply anyway. Sending the key focuses the item first,
181
+ * exactly as a roving cursor would have.
182
+ */
183
+ async openSubmenu(timeout = DEFAULT_TIMEOUT) {
184
+ await this.assertHasSubmenu('openSubmenu');
185
+ if (await this.isSubmenuOpen())
186
+ return;
187
+ await (await this.host()).sendKeys(TestKey.RIGHT_ARROW);
188
+ if (await this.isSubmenuOpen())
189
+ return;
190
+ if (await this.settled(true, timeout))
191
+ return;
192
+ throw new Error(`WrContextMenuItemHarness.openSubmenu(): "${await this.getText()}" did not open its submenu within ` +
193
+ `${timeout}ms. A disabled item refuses the key outright — check isDisabled().`);
194
+ }
195
+ /**
196
+ * Open this item's submenu by resting the pointer on it, the gesture a mouse
197
+ * user actually makes, and wait out the hover delay.
198
+ */
199
+ async openSubmenuByHover(timeout = DEFAULT_TIMEOUT) {
200
+ await this.assertHasSubmenu('openSubmenuByHover');
201
+ if (await this.isSubmenuOpen())
202
+ return;
203
+ await (await this.host()).hover();
204
+ if (await this.settled(true, timeout))
205
+ return;
206
+ throw new Error(`WrContextMenuItemHarness.openSubmenuByHover(): "${await this.getText()}" did not open its submenu ` +
207
+ `within ${timeout}ms. The hover path is a real 120ms timer, so a spec on fake timers has to ` +
208
+ 'advance the clock itself; a disabled item ignores the pointer entirely.');
209
+ }
210
+ /** Close this item's submenu with the left arrow. An item without one open is left alone. */
211
+ async closeSubmenu(timeout = DEFAULT_TIMEOUT) {
212
+ if (!(await this.isSubmenuOpen()))
213
+ return;
214
+ await (await this.host()).sendKeys(TestKey.LEFT_ARROW);
215
+ if (await this.settled(false, timeout))
216
+ return;
217
+ throw new Error(`WrContextMenuItemHarness.closeSubmenu(): "${await this.getText()}" still reports its submenu open ` +
218
+ `after ${timeout}ms.`);
219
+ }
220
+ /**
221
+ * The items in THIS item's submenu, in DOM order.
222
+ *
223
+ * Throws while the submenu is shut, and while the item owns none: both would
224
+ * otherwise answer with an empty array, which reads like a submenu that
225
+ * rendered nothing and fails somewhere else entirely.
226
+ */
227
+ async getSubmenuItems(filters = {}) {
228
+ const loader = await this.submenuLoader();
229
+ return loader.getAllHarnesses(WrContextMenuItemHarness.with(filters));
230
+ }
231
+ /** The labels of the items in this item's submenu, in DOM order. */
232
+ async getSubmenuItemTexts() {
233
+ const items = await this.getSubmenuItems();
234
+ return Promise.all(items.map(item => item.getText()));
235
+ }
236
+ /**
237
+ * Open the submenu if it is shut, then click the first item in it matching the
238
+ * filters.
239
+ *
240
+ * Picking a leaf dismisses the whole chain — this item's submenu and the root
241
+ * menu with it.
242
+ */
243
+ async clickSubmenuItem(filters) {
244
+ await this.openSubmenu();
245
+ const [item] = await this.getSubmenuItems(filters);
246
+ if (!item) {
247
+ const offered = await this.getSubmenuItemTexts();
248
+ throw new Error(`WrContextMenuItemHarness.clickSubmenuItem(): no item matched ${JSON.stringify(filters)}. ` +
249
+ `The submenu of "${await this.getText()}" offers: ${offered.join(', ')}.`);
250
+ }
251
+ await item.click();
252
+ }
253
+ /**
254
+ * A loader scoped to THIS item's submenu pane.
255
+ *
256
+ * Scoped by the published id rather than by `.wr-context-menu`: every pane in
257
+ * the chain — the root menu and each open submenu — carries that class in one
258
+ * shared overlay container, so a class query would answer with whichever
259
+ * opened first.
260
+ */
261
+ async submenuLoader() {
262
+ return this.documentRootLocatorFactory().harnessLoaderFor(`#${await this.submenuId()}`);
263
+ }
264
+ /** The id this item publishes as `aria-controls`, which its open submenu carries. */
265
+ async submenuId() {
266
+ const id = await (await this.host()).getAttribute('aria-controls');
267
+ if (!id) {
268
+ const label = await this.getText();
269
+ throw new Error(`WrContextMenuItemHarness: "${label}" has no submenu showing. An item publishes aria-controls only ` +
270
+ 'while its submenu is open — call openSubmenu() first, and check that it owns one at all with ' +
271
+ 'hasSubmenu().');
272
+ }
273
+ return id;
274
+ }
275
+ /** Fail early, and by name, when the item is not a drill-down at all. */
276
+ async assertHasSubmenu(method) {
277
+ if (await this.hasSubmenu())
278
+ return;
279
+ throw new Error(`WrContextMenuItemHarness.${method}(): "${await this.getText()}" owns no submenu, so there is ` +
280
+ 'nothing to open. An item that does advertises it with aria-haspopup="menu" — hasSubmenu().');
281
+ }
282
+ /** Poll until `isSubmenuOpen()` reports `open`, and say whether it did. */
283
+ async settled(open, timeout) {
284
+ for (let waited = 0; waited <= timeout; waited += POLL_STEP) {
285
+ if ((await this.isSubmenuOpen()) === open)
286
+ return true;
287
+ await sleep(POLL_STEP);
288
+ await this.forceStabilize();
289
+ }
290
+ return false;
291
+ }
292
+ }
293
+
294
+ /**
295
+ * @license
296
+ *
297
+ * Use of this source code is governed by an MIT-style license that can be
298
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
299
+ */
300
+ /**
301
+ * How long to sit still before an outside press is allowed to dismiss the menu.
302
+ *
303
+ * The directive ignores outside events for 200ms after opening, because the very
304
+ * right-click that opened the menu still has its own `mouseup` / `auxclick`
305
+ * pending — without the window, lifting the finger would shut the menu again.
306
+ */
307
+ const OUTSIDE_GUARD_MS = 250;
308
+ /**
309
+ * Test harness for `[wrContextMenu]` — the right-click target, and the menu it
310
+ * opens.
311
+ *
312
+ * The harness matches the TARGET, because that is the only part of a context
313
+ * menu in the fixture: `<wr-context-menu>` renders nothing of its own (it hands
314
+ * over an `<ng-template>` and hides its host), and the menu is portalled into the
315
+ * overlay container, a sibling of the whole app. So every item is read through
316
+ * the document root, scoped by the `aria-controls` id the target publishes while
317
+ * its menu is up — which is what keeps two menus on one page from answering with
318
+ * each other's items, and what keeps a re-opened menu from answering with the one
319
+ * still playing its exit animation.
320
+ *
321
+ * That scoped loader is also this harness's CONTENT loader, so
322
+ * `menu.getHarness(…)` resolves inside THIS menu: a component the consumer
323
+ * projected into the menu is reachable without the spec ever touching the
324
+ * overlay.
325
+ *
326
+ * **How it differs from `WrDropdownHarness`, its closest sibling.**
327
+ *
328
+ * - The gesture is a real `contextmenu` event, not a click — `open()` sends one,
329
+ * and `openByLongPress()` covers the touch path. There is no toggle: a second
330
+ * right-click re-opens the menu at the new pointer position.
331
+ * - Activating an item DISMISSES the menu (a dropdown's stays up), so
332
+ * `clickItem()` leaves it closed.
333
+ * - Submenus are a first-class input here rather than a nested trigger, so they
334
+ * are driven from {@link WrContextMenuItemHarness}.
335
+ * - The menu never takes focus: nothing focuses the first item and there is no
336
+ * arrow-key cursor between items, so there is no `getFocusedItemText()` to ask
337
+ * — see `WrContextMenuItemHarness.isFocused()`.
338
+ *
339
+ * **Timing.** The waits are real: a 500ms `setTimeout` for the long-press hold and
340
+ * another 220ms one for the exit animation the pane is held alive through, plus the
341
+ * outside-press window above — that one is a `performance.now()` comparison against
342
+ * the moment the menu opened rather than a timer, so only wall-clock time gets past
343
+ * it. The methods that must sit out real time say so; a spec on fake timers should
344
+ * drive the clock itself and read `isOpen()`.
345
+ *
346
+ * @example
347
+ * ```ts
348
+ * const menu = await loader.getHarness(WrContextMenuHarness.with({ text: 'Right-click me' }));
349
+ *
350
+ * await menu.open();
351
+ * expect(await menu.getItemTexts()).toEqual(['Cut', 'Copy', 'More']);
352
+ *
353
+ * await menu.clickItem({ text: 'Cut' });
354
+ * expect(await menu.isOpen()).toBe(false);
355
+ * ```
356
+ *
357
+ * @see https://ngwr.dev/guides/testing
358
+ */
359
+ class WrContextMenuHarness extends ContentContainerComponentHarness {
360
+ /** The directive's host — whatever element the consumer put `[wrContextMenu]` on. */
361
+ static hostSelector = '.wr-context-menu-host';
362
+ /** Build a predicate that narrows the query. */
363
+ static with(options = {}) {
364
+ return new HarnessPredicate(WrContextMenuHarness, options)
365
+ .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getTargetText(), text))
366
+ .addOption('open', options.open, async (harness, open) => (await harness.isOpen()) === open);
367
+ }
368
+ /** The target's own visible text — the content that gets right-clicked. */
369
+ async getTargetText() {
370
+ return (await this.host()).text();
371
+ }
372
+ /**
373
+ * Whether this target's menu is showing.
374
+ *
375
+ * Read from the target rather than from the overlay, and that is the whole
376
+ * point: a closed menu's pane stays in the DOM for its exit animation, while
377
+ * the reference is dropped the instant the close begins. Asking the DOM
378
+ * "is a menu present" would answer `true` for a quarter of a second after every
379
+ * dismissal.
380
+ *
381
+ * So the answer is only as good as the directive's claim on `aria-controls`:
382
+ * put `[wrContextMenu]` on an element that publishes one of its own and the two
383
+ * fight over a single attribute.
384
+ */
385
+ async isOpen() {
386
+ return (await (await this.host()).getAttribute('aria-controls')) !== null;
387
+ }
388
+ /** The role the menu announces — `menu`. Throws while no menu is open. */
389
+ async getMenuRole() {
390
+ return (await this.menu()).getAttribute('role');
391
+ }
392
+ /**
393
+ * Everything the open menu renders as text, runs of whitespace collapsed.
394
+ *
395
+ * Wider than `getItemTexts()` on purpose: `<wr-context-menu>` projects whatever
396
+ * it is given, so a section heading or any other markup a consumer put between
397
+ * the items shows up here and in no item harness. Dividers contribute nothing —
398
+ * they render no text.
399
+ *
400
+ * Expect to match a FRAGMENT of this rather than the whole of it: Angular
401
+ * strips the whitespace between elements at compile time, so the labels run
402
+ * together (`'Pick oneAppleBanana'`). The collapsing here only tidies newlines
403
+ * inside a single block of projected text.
404
+ */
405
+ async getMenuText() {
406
+ return (await (await this.menu()).text()).replace(/\s+/g, ' ').trim();
407
+ }
408
+ /**
409
+ * Open the menu by right-clicking the target, the gesture the directive
410
+ * actually listens for (`contextmenu`, which is also what Shift+F10 sends).
411
+ *
412
+ * An already-open menu is left alone — `rightClick()` is the raw gesture if
413
+ * what you want is the re-open.
414
+ *
415
+ * Note for a spec with two targets: a `contextmenu` event anywhere is an
416
+ * outside pointer event for every OTHER open menu, so this dismisses them on
417
+ * the way in. `openByLongPress()` is the route that does not.
418
+ */
419
+ async open() {
420
+ if (await this.isOpen())
421
+ return;
422
+ await this.rightClick();
423
+ if (await this.isOpen())
424
+ return;
425
+ throw new Error('WrContextMenuHarness.open(): the right-click did not open a menu. The directive answers ' +
426
+ '`contextmenu` on its own host, so check this is the element you put [wrContextMenu] on. One ' +
427
+ 'deliberate exception: a right-click within 700ms of a long-press open is swallowed, because touch ' +
428
+ 'browsers fire a synthetic contextmenu after the hold.');
429
+ }
430
+ /**
431
+ * Send a `contextmenu` to the target whatever state the menu is in.
432
+ *
433
+ * On an open menu this re-opens it at the new pointer position — the previous
434
+ * pane is dismissed and a fresh one takes its place, which is why the harness
435
+ * scopes by a per-open id rather than by class: for the length of the exit
436
+ * animation both are in the container, the dying one first.
437
+ *
438
+ * The coordinates the CDK requires are all zeros, and meaningless: jsdom has no
439
+ * layout. Nothing here needs them — the event is dispatched on the element
440
+ * itself, no hit test involved.
441
+ */
442
+ async rightClick() {
443
+ return (await this.host()).rightClick(0, 0);
444
+ }
445
+ /**
446
+ * Open the menu with a touch long-press — hold a non-mouse pointer on the
447
+ * target for 500ms — and wait until it is up.
448
+ *
449
+ * Worth its own method rather than an argument to `open()`, for the reason the
450
+ * dropdown has `openByKeyboard()`: it is the only way to get TWO context menus
451
+ * open at once. The press emits no `click` / `auxclick` / `contextmenu`, so it
452
+ * is not an outside press for anyone else's menu, while a right-click is.
453
+ *
454
+ * The pointer fields the directive reads are assigned onto a synthetic event:
455
+ * what matters is a primary pointer that is not a mouse. Movement beyond 10px,
456
+ * a scroll, or an early lift cancels the hold in the component — none of which
457
+ * this does.
458
+ */
459
+ async openByLongPress(timeout = DEFAULT_TIMEOUT) {
460
+ if (await this.isOpen())
461
+ return;
462
+ const host = await this.host();
463
+ await host.dispatchEvent('pointerdown', {
464
+ pointerType: 'touch',
465
+ isPrimary: true,
466
+ clientX: 0,
467
+ clientY: 0,
468
+ pageX: 0,
469
+ pageY: 0,
470
+ });
471
+ const opened = await this.settled(true, timeout);
472
+ // The finger comes off once the menu is up — after the hold, so it reads as a
473
+ // completed long-press rather than the early lift that cancels one.
474
+ await host.dispatchEvent('pointerup');
475
+ if (opened)
476
+ return;
477
+ throw new Error(`WrContextMenuHarness.openByLongPress(): nothing opened within ${timeout}ms. The hold is a real 500ms ` +
478
+ 'timer, so a spec on fake timers has to advance the clock itself and read isOpen().');
479
+ }
480
+ /**
481
+ * Dismiss the menu with Escape and wait until its pane has left the DOM.
482
+ *
483
+ * Escape is delivered by the CDK's keyboard dispatcher to the TOP-MOST overlay,
484
+ * so with a later menu (or any other overlay) open on top, this one keeps
485
+ * waiting its turn — that is what the throw below is about. The wait covers the
486
+ * 220ms exit animation, so a spec can assert afterwards that nothing lingers.
487
+ */
488
+ async close(timeout = DEFAULT_TIMEOUT) {
489
+ if (!(await this.isOpen()))
490
+ return;
491
+ // Captured first: the target drops the reference the instant the close starts,
492
+ // and the wait below still has to know which pane to watch.
493
+ const id = await this.menuId();
494
+ await (await this.host()).sendKeys(TestKey.ESCAPE);
495
+ if (await this.isOpen()) {
496
+ throw new Error('WrContextMenuHarness.close(): Escape did not dismiss the menu. The CDK keyboard dispatcher ' +
497
+ 'delivers it to the TOP-MOST overlay only, so anything opened after this menu takes it first.');
498
+ }
499
+ return this.waitUntilGone(id, 'close', timeout);
500
+ }
501
+ /**
502
+ * Dismiss the menu by pressing outside it, the way a user gets rid of one, and
503
+ * wait until its pane has left the DOM.
504
+ *
505
+ * Sits out real time first: the directive ignores outside events for 200ms after
506
+ * opening, so the right-click that opened the menu cannot immediately close it
507
+ * again with its own trailing `auxclick`. The press then lands on the TARGET,
508
+ * which is outside the pane and therefore counts — the page background is not
509
+ * something a harness has a handle on. A target that carries a `(click)` of its
510
+ * own will see it fire, so assert on the dismissal rather than on that handler.
511
+ */
512
+ async closeByOutsidePress(timeout = DEFAULT_TIMEOUT) {
513
+ if (!(await this.isOpen()))
514
+ return;
515
+ const id = await this.menuId();
516
+ await sleep(OUTSIDE_GUARD_MS);
517
+ await this.forceStabilize();
518
+ await (await this.host()).click();
519
+ if (await this.isOpen()) {
520
+ throw new Error('WrContextMenuHarness.closeByOutsidePress(): the menu is still open. A press inside the pane is ' +
521
+ 'not an outside press, and neither is one that started inside it — this one lands on the target.');
522
+ }
523
+ return this.waitUntilGone(id, 'closeByOutsidePress', timeout);
524
+ }
525
+ /**
526
+ * The items in this menu, in DOM order.
527
+ *
528
+ * Only this menu's own: an open submenu is a separate pane, so its items are
529
+ * `WrContextMenuItemHarness.getSubmenuItems()`, not part of this list. Dividers
530
+ * are not items either.
531
+ *
532
+ * Throws while the menu is shut — the items do not exist anywhere until the
533
+ * portal is attached, and an empty array reads like a menu that rendered
534
+ * nothing.
535
+ */
536
+ async getItems(filters = {}) {
537
+ return this.getAllHarnesses(WrContextMenuItemHarness.with(filters));
538
+ }
539
+ /** The labels of this menu's items, in DOM order. */
540
+ async getItemTexts() {
541
+ const items = await this.getItems();
542
+ return Promise.all(items.map(item => item.getText()));
543
+ }
544
+ /**
545
+ * How many separators this menu shows.
546
+ *
547
+ * Counted by `role="separator"` rather than by `.wr-context-menu-divider`, so a
548
+ * separator the consumer wrote themselves counts too — the role is what tells a
549
+ * screen reader where one group of items ends. A separator is never a member of
550
+ * `getItems()`.
551
+ */
552
+ async getDividerCount() {
553
+ const separators = await this.inMenuAll('[role="separator"]');
554
+ return separators.length;
555
+ }
556
+ /**
557
+ * Open the menu if it is shut, then click the first item matching the filters.
558
+ *
559
+ * Picking a leaf DISMISSES the menu — unlike a dropdown, which stays up. The
560
+ * dismissal is reported at once (the target drops its reference synchronously),
561
+ * while the pane plays its exit animation for another 220ms.
562
+ */
563
+ async clickItem(filters) {
564
+ await this.open();
565
+ const [item] = await this.getItems(filters);
566
+ if (!item) {
567
+ const offered = await this.getItemTexts();
568
+ throw new Error(`WrContextMenuHarness.clickItem(): no item matched ${JSON.stringify(filters)}. ` +
569
+ `The menu offers: ${offered.join(', ')}.`);
570
+ }
571
+ await item.click();
572
+ }
573
+ /**
574
+ * A loader scoped to THIS target's menu — the content loader every
575
+ * `HarnessLoader` method on this class runs through, `getItems()` included.
576
+ *
577
+ * Scoped by the published id rather than by `.wr-context-menu`: the overlay
578
+ * container is shared by every pane on the page, so a bare class query would
579
+ * answer with whichever menu opened first.
580
+ */
581
+ async getRootHarnessLoader() {
582
+ return this.documentRootLocatorFactory().harnessLoaderFor(`#${await this.menuId()}`);
583
+ }
584
+ /** This target's menu element in the overlay. */
585
+ async menu() {
586
+ return this.documentRootLocatorFactory().locatorFor(`#${await this.menuId()}`)();
587
+ }
588
+ /** Every element inside THIS menu matching the selector. */
589
+ async inMenuAll(selector) {
590
+ return this.documentRootLocatorFactory().locatorForAll(`#${await this.menuId()} ${selector}`)();
591
+ }
592
+ /** The id the target publishes as `aria-controls`, which its open menu carries. */
593
+ async menuId() {
594
+ const id = await (await this.host()).getAttribute('aria-controls');
595
+ if (!id) {
596
+ throw new Error('WrContextMenuHarness: no menu is open, so there is nothing inside it to read — call open() ' +
597
+ 'first. The target publishes `aria-controls` only while its menu is up.');
598
+ }
599
+ return id;
600
+ }
601
+ /** Poll until the pane with this id has been disposed. */
602
+ async waitUntilGone(id, method, timeout) {
603
+ const locate = this.documentRootLocatorFactory().locatorForOptional(`#${id}`);
604
+ for (let waited = 0; waited <= timeout; waited += POLL_STEP) {
605
+ if ((await locate()) === null)
606
+ return;
607
+ await sleep(POLL_STEP);
608
+ await this.forceStabilize();
609
+ }
610
+ throw new Error(`WrContextMenuHarness.${method}(): the menu was still in the DOM ${timeout}ms after it closed. The ` +
611
+ 'directive keeps the pane alive for its 220ms exit animation and disposes it on a real timer, so a ' +
612
+ 'spec on fake timers has to advance the clock itself.');
613
+ }
614
+ /** Poll until `isOpen()` reports `open`, and say whether it did. */
615
+ async settled(open, timeout) {
616
+ for (let waited = 0; waited <= timeout; waited += POLL_STEP) {
617
+ if ((await this.isOpen()) === open)
618
+ return true;
619
+ await sleep(POLL_STEP);
620
+ await this.forceStabilize();
621
+ }
622
+ return false;
623
+ }
624
+ }
625
+
626
+ /**
627
+ * Generated bundle index. Do not edit.
628
+ */
629
+
630
+ export { WrContextMenuHarness, WrContextMenuItemHarness };
631
+ //# sourceMappingURL=ngwr-context-menu-testing.mjs.map