ngwr 10.2.1 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) hide show
  1. package/README.md +39 -19
  2. package/anchor/styles/_index.scss +4 -4
  3. package/back-top/styles/_index.scss +6 -1
  4. package/blur-text/styles/_index.scss +13 -0
  5. package/button/styles/_index.scss +11 -6
  6. package/carousel/styles/_index.scss +13 -2
  7. package/cascader/styles/_index.scss +2 -2
  8. package/circular-text/styles/_index.scss +2 -0
  9. package/collapse/styles/_index.scss +1 -1
  10. package/color-picker/styles/_index.scss +6 -1
  11. package/compare/styles/_index.scss +1 -2
  12. package/context-menu/styles/_index.scss +6 -1
  13. package/descriptions/styles/_index.scss +2 -2
  14. package/dialog/styles/_index.scss +7 -0
  15. package/drawer/styles/_index.scss +20 -1
  16. package/dropdown/styles/_index.scss +19 -5
  17. package/empty/styles/_index.scss +10 -0
  18. package/fesm2022/ngwr-action-sheet.mjs +13 -3
  19. package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
  20. package/fesm2022/ngwr-affix.mjs +40 -13
  21. package/fesm2022/ngwr-affix.mjs.map +1 -1
  22. package/fesm2022/ngwr-anchor.mjs +18 -6
  23. package/fesm2022/ngwr-anchor.mjs.map +1 -1
  24. package/fesm2022/ngwr-aurora.mjs +2 -2
  25. package/fesm2022/ngwr-aurora.mjs.map +1 -1
  26. package/fesm2022/ngwr-avatar.mjs +31 -7
  27. package/fesm2022/ngwr-avatar.mjs.map +1 -1
  28. package/fesm2022/ngwr-back-top.mjs +6 -2
  29. package/fesm2022/ngwr-back-top.mjs.map +1 -1
  30. package/fesm2022/ngwr-badge.mjs +1 -1
  31. package/fesm2022/ngwr-badge.mjs.map +1 -1
  32. package/fesm2022/ngwr-bar-chart.mjs +30 -9
  33. package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
  34. package/fesm2022/ngwr-blur-text.mjs +2 -2
  35. package/fesm2022/ngwr-blur-text.mjs.map +1 -1
  36. package/fesm2022/ngwr-border-glow.mjs +2 -2
  37. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  38. package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
  39. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  40. package/fesm2022/ngwr-burger.mjs +9 -4
  41. package/fesm2022/ngwr-burger.mjs.map +1 -1
  42. package/fesm2022/ngwr-button-testing.mjs +96 -0
  43. package/fesm2022/ngwr-button-testing.mjs.map +1 -0
  44. package/fesm2022/ngwr-button.mjs +31 -14
  45. package/fesm2022/ngwr-button.mjs.map +1 -1
  46. package/fesm2022/ngwr-calendar-heatmap.mjs +40 -8
  47. package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
  48. package/fesm2022/ngwr-calendar.mjs +20 -1
  49. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  50. package/fesm2022/ngwr-card.mjs +2 -2
  51. package/fesm2022/ngwr-card.mjs.map +1 -1
  52. package/fesm2022/ngwr-carousel-testing.mjs +377 -0
  53. package/fesm2022/ngwr-carousel-testing.mjs.map +1 -0
  54. package/fesm2022/ngwr-carousel.mjs +67 -13
  55. package/fesm2022/ngwr-carousel.mjs.map +1 -1
  56. package/fesm2022/ngwr-cascader-testing.mjs +534 -0
  57. package/fesm2022/ngwr-cascader-testing.mjs.map +1 -0
  58. package/fesm2022/ngwr-cascader.mjs +2 -2
  59. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  60. package/fesm2022/ngwr-checkbox-testing.mjs +90 -0
  61. package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -0
  62. package/fesm2022/ngwr-checkbox.mjs +9 -3
  63. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  64. package/fesm2022/ngwr-circular-text.mjs +2 -2
  65. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  66. package/fesm2022/ngwr-click-spark.mjs +2 -2
  67. package/fesm2022/ngwr-click-spark.mjs.map +1 -1
  68. package/fesm2022/ngwr-collapse-testing.mjs +368 -0
  69. package/fesm2022/ngwr-collapse-testing.mjs.map +1 -0
  70. package/fesm2022/ngwr-color-picker.mjs +134 -14
  71. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  72. package/fesm2022/ngwr-command-palette-testing.mjs +589 -0
  73. package/fesm2022/ngwr-command-palette-testing.mjs.map +1 -0
  74. package/fesm2022/ngwr-command-palette.mjs +58 -8
  75. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  76. package/fesm2022/ngwr-compare.mjs +103 -13
  77. package/fesm2022/ngwr-compare.mjs.map +1 -1
  78. package/fesm2022/ngwr-config.mjs +106 -0
  79. package/fesm2022/ngwr-config.mjs.map +1 -0
  80. package/fesm2022/ngwr-context-menu-testing.mjs +631 -0
  81. package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -0
  82. package/fesm2022/ngwr-context-menu.mjs +94 -8
  83. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  84. package/fesm2022/ngwr-cookie.mjs +5 -1
  85. package/fesm2022/ngwr-cookie.mjs.map +1 -1
  86. package/fesm2022/ngwr-counter.mjs +11 -3
  87. package/fesm2022/ngwr-counter.mjs.map +1 -1
  88. package/fesm2022/ngwr-date-adapter-luxon.mjs +52 -4
  89. package/fesm2022/ngwr-date-adapter-luxon.mjs.map +1 -1
  90. package/fesm2022/ngwr-date-adapter.mjs +54 -8
  91. package/fesm2022/ngwr-date-adapter.mjs.map +1 -1
  92. package/fesm2022/ngwr-date-picker-testing.mjs +766 -0
  93. package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -0
  94. package/fesm2022/ngwr-date-picker.mjs +73 -3
  95. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  96. package/fesm2022/ngwr-decrypt-text.mjs +27 -9
  97. package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
  98. package/fesm2022/ngwr-dialog-testing.mjs +89 -0
  99. package/fesm2022/ngwr-dialog-testing.mjs.map +1 -0
  100. package/fesm2022/ngwr-directives.mjs +36 -12
  101. package/fesm2022/ngwr-directives.mjs.map +1 -1
  102. package/fesm2022/ngwr-donut-chart.mjs +22 -5
  103. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  104. package/fesm2022/ngwr-drag-drop.mjs +2 -2
  105. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  106. package/fesm2022/ngwr-drawer-testing.mjs +250 -0
  107. package/fesm2022/ngwr-drawer-testing.mjs.map +1 -0
  108. package/fesm2022/ngwr-dropdown-testing.mjs +291 -0
  109. package/fesm2022/ngwr-dropdown-testing.mjs.map +1 -0
  110. package/fesm2022/ngwr-dropdown.mjs +10 -2
  111. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  112. package/fesm2022/ngwr-empty.mjs +24 -7
  113. package/fesm2022/ngwr-empty.mjs.map +1 -1
  114. package/fesm2022/ngwr-event-calendar.mjs +57 -10
  115. package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
  116. package/fesm2022/ngwr-falling-text.mjs +2 -2
  117. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  118. package/fesm2022/ngwr-file-upload-testing.mjs +332 -0
  119. package/fesm2022/ngwr-file-upload-testing.mjs.map +1 -0
  120. package/fesm2022/ngwr-form-testing.mjs +451 -0
  121. package/fesm2022/ngwr-form-testing.mjs.map +1 -0
  122. package/fesm2022/ngwr-form.mjs +19 -3
  123. package/fesm2022/ngwr-form.mjs.map +1 -1
  124. package/fesm2022/ngwr-fuzzy-text.mjs +9 -2
  125. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  126. package/fesm2022/ngwr-gauge.mjs +19 -5
  127. package/fesm2022/ngwr-gauge.mjs.map +1 -1
  128. package/fesm2022/ngwr-glitch-text.mjs +2 -2
  129. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  130. package/fesm2022/ngwr-gradient-text.mjs +2 -2
  131. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  132. package/fesm2022/ngwr-i18n-en.mjs +50 -0
  133. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  134. package/fesm2022/ngwr-i18n-ru.mjs +48 -0
  135. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  136. package/fesm2022/ngwr-image-cropper.mjs +23 -0
  137. package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
  138. package/fesm2022/ngwr-input-number-testing.mjs +306 -0
  139. package/fesm2022/ngwr-input-number-testing.mjs.map +1 -0
  140. package/fesm2022/ngwr-input-number.mjs +35 -3
  141. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  142. package/fesm2022/ngwr-input-otp-testing.mjs +419 -0
  143. package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -0
  144. package/fesm2022/ngwr-input-otp.mjs +36 -5
  145. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  146. package/fesm2022/ngwr-input-testing.mjs +102 -0
  147. package/fesm2022/ngwr-input-testing.mjs.map +1 -0
  148. package/fesm2022/ngwr-input.mjs +47 -10
  149. package/fesm2022/ngwr-input.mjs.map +1 -1
  150. package/fesm2022/ngwr-knob.mjs +44 -8
  151. package/fesm2022/ngwr-knob.mjs.map +1 -1
  152. package/fesm2022/ngwr-layout.mjs +21 -5
  153. package/fesm2022/ngwr-layout.mjs.map +1 -1
  154. package/fesm2022/ngwr-lightbox.mjs +33 -6
  155. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  156. package/fesm2022/ngwr-line-chart.mjs +17 -4
  157. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  158. package/fesm2022/ngwr-list.mjs +2 -2
  159. package/fesm2022/ngwr-list.mjs.map +1 -1
  160. package/fesm2022/ngwr-loading-bar.mjs +2 -2
  161. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  162. package/fesm2022/ngwr-markdown-testing.mjs +516 -0
  163. package/fesm2022/ngwr-markdown-testing.mjs.map +1 -0
  164. package/fesm2022/ngwr-markdown.mjs +1492 -0
  165. package/fesm2022/ngwr-markdown.mjs.map +1 -0
  166. package/fesm2022/ngwr-marquee.mjs +17 -6
  167. package/fesm2022/ngwr-marquee.mjs.map +1 -1
  168. package/fesm2022/ngwr-mention-testing.mjs +513 -0
  169. package/fesm2022/ngwr-mention-testing.mjs.map +1 -0
  170. package/fesm2022/ngwr-mention.mjs +10 -1
  171. package/fesm2022/ngwr-mention.mjs.map +1 -1
  172. package/fesm2022/ngwr-meta.mjs +22 -7
  173. package/fesm2022/ngwr-meta.mjs.map +1 -1
  174. package/fesm2022/ngwr-meter-group.mjs +19 -5
  175. package/fesm2022/ngwr-meter-group.mjs.map +1 -1
  176. package/fesm2022/ngwr-overlay.mjs +41 -1
  177. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  178. package/fesm2022/ngwr-pagination-testing.mjs +389 -0
  179. package/fesm2022/ngwr-pagination-testing.mjs.map +1 -0
  180. package/fesm2022/ngwr-pagination.mjs +14 -2
  181. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  182. package/fesm2022/ngwr-popconfirm-testing.mjs +309 -0
  183. package/fesm2022/ngwr-popconfirm-testing.mjs.map +1 -0
  184. package/fesm2022/ngwr-popconfirm.mjs +95 -17
  185. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  186. package/fesm2022/ngwr-popover-testing.mjs +316 -0
  187. package/fesm2022/ngwr-popover-testing.mjs.map +1 -0
  188. package/fesm2022/ngwr-popover.mjs +21 -3
  189. package/fesm2022/ngwr-popover.mjs.map +1 -1
  190. package/fesm2022/ngwr-pull-to-refresh.mjs +17 -2
  191. package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -1
  192. package/fesm2022/ngwr-qr.mjs +13 -3
  193. package/fesm2022/ngwr-qr.mjs.map +1 -1
  194. package/fesm2022/ngwr-radio-testing.mjs +392 -0
  195. package/fesm2022/ngwr-radio-testing.mjs.map +1 -0
  196. package/fesm2022/ngwr-radio.mjs +10 -3
  197. package/fesm2022/ngwr-radio.mjs.map +1 -1
  198. package/fesm2022/ngwr-rating-testing.mjs +384 -0
  199. package/fesm2022/ngwr-rating-testing.mjs.map +1 -0
  200. package/fesm2022/ngwr-rating.mjs +37 -2
  201. package/fesm2022/ngwr-rating.mjs.map +1 -1
  202. package/fesm2022/ngwr-segmented-testing.mjs +512 -0
  203. package/fesm2022/ngwr-segmented-testing.mjs.map +1 -0
  204. package/fesm2022/ngwr-select-testing.mjs +268 -0
  205. package/fesm2022/ngwr-select-testing.mjs.map +1 -0
  206. package/fesm2022/ngwr-select.mjs +87 -16
  207. package/fesm2022/ngwr-select.mjs.map +1 -1
  208. package/fesm2022/ngwr-shiny-text.mjs +2 -2
  209. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  210. package/fesm2022/ngwr-sidebar.mjs +65 -12
  211. package/fesm2022/ngwr-sidebar.mjs.map +1 -1
  212. package/fesm2022/ngwr-slider-testing.mjs +478 -0
  213. package/fesm2022/ngwr-slider-testing.mjs.map +1 -0
  214. package/fesm2022/ngwr-slider.mjs +57 -13
  215. package/fesm2022/ngwr-slider.mjs.map +1 -1
  216. package/fesm2022/ngwr-sparkline.mjs +26 -6
  217. package/fesm2022/ngwr-sparkline.mjs.map +1 -1
  218. package/fesm2022/ngwr-speed-dial.mjs +37 -4
  219. package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
  220. package/fesm2022/ngwr-spinner.mjs +12 -3
  221. package/fesm2022/ngwr-spinner.mjs.map +1 -1
  222. package/fesm2022/ngwr-splash-cursor.mjs +2 -2
  223. package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
  224. package/fesm2022/ngwr-split-text.mjs +2 -2
  225. package/fesm2022/ngwr-split-text.mjs.map +1 -1
  226. package/fesm2022/ngwr-splitter.mjs +70 -9
  227. package/fesm2022/ngwr-splitter.mjs.map +1 -1
  228. package/fesm2022/ngwr-spotlight-card.mjs +2 -2
  229. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  230. package/fesm2022/ngwr-star-border.mjs +2 -2
  231. package/fesm2022/ngwr-star-border.mjs.map +1 -1
  232. package/fesm2022/ngwr-statistic.mjs +24 -7
  233. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  234. package/fesm2022/ngwr-stepper-testing.mjs +477 -0
  235. package/fesm2022/ngwr-stepper-testing.mjs.map +1 -0
  236. package/fesm2022/ngwr-switch-testing.mjs +77 -0
  237. package/fesm2022/ngwr-switch-testing.mjs.map +1 -0
  238. package/fesm2022/ngwr-switch.mjs +9 -3
  239. package/fesm2022/ngwr-switch.mjs.map +1 -1
  240. package/fesm2022/ngwr-table-testing.mjs +580 -0
  241. package/fesm2022/ngwr-table-testing.mjs.map +1 -0
  242. package/fesm2022/ngwr-table.mjs +87 -14
  243. package/fesm2022/ngwr-table.mjs.map +1 -1
  244. package/fesm2022/ngwr-tabs-testing.mjs +617 -0
  245. package/fesm2022/ngwr-tabs-testing.mjs.map +1 -0
  246. package/fesm2022/ngwr-tabs.mjs +38 -6
  247. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  248. package/fesm2022/ngwr-textarea-testing.mjs +238 -0
  249. package/fesm2022/ngwr-textarea-testing.mjs.map +1 -0
  250. package/fesm2022/ngwr-textarea.mjs +32 -4
  251. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  252. package/fesm2022/ngwr-tilt-card.mjs +2 -2
  253. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  254. package/fesm2022/ngwr-toast-testing.mjs +101 -0
  255. package/fesm2022/ngwr-toast-testing.mjs.map +1 -0
  256. package/fesm2022/ngwr-toast.mjs +2 -2
  257. package/fesm2022/ngwr-toast.mjs.map +1 -1
  258. package/fesm2022/ngwr-tour.mjs +61 -9
  259. package/fesm2022/ngwr-tour.mjs.map +1 -1
  260. package/fesm2022/ngwr-transfer-testing.mjs +538 -0
  261. package/fesm2022/ngwr-transfer-testing.mjs.map +1 -0
  262. package/fesm2022/ngwr-transfer.mjs +45 -14
  263. package/fesm2022/ngwr-transfer.mjs.map +1 -1
  264. package/fesm2022/ngwr-tree-testing.mjs +734 -0
  265. package/fesm2022/ngwr-tree-testing.mjs.map +1 -0
  266. package/fesm2022/ngwr-tree.mjs +73 -7
  267. package/fesm2022/ngwr-tree.mjs.map +1 -1
  268. package/fesm2022/ngwr-typewriter.mjs +5 -3
  269. package/fesm2022/ngwr-typewriter.mjs.map +1 -1
  270. package/fesm2022/ngwr-version.mjs +1 -1
  271. package/fesm2022/ngwr-version.mjs.map +1 -1
  272. package/fesm2022/ngwr-virtual-scroll.mjs +31 -5
  273. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  274. package/fesm2022/ngwr-waves.mjs +3 -3
  275. package/fesm2022/ngwr-waves.mjs.map +1 -1
  276. package/fesm2022/ngwr-window.mjs +8 -0
  277. package/fesm2022/ngwr-window.mjs.map +1 -1
  278. package/gauge/styles/_index.scss +1 -1
  279. package/glitch-text/styles/_index.scss +4 -0
  280. package/i18n/en.json +48 -0
  281. package/i18n/ru.json +48 -0
  282. package/image-cropper/styles/_index.scss +13 -1
  283. package/input/styles/_index.scss +2 -2
  284. package/input-number/styles/_index.scss +7 -2
  285. package/knob/styles/_index.scss +8 -1
  286. package/layout/styles/_index.scss +3 -3
  287. package/lightbox/styles/_index.scss +10 -2
  288. package/line-chart/styles/_index.scss +6 -0
  289. package/llms-full.txt +151 -4
  290. package/llms.txt +57 -8
  291. package/loading-bar/styles/_index.scss +1 -2
  292. package/markdown/styles/_index.scss +296 -0
  293. package/marquee/styles/_index.scss +12 -0
  294. package/mcp/api.js +512 -0
  295. package/mcp/catalog.js +157 -0
  296. package/mcp/server.js +273 -0
  297. package/mcp/tools.js +366 -0
  298. package/meter-group/styles/_index.scss +1 -1
  299. package/package.json +186 -35
  300. package/pagination/styles/_index.scss +6 -6
  301. package/popover/styles/_index.scss +37 -5
  302. package/rating/styles/_index.scss +10 -0
  303. package/schematics/use/symbol-map.json +2 -0
  304. package/segmented/styles/_index.scss +7 -0
  305. package/select/styles/_index.scss +29 -9
  306. package/sidebar/styles/_index.scss +30 -5
  307. package/slider/styles/_index.scss +15 -0
  308. package/speed-dial/styles/_index.scss +20 -0
  309. package/split-text/styles/_index.scss +13 -0
  310. package/star-border/styles/_index.scss +2 -0
  311. package/stepper/styles/_index.scss +1 -1
  312. package/styles/_grid.scss +4 -4
  313. package/styles.scss +1 -0
  314. package/switch/styles/_index.scss +5 -3
  315. package/table/styles/_index.scss +22 -11
  316. package/tabs/styles/_index.scss +11 -1
  317. package/textarea/styles/_index.scss +5 -0
  318. package/theme/styles/_colors.scss +29 -13
  319. package/theme/styles/_dark.scss +11 -3
  320. package/theme/styles/_mixins.scss +3 -0
  321. package/timeline/styles/_index.scss +2 -2
  322. package/toast/styles/_index.scss +17 -8
  323. package/toolbar/styles/_index.scss +3 -3
  324. package/tour/styles/_index.scss +7 -1
  325. package/tree/styles/_index.scss +5 -3
  326. package/types/ngwr-action-sheet.d.ts +9 -1
  327. package/types/ngwr-affix.d.ts +7 -1
  328. package/types/ngwr-anchor.d.ts +8 -1
  329. package/types/ngwr-avatar.d.ts +13 -3
  330. package/types/ngwr-bar-chart.d.ts +16 -0
  331. package/types/ngwr-burger.d.ts +6 -2
  332. package/types/ngwr-button-testing.d.ts +85 -0
  333. package/types/ngwr-button.d.ts +26 -10
  334. package/types/ngwr-calendar-heatmap.d.ts +16 -2
  335. package/types/ngwr-calendar.d.ts +10 -0
  336. package/types/ngwr-carousel-testing.d.ts +257 -0
  337. package/types/ngwr-carousel.d.ts +20 -4
  338. package/types/ngwr-cascader-testing.d.ts +392 -0
  339. package/types/ngwr-checkbox-testing.d.ts +77 -0
  340. package/types/ngwr-checkbox.d.ts +7 -2
  341. package/types/ngwr-collapse-testing.d.ts +290 -0
  342. package/types/ngwr-color-picker.d.ts +20 -11
  343. package/types/ngwr-command-palette-testing.d.ts +437 -0
  344. package/types/ngwr-command-palette.d.ts +25 -2
  345. package/types/ngwr-compare.d.ts +50 -2
  346. package/types/ngwr-config.d.ts +176 -0
  347. package/types/ngwr-context-menu-testing.d.ts +401 -0
  348. package/types/ngwr-context-menu.d.ts +65 -17
  349. package/types/ngwr-counter.d.ts +6 -1
  350. package/types/ngwr-date-adapter-luxon.d.ts +26 -0
  351. package/types/ngwr-date-picker-testing.d.ts +518 -0
  352. package/types/ngwr-date-picker.d.ts +4 -0
  353. package/types/ngwr-dialog-testing.d.ts +79 -0
  354. package/types/ngwr-directives.d.ts +10 -1
  355. package/types/ngwr-donut-chart.d.ts +8 -1
  356. package/types/ngwr-drawer-testing.d.ts +196 -0
  357. package/types/ngwr-dropdown-testing.d.ts +202 -0
  358. package/types/ngwr-dropdown.d.ts +7 -1
  359. package/types/ngwr-empty.d.ts +19 -4
  360. package/types/ngwr-event-calendar.d.ts +26 -1
  361. package/types/ngwr-file-upload-testing.d.ts +194 -0
  362. package/types/ngwr-form-testing.d.ts +379 -0
  363. package/types/ngwr-form.d.ts +17 -0
  364. package/types/ngwr-gauge.d.ts +13 -1
  365. package/types/ngwr-image-cropper.d.ts +10 -0
  366. package/types/ngwr-input-number-testing.d.ts +226 -0
  367. package/types/ngwr-input-number.d.ts +29 -1
  368. package/types/ngwr-input-otp-testing.d.ts +299 -0
  369. package/types/ngwr-input-otp.d.ts +23 -2
  370. package/types/ngwr-input-testing.d.ts +84 -0
  371. package/types/ngwr-input.d.ts +20 -6
  372. package/types/ngwr-knob.d.ts +18 -0
  373. package/types/ngwr-layout.d.ts +1 -0
  374. package/types/ngwr-lightbox.d.ts +17 -3
  375. package/types/ngwr-line-chart.d.ts +9 -2
  376. package/types/ngwr-markdown-testing.d.ts +462 -0
  377. package/types/ngwr-markdown.d.ts +534 -0
  378. package/types/ngwr-marquee.d.ts +12 -2
  379. package/types/ngwr-mention-testing.d.ts +359 -0
  380. package/types/ngwr-meta.d.ts +4 -2
  381. package/types/ngwr-meter-group.d.ts +11 -1
  382. package/types/ngwr-overlay.d.ts +33 -2
  383. package/types/ngwr-pagination-testing.d.ts +291 -0
  384. package/types/ngwr-pagination.d.ts +1 -0
  385. package/types/ngwr-popconfirm-testing.d.ts +235 -0
  386. package/types/ngwr-popconfirm.d.ts +31 -21
  387. package/types/ngwr-popover-testing.d.ts +221 -0
  388. package/types/ngwr-popover.d.ts +9 -0
  389. package/types/ngwr-pull-to-refresh.d.ts +7 -0
  390. package/types/ngwr-qr.d.ts +9 -1
  391. package/types/ngwr-radio-testing.d.ts +296 -0
  392. package/types/ngwr-radio.d.ts +8 -2
  393. package/types/ngwr-rating-testing.d.ts +291 -0
  394. package/types/ngwr-rating.d.ts +23 -0
  395. package/types/ngwr-segmented-testing.d.ts +401 -0
  396. package/types/ngwr-select-testing.d.ts +175 -0
  397. package/types/ngwr-select.d.ts +45 -4
  398. package/types/ngwr-sidebar.d.ts +17 -2
  399. package/types/ngwr-slider-testing.d.ts +329 -0
  400. package/types/ngwr-slider.d.ts +35 -1
  401. package/types/ngwr-sparkline.d.ts +12 -2
  402. package/types/ngwr-speed-dial.d.ts +17 -18
  403. package/types/ngwr-spinner.d.ts +8 -1
  404. package/types/ngwr-splitter.d.ts +24 -1
  405. package/types/ngwr-statistic.d.ts +12 -2
  406. package/types/ngwr-stepper-testing.d.ts +346 -0
  407. package/types/ngwr-switch-testing.d.ts +66 -0
  408. package/types/ngwr-switch.d.ts +7 -2
  409. package/types/ngwr-table-testing.d.ts +423 -0
  410. package/types/ngwr-table.d.ts +42 -0
  411. package/types/ngwr-tabs-testing.d.ts +470 -0
  412. package/types/ngwr-tabs.d.ts +9 -0
  413. package/types/ngwr-textarea-testing.d.ts +184 -0
  414. package/types/ngwr-textarea.d.ts +7 -2
  415. package/types/ngwr-toast-testing.d.ts +80 -0
  416. package/types/ngwr-tour.d.ts +27 -0
  417. package/types/ngwr-transfer-testing.d.ts +444 -0
  418. package/types/ngwr-transfer.d.ts +16 -1
  419. package/types/ngwr-tree-testing.d.ts +501 -0
  420. package/types/ngwr-tree.d.ts +33 -0
  421. package/types/ngwr-version.d.ts +1 -1
  422. package/types/ngwr-virtual-scroll.d.ts +13 -1
  423. package/typewriter/styles/_index.scss +1 -1
  424. package/typography/styles/_index.scss +1 -1
  425. package/window/styles/_index.scss +32 -9
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-carousel.mjs","sources":["../../../projects/lib/carousel/carousel-slide.ts","../../../projects/lib/carousel/carousel.ts","../../../projects/lib/carousel/carousel.html","../../../projects/lib/carousel/ngwr-carousel.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Component, ViewEncapsulation } from '@angular/core';\n\n/**\n * One slide in a {@link WrCarousel}. Holds whatever content you\n * project — image, card, video, anything.\n */\n@Component({\n selector: 'wr-carousel-slide',\n template: '<ng-content />',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-carousel-slide', role: 'group', 'aria-roledescription': 'slide' },\n})\nexport class WrCarouselSlide {}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n DestroyRef,\n ViewEncapsulation,\n computed,\n contentChildren,\n effect,\n inject,\n input,\n model,\n signal,\n} from '@angular/core';\n\nimport { useI18nText } from 'ngwr/i18n';\n\nimport { WrCarouselSlide } from './carousel-slide';\n\n/**\n * Slide carousel. Project `<wr-carousel-slide>` children — the carousel\n * snaps between them with prev/next buttons and optional dots / autoplay.\n *\n * @example\n * ```html\n * <wr-carousel [(active)]=\"i\" autoplay>\n * <wr-carousel-slide><img src=\"a.jpg\" /></wr-carousel-slide>\n * <wr-carousel-slide><img src=\"b.jpg\" /></wr-carousel-slide>\n * <wr-carousel-slide><img src=\"c.jpg\" /></wr-carousel-slide>\n * </wr-carousel>\n * ```\n *\n * @see https://ngwr.dev/reference/components/carousel\n */\n@Component({\n selector: 'wr-carousel',\n templateUrl: './carousel.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-carousel' },\n})\nexport class WrCarousel {\n /** Active slide index. Two-way bindable. @default 0 */\n /** Accessible name of the previous-slide button. Falls back to `carousel.prev`. */\n readonly prevLabel = input<string | null>(null);\n\n /** Accessible name of the next-slide button. Falls back to `carousel.next`. */\n readonly nextLabel = input<string | null>(null);\n\n /** Accessible name of the dot group. Falls back to `carousel.pagination`. */\n readonly paginationLabel = input<string | null>(null);\n\n protected readonly resolvedPrevLabel = useI18nText(this.prevLabel, 'carousel.prev', 'Previous slide');\n protected readonly resolvedNextLabel = useI18nText(this.nextLabel, 'carousel.next', 'Next slide');\n protected readonly resolvedPaginationLabel = useI18nText(\n this.paginationLabel,\n 'carousel.pagination',\n 'Carousel pagination'\n );\n\n readonly active = model(0);\n\n /** Show prev / next arrow buttons. @default true */\n readonly showArrows = input(true, { transform: coerceBooleanProperty });\n\n /** Show dot indicators below the slides. @default true */\n readonly showDots = input(true, { transform: coerceBooleanProperty });\n\n /** Auto-advance slides. @default false */\n readonly autoplay = input(false, { transform: coerceBooleanProperty });\n\n /** Autoplay interval (ms). @default 4000 */\n readonly intervalMs = input(4000, {\n transform: (v: unknown): number => Math.max(500, coerceNumberProperty(v, 4000)),\n });\n\n /** Wrap around at the ends. @default true */\n readonly loop = input(true, { transform: coerceBooleanProperty });\n\n protected readonly slides = contentChildren(WrCarouselSlide);\n protected readonly count = computed(() => this.slides().length);\n\n /** Live horizontal drag offset (px) during a touch swipe. */\n protected readonly dragX = signal(0);\n protected readonly dragging = signal(false);\n\n /** CSS transform for the track — the per-slide offset plus any live drag. */\n protected readonly trackStyle = computed(() => {\n const base = -this.active() * 100;\n const drag = this.dragX();\n return drag === 0 ? `translateX(${base}%)` : `translateX(calc(${base}% + ${drag}px))`;\n });\n\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly paused = signal(false);\n private readonly destroyRef = inject(DestroyRef);\n\n constructor() {\n effect(() => {\n if (this.timer) clearInterval(this.timer);\n this.timer = null;\n if (!this.autoplay() || this.paused() || this.count() < 2) return;\n const interval = this.intervalMs();\n this.timer = setInterval(() => this.next(), interval);\n });\n\n this.destroyRef.onDestroy(() => {\n if (this.timer) clearInterval(this.timer);\n });\n }\n\n protected onMouseEnter(): void {\n this.paused.set(true);\n }\n\n protected onMouseLeave(): void {\n this.paused.set(false);\n }\n\n // Imperative\n\n goTo(index: number): void {\n const max = this.count() - 1;\n if (max < 0) return;\n if (this.loop()) {\n const next = ((index % this.count()) + this.count()) % this.count();\n this.active.set(next);\n } else {\n this.active.set(Math.min(Math.max(0, index), max));\n }\n }\n\n next(): void {\n this.goTo(this.active() + 1);\n }\n\n prev(): void {\n this.goTo(this.active() - 1);\n }\n\n // Swipe navigation — the track follows the finger; releasing past ~20% of the\n // viewport advances a slide (left = next, right = prev), otherwise snaps back.\n\n private swipeStartX = 0;\n\n protected onSwipeStart(event: TouchEvent): void {\n const touch = event.touches[0];\n if (!touch) return;\n this.swipeStartX = touch.clientX;\n this.dragging.set(true);\n this.paused.set(true); // hold autoplay while dragging\n }\n\n protected onSwipeMove(event: TouchEvent): void {\n if (!this.dragging()) return;\n const touch = event.touches[0];\n if (!touch) return;\n this.dragX.set(touch.clientX - this.swipeStartX);\n }\n\n protected onSwipeEnd(event: TouchEvent, viewport: HTMLElement): void {\n if (!this.dragging()) return;\n this.dragging.set(false);\n const dx = this.dragX();\n this.dragX.set(0);\n this.paused.set(false);\n const threshold = (viewport.offsetWidth || 0) * 0.2;\n if (dx <= -threshold) this.next();\n else if (dx >= threshold) this.prev();\n }\n}\n","<div\n #viewport\n class=\"wr-carousel__viewport\"\n aria-roledescription=\"carousel\"\n (mouseenter)=\"onMouseEnter()\"\n (mouseleave)=\"onMouseLeave()\"\n (touchstart)=\"onSwipeStart($event)\"\n (touchmove)=\"onSwipeMove($event)\"\n (touchend)=\"onSwipeEnd($event, viewport)\"\n (touchcancel)=\"onSwipeEnd($event, viewport)\"\n>\n <div class=\"wr-carousel__track\" [style.transform]=\"trackStyle()\" [style.transition]=\"dragging() ? 'none' : null\">\n <ng-content />\n </div>\n</div>\n\n@if (showArrows() && count() > 1) {\n <button\n type=\"button\"\n class=\"wr-carousel__nav wr-carousel__nav--prev\"\n [attr.aria-label]=\"resolvedPrevLabel()\"\n (click)=\"prev()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" aria-hidden=\"true\">\n <path d=\"M9 2 L4 7 L9 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </button>\n <button\n type=\"button\"\n class=\"wr-carousel__nav wr-carousel__nav--next\"\n [attr.aria-label]=\"resolvedNextLabel()\"\n (click)=\"next()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" aria-hidden=\"true\">\n <path d=\"M5 2 L10 7 L5 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </button>\n}\n\n@if (showDots() && count() > 1) {\n <div class=\"wr-carousel__dots\" role=\"group\" [attr.aria-label]=\"resolvedPaginationLabel()\">\n @for (slide of slides(); track $index) {\n <button\n type=\"button\"\n class=\"wr-carousel__dot\"\n [class.wr-carousel__dot--active]=\"$index === active()\"\n [attr.aria-current]=\"$index === active() ? 'true' : null\"\n [attr.aria-label]=\"`Go to slide ${$index + 1}`\"\n (click)=\"goTo($index)\"\n ></button>\n }\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngwr-carousel.mjs","sources":["../../../projects/lib/carousel/carousel-slide.ts","../../../projects/lib/carousel/carousel.ts","../../../projects/lib/carousel/carousel.html","../../../projects/lib/carousel/ngwr-carousel.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Component, ViewEncapsulation } from '@angular/core';\n\n/**\n * One slide in a {@link WrCarousel}. Holds whatever content you\n * project — image, card, video, anything.\n */\n@Component({\n selector: 'wr-carousel-slide',\n template: '<ng-content />',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-carousel-slide', role: 'group', 'aria-roledescription': 'slide' },\n})\nexport class WrCarouselSlide {}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directionality } from '@angular/cdk/bidi';\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n PLATFORM_ID,\n ViewEncapsulation,\n computed,\n contentChildren,\n effect,\n inject,\n input,\n model,\n signal,\n} from '@angular/core';\n\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\n\nimport { WrCarouselSlide } from './carousel-slide';\n\n/**\n * Slide carousel. Project `<wr-carousel-slide>` children — the carousel\n * snaps between them with prev/next buttons and optional dots / autoplay.\n *\n * @example\n * ```html\n * <wr-carousel [(active)]=\"i\" autoplay>\n * <wr-carousel-slide><img src=\"a.jpg\" /></wr-carousel-slide>\n * <wr-carousel-slide><img src=\"b.jpg\" /></wr-carousel-slide>\n * <wr-carousel-slide><img src=\"c.jpg\" /></wr-carousel-slide>\n * </wr-carousel>\n * ```\n *\n * @see https://ngwr.dev/reference/components/carousel\n */\n@Component({\n selector: 'wr-carousel',\n templateUrl: './carousel.html',\n encapsulation: ViewEncapsulation.None,\n // On the HOST, not the viewport: the arrows and dots are the viewport's siblings, so\n // viewport-scoped listeners let a slide change under a cursor aiming at an arrow.\n // `focusin` / `focusout` are the keyboard half — WCAG 2.2.2 wants a way to stop\n // moving content, and hovering is not one for someone who never uses a mouse.\n host: {\n class: 'wr-carousel',\n '(mouseenter)': 'onPauseIn()',\n '(mouseleave)': 'onPauseOut()',\n '(focusin)': 'onPauseIn()',\n '(focusout)': 'onPauseOut()',\n },\n})\nexport class WrCarousel {\n /** Accessible name of the previous-slide button. Falls back to `carousel.prev`. */\n readonly prevLabel = input<string | null>(null);\n\n /** Accessible name of the next-slide button. Falls back to `carousel.next`. */\n readonly nextLabel = input<string | null>(null);\n\n /** Accessible name of the dot group. Falls back to `carousel.pagination`. */\n readonly paginationLabel = input<string | null>(null);\n\n protected readonly resolvedPrevLabel = useI18nText(this.prevLabel, 'carousel.prev', 'Previous slide');\n protected readonly resolvedNextLabel = useI18nText(this.nextLabel, 'carousel.next', 'Next slide');\n protected readonly resolvedPaginationLabel = useI18nText(\n this.paginationLabel,\n 'carousel.pagination',\n 'Carousel pagination'\n );\n\n /** Accessible name of the carousel itself. Falls back to `carousel.label`. */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'carousel.label', 'Carousel');\n\n // The three labels above route through the catalog; this one was a hard-coded\n // English template, so a localized app got two languages in one pagination strip.\n protected readonly slideLabel = useI18nFormatter('carousel.goToSlide', 'Go to slide {{index}}');\n\n /** Active slide index. Two-way bindable. @default 0 */\n readonly active = model(0);\n\n /** Show prev / next arrow buttons. @default true */\n readonly showArrows = input(true, { transform: coerceBooleanProperty });\n\n /** Show dot indicators below the slides. @default true */\n readonly showDots = input(true, { transform: coerceBooleanProperty });\n\n /** Auto-advance slides. @default false */\n readonly autoplay = input(false, { transform: coerceBooleanProperty });\n\n /** Autoplay interval (ms). @default 4000 */\n readonly intervalMs = input(4000, {\n transform: (v: unknown): number => Math.max(500, coerceNumberProperty(v, 4000)),\n });\n\n /** Wrap around at the ends. @default true */\n readonly loop = input(true, { transform: coerceBooleanProperty });\n\n protected readonly slides = contentChildren(WrCarouselSlide);\n protected readonly count = computed(() => this.slides().length);\n\n /** Live horizontal drag offset (px) during a touch swipe. */\n protected readonly dragX = signal(0);\n protected readonly dragging = signal(false);\n\n private readonly dir = inject(Directionality, { optional: true });\n\n /**\n * Reading direction of the track. `Directionality` is root-provided, so this\n * always resolves — `optional` only guards a consumer who has deliberately\n * torn the provider out. It reads the document once at construction; a\n * subtree that overrides the direction does it with the CDK's `Dir`\n * directive, which writes `valueSignal`, so `trackStyle` re-renders instead\n * of leaving the track parked on the old side.\n */\n private readonly isRtl = computed(() => this.dir?.valueSignal() === 'rtl');\n\n /** CSS transform for the track — the per-slide offset plus any live drag. */\n protected readonly trackStyle = computed(() => {\n // `translateX` is PHYSICAL while the slides are laid out on the inline axis:\n // under `dir=\"rtl\"` the flex track runs right-to-left, so slide 1 sits to the\n // LEFT of slide 0 and reaching it means moving the track the other way. Left\n // unsigned, every RTL carousel translated itself off into blank space.\n const base = (this.isRtl() ? 1 : -1) * this.active() * 100;\n // The drag stays physical on purpose: it is the finger's own displacement,\n // and the track follows the finger in both directions.\n const drag = this.dragX();\n return drag === 0 ? `translateX(${base}%)` : `translateX(calc(${base}% + ${drag}px))`;\n });\n\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly paused = signal(false);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n constructor() {\n effect(() => {\n if (this.timer) clearInterval(this.timer);\n this.timer = null;\n // `isBrowser` first: without it the prerender ran the timer too, doing work\n // nobody will ever see on a slide index that then gets serialized.\n if (!this.isBrowser || !this.autoplay() || this.paused() || this.count() < 2) return;\n const interval = this.intervalMs();\n this.timer = setInterval(() => this.next(), interval);\n });\n\n // `active` is a plain `model`, so `[(active)]` and a shrinking slide list both\n // write into it unchecked — a filtered list left it pointing past the end,\n // translating the track into blank space with no dot lit.\n effect(() => {\n const max = this.count() - 1;\n if (max < 0) return;\n const clamped = Math.min(Math.max(0, this.active()), max);\n if (clamped !== this.active()) this.active.set(clamped);\n });\n\n this.destroyRef.onDestroy(() => {\n if (this.timer) clearInterval(this.timer);\n });\n }\n\n protected onPauseIn(): void {\n this.paused.set(true);\n }\n\n protected onPauseOut(): void {\n this.paused.set(false);\n }\n\n // Imperative\n\n goTo(index: number): void {\n const max = this.count() - 1;\n if (max < 0) return;\n if (this.loop()) {\n const next = ((index % this.count()) + this.count()) % this.count();\n this.active.set(next);\n } else {\n this.active.set(Math.min(Math.max(0, index), max));\n }\n }\n\n next(): void {\n this.goTo(this.active() + 1);\n }\n\n prev(): void {\n this.goTo(this.active() - 1);\n }\n\n // Swipe navigation — the track follows the finger; releasing past ~20% of the\n // viewport advances a slide, otherwise snaps back. Which way that is follows\n // the reading direction: dragging toward the inline start (left in LTR, right\n // in RTL) pulls the next slide into view.\n\n private swipeStartX = 0;\n\n protected onSwipeStart(event: TouchEvent): void {\n const touch = event.touches[0];\n if (!touch) return;\n this.swipeStartX = touch.clientX;\n this.dragging.set(true);\n this.paused.set(true); // hold autoplay while dragging\n }\n\n protected onSwipeMove(event: TouchEvent): void {\n if (!this.dragging()) return;\n const touch = event.touches[0];\n if (!touch) return;\n this.dragX.set(touch.clientX - this.swipeStartX);\n }\n\n protected onSwipeEnd(event: TouchEvent, viewport: HTMLElement): void {\n if (!this.dragging()) return;\n this.dragging.set(false);\n const dx = this.dragX();\n this.dragX.set(0);\n this.paused.set(false);\n const threshold = (viewport.offsetWidth || 0) * 0.2;\n // `dx` is a physical delta. The next slide sits to the physical RIGHT in LTR\n // and to the LEFT in RTL, so the drag that pulls it into view — and with it\n // the sign that advances — turns around with the direction. The buttons keep\n // their semantics either way; only the gesture is physical.\n const advance = this.isRtl() ? dx >= threshold : dx <= -threshold;\n const retreat = this.isRtl() ? dx <= -threshold : dx >= threshold;\n if (advance) this.next();\n else if (retreat) this.prev();\n }\n}\n","<div\n #viewport\n class=\"wr-carousel__viewport\"\n role=\"group\"\n aria-roledescription=\"carousel\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n (touchstart)=\"onSwipeStart($event)\"\n (touchmove)=\"onSwipeMove($event)\"\n (touchend)=\"onSwipeEnd($event, viewport)\"\n (touchcancel)=\"onSwipeEnd($event, viewport)\"\n>\n <div class=\"wr-carousel__track\" [style.transform]=\"trackStyle()\" [style.transition]=\"dragging() ? 'none' : null\">\n <ng-content />\n </div>\n</div>\n\n@if (showArrows() && count() > 1) {\n <button\n type=\"button\"\n class=\"wr-carousel__nav wr-carousel__nav--prev\"\n [attr.aria-label]=\"resolvedPrevLabel()\"\n (click)=\"prev()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" aria-hidden=\"true\">\n <path d=\"M9 2 L4 7 L9 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </button>\n <button\n type=\"button\"\n class=\"wr-carousel__nav wr-carousel__nav--next\"\n [attr.aria-label]=\"resolvedNextLabel()\"\n (click)=\"next()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" aria-hidden=\"true\">\n <path d=\"M5 2 L10 7 L5 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </button>\n}\n\n@if (showDots() && count() > 1) {\n <div class=\"wr-carousel__dots\" role=\"group\" [attr.aria-label]=\"resolvedPaginationLabel()\">\n @for (slide of slides(); track $index) {\n <button\n type=\"button\"\n class=\"wr-carousel__dot\"\n [class.wr-carousel__dot--active]=\"$index === active()\"\n [attr.aria-current]=\"$index === active() ? 'true' : null\"\n [attr.aria-label]=\"slideLabel({ index: $index + 1 })\"\n (click)=\"goTo($index)\"\n ></button>\n }\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,534 @@
1
+ import { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';
2
+
3
+ /**
4
+ * @license
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
8
+ */
9
+ /**
10
+ * Test harness for one option inside a `<wr-cascader>` column.
11
+ *
12
+ * An option is either a BRANCH (it has children, so clicking it opens the next
13
+ * column) or a LEAF (clicking it commits the whole path and closes the panel).
14
+ * {@link hasChildren} is the only way to tell them apart, and it reads the
15
+ * chevron the template draws for branches — the option carries no
16
+ * `aria-haspopup` / `aria-expanded`, so a screen-reader user is told nothing
17
+ * about a branch either. Reported here rather than papered over.
18
+ *
19
+ * @see https://ngwr.dev/guides/testing
20
+ */
21
+ class WrCascaderOptionHarness extends ComponentHarness {
22
+ /** The `<li role="menuitem">` a column renders per option. */
23
+ static hostSelector = '.wr-cascader__opt';
24
+ /** Build a predicate that narrows the query. */
25
+ static with(options = {}) {
26
+ return new HarnessPredicate(WrCascaderOptionHarness, options)
27
+ .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))
28
+ .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)
29
+ .addOption('active', options.active, async (harness, active) => (await harness.isActive()) === active)
30
+ .addOption('hasChildren', options.hasChildren, async (harness, hasChildren) => (await harness.hasChildren()) === hasChildren);
31
+ }
32
+ /** The option's label, trimmed. The branch chevron contributes no text. */
33
+ async getText() {
34
+ return (await this.locatorFor('.wr-cascader__opt-label')()).text();
35
+ }
36
+ /** The role the option announces — `menuitem`. */
37
+ async getRole() {
38
+ return (await this.host()).getAttribute('role');
39
+ }
40
+ /** Whether the option refuses selection, from the state a screen reader is given. */
41
+ async isDisabled() {
42
+ return (await (await this.host()).getAttribute('aria-disabled')) === 'true';
43
+ }
44
+ /**
45
+ * Whether this is the option its column is currently drilled into — the one
46
+ * whose children the column to the right is showing, or the committed segment
47
+ * at this level.
48
+ *
49
+ * Read from the `--active` modifier because nothing else says it: the option
50
+ * has no `aria-selected` and no `aria-expanded`, so the class is both the
51
+ * whole visual answer and the only one available.
52
+ */
53
+ async isActive() {
54
+ return (await this.host()).hasClass('wr-cascader__opt--active');
55
+ }
56
+ /** Whether the option opens a deeper level rather than ending the path. */
57
+ async hasChildren() {
58
+ return (await this.locatorForOptional('.wr-cascader__opt-arrow')()) !== null;
59
+ }
60
+ /**
61
+ * The option's tab index — `0` for every enabled option, `-1` for a disabled
62
+ * one.
63
+ *
64
+ * Worth asking: a cascader column is NOT a roving-cursor listbox. Every
65
+ * enabled option is its own tab stop, in every column, which is the documented
66
+ * reason virtual scrolling is deferred for this component — there is no
67
+ * container-owned arrow-nav model to hang a window off.
68
+ *
69
+ * Read as the element's `tabIndex` PROPERTY rather than the attribute, so an
70
+ * option that carried no `tabindex` at all answers `-1` — what the DOM says of a
71
+ * bare `<li>` — instead of a made-up `0` that would report an unfocusable option
72
+ * as a tab stop if this component ever moved to a roving cursor.
73
+ */
74
+ async getTabIndex() {
75
+ return (await this.host()).getProperty('tabIndex');
76
+ }
77
+ /**
78
+ * Click the option: a branch opens its children to the right, a leaf commits
79
+ * the path and closes the panel.
80
+ *
81
+ * A disabled option is clickable here on purpose — the component refuses it in
82
+ * its own handler rather than through `pointer-events`, so the click a spec
83
+ * dispatches is exactly as ineffective as one in a browser.
84
+ */
85
+ async click() {
86
+ return (await this.host()).click();
87
+ }
88
+ /**
89
+ * Activate the option from the keyboard (Enter; Space is bound to the same
90
+ * handler).
91
+ *
92
+ * This is the component's entire keyboard model — the columns bind
93
+ * `keydown.enter` / `keydown.space` per option and nothing else, so there are
94
+ * no arrow keys to walk levels with. A keyboard user reaches the option they
95
+ * want with Tab and presses Enter — and Tab is a long way round: the panel is a
96
+ * portal in the overlay container at the end of the document, and nothing moves
97
+ * focus into it on open, so the first option is not the next stop after the
98
+ * trigger.
99
+ */
100
+ async selectByKeyboard() {
101
+ return (await this.host()).sendKeys(TestKey.ENTER);
102
+ }
103
+ /**
104
+ * Move the pointer onto the option.
105
+ *
106
+ * Deliberately does NOT expand a branch: this cascader drills down on CLICK
107
+ * only, unlike the hover-to-expand cascaders elsewhere. Kept because a spec
108
+ * may want to pin that, and because the option's hover tint is styled.
109
+ */
110
+ async hover() {
111
+ return (await this.host()).hover();
112
+ }
113
+ /** Move keyboard focus to the option. */
114
+ async focus() {
115
+ return (await this.host()).focus();
116
+ }
117
+ /** Whether the option holds keyboard focus. */
118
+ async isFocused() {
119
+ return (await this.host()).isFocused();
120
+ }
121
+ }
122
+
123
+ /**
124
+ * @license
125
+ *
126
+ * Use of this source code is governed by an MIT-style license that can be
127
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
128
+ */
129
+ /**
130
+ * Test harness for one COLUMN of an open `<wr-cascader>` panel.
131
+ *
132
+ * A column is a level of the tree: column 0 holds the root options, and each
133
+ * further column holds the children of the active option in the column before
134
+ * it. Which columns exist is therefore a function of what is expanded — the
135
+ * relationship this harness exists to let a spec assert. Column 0 is always
136
+ * there; a column only appears once there are children to put in it, so a leaf
137
+ * adds none.
138
+ *
139
+ * @example
140
+ * ```ts
141
+ * const [countries, cities] = await cascader.getColumns();
142
+ *
143
+ * expect(await countries.getActiveOptionText()).toBe('Germany');
144
+ * expect(await cities.getOptionLabels()).toEqual(['Berlin']);
145
+ * ```
146
+ *
147
+ * @see https://ngwr.dev/guides/testing
148
+ */
149
+ class WrCascaderColumnHarness extends ComponentHarness {
150
+ /** The `<ul role="menu">` the panel renders per level. */
151
+ static hostSelector = '.wr-cascader__col';
152
+ /** Build a predicate that narrows the query. */
153
+ static with(options = {}) {
154
+ return new HarnessPredicate(WrCascaderColumnHarness, options).addOption('optionText', options.optionText, async (harness, text) => {
155
+ for (const label of await harness.getOptionLabels()) {
156
+ if (await HarnessPredicate.stringMatches(label, text))
157
+ return true;
158
+ }
159
+ return false;
160
+ });
161
+ }
162
+ /** The role the column announces — `menu`. */
163
+ async getRole() {
164
+ return (await this.host()).getAttribute('role');
165
+ }
166
+ /** The options this level offers, in order. */
167
+ async getOptions(filters = {}) {
168
+ return this.locatorForAll(WrCascaderOptionHarness.with(filters))();
169
+ }
170
+ /** The labels this level offers, in order. */
171
+ async getOptionLabels() {
172
+ const options = await this.getOptions();
173
+ return Promise.all(options.map(option => option.getText()));
174
+ }
175
+ /**
176
+ * The first option matching the filters.
177
+ *
178
+ * Throws rather than answering `null`, and names what the column does offer:
179
+ * a missing option here almost always means the level is not the one the spec
180
+ * thought it was, and that is far easier to see with the alternatives listed.
181
+ */
182
+ async getOption(filters) {
183
+ const [option] = await this.getOptions(filters);
184
+ if (!option) {
185
+ throw new Error(`WrCascaderColumnHarness.getOption(): no option matched ${JSON.stringify(filters)}. ` +
186
+ `This column offers: ${(await this.getOptionLabels()).join(', ')}.`);
187
+ }
188
+ return option;
189
+ }
190
+ /** The option this level is drilled into, or `null` when nothing here is expanded. */
191
+ async getActiveOption() {
192
+ const [active] = await this.getOptions({ active: true });
193
+ return active ?? null;
194
+ }
195
+ /** The label of the option this level is drilled into, or `null`. */
196
+ async getActiveOptionText() {
197
+ const active = await this.getActiveOption();
198
+ return active ? active.getText() : null;
199
+ }
200
+ }
201
+
202
+ /**
203
+ * @license
204
+ *
205
+ * Use of this source code is governed by an MIT-style license that can be
206
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
207
+ */
208
+ /**
209
+ * Test harness for `<wr-cascader>` — the trigger, and the panel of COLUMNS it
210
+ * opens. Root of a small family: {@link WrCascaderColumnHarness} for one level,
211
+ * `WrCascaderOptionHarness` for one option in it.
212
+ *
213
+ * A cascader is not a select with extra steps. Its value is the whole PATH from
214
+ * root to leaf (`['eu', 'de', 'ber']`, not `'ber'`), and the panel shows one
215
+ * column per level, so which columns exist depends on what is expanded — column
216
+ * 0 is the roots, and every further column holds the children of the active
217
+ * option in the column to its left. That relationship is the component, so it is
218
+ * what {@link getColumns} and {@link getColumnLabels} are for.
219
+ *
220
+ * The panel is NOT inside the cascader: it is a template portal in the overlay
221
+ * container, a sibling of the whole app. Every read of it goes through the
222
+ * document root scoped by the `aria-controls` id the trigger publishes, so two
223
+ * cascaders on one page can never answer with each other's columns.
224
+ *
225
+ * @example
226
+ * ```ts
227
+ * const cascader = await loader.getHarness(WrCascaderHarness);
228
+ *
229
+ * await cascader.selectPath(['Europe', 'Germany', 'Berlin']);
230
+ *
231
+ * expect(await cascader.getValueText()).toBe('Europe / Germany / Berlin');
232
+ * expect(await cascader.isOpen()).toBe(false);
233
+ * ```
234
+ *
235
+ * @see https://ngwr.dev/guides/testing
236
+ */
237
+ class WrCascaderHarness extends ComponentHarness {
238
+ static hostSelector = 'wr-cascader';
239
+ /** Build a predicate that narrows the query. */
240
+ static with(options = {}) {
241
+ return new HarnessPredicate(WrCascaderHarness, options)
242
+ .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getValueText(), text))
243
+ .addOption('placeholder', options.placeholder, (harness, placeholder) => HarnessPredicate.stringMatches(harness.getPlaceholder(), placeholder))
244
+ .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)
245
+ .addOption('open', options.open, async (harness, open) => (await harness.isOpen()) === open);
246
+ }
247
+ trigger = this.locatorFor('.wr-cascader__trigger');
248
+ /**
249
+ * Whether the panel is showing.
250
+ *
251
+ * From the trigger's `aria-expanded` rather than the host's `--open` class:
252
+ * both exist, and the ARIA state is the one a screen-reader user is told.
253
+ */
254
+ async isOpen() {
255
+ return (await (await this.trigger()).getAttribute('aria-expanded')) === 'true';
256
+ }
257
+ /**
258
+ * Whether the cascader refuses interaction.
259
+ *
260
+ * From the trigger's native `disabled`, which is what actually stops a pointer
261
+ * and what assistive tech reports; the host's `--disabled` class only mirrors
262
+ * it for styling.
263
+ */
264
+ async isDisabled() {
265
+ return (await this.trigger()).getProperty('disabled');
266
+ }
267
+ /**
268
+ * What the trigger displays as the selection: the labels of the whole path
269
+ * joined by the `separator` (`'Europe / Germany / Berlin'` by default), or `''`
270
+ * while nothing is selected and the placeholder is showing.
271
+ *
272
+ * The joined string is all the DOM has — the separator is not published
273
+ * anywhere on its own, so the harness will not pretend it can split the path
274
+ * back apart. Assert against the bound value, or against
275
+ * {@link getActiveTrail} while the panel is open, when the segments matter.
276
+ */
277
+ async getValueText() {
278
+ const value = await this.locatorForOptional('.wr-cascader__value')();
279
+ return value ? value.text() : '';
280
+ }
281
+ /**
282
+ * The placeholder, or `null` when a selection is hiding it.
283
+ *
284
+ * `''` is a real answer, not an absence: a cascader with no `placeholder` still
285
+ * renders the element while unselected.
286
+ */
287
+ async getPlaceholder() {
288
+ const placeholder = await this.locatorForOptional('.wr-cascader__placeholder')();
289
+ return placeholder ? placeholder.text() : null;
290
+ }
291
+ /**
292
+ * The trigger's accessible name — the `ariaLabel` input, falling back to the
293
+ * placeholder and then to the i18n catalog, because a `role="combobox"` with
294
+ * nothing selected and no placeholder would otherwise have no name at all.
295
+ */
296
+ async getAccessibleName() {
297
+ return (await this.trigger()).getAttribute('aria-label');
298
+ }
299
+ /** The kind of popup the trigger promises via `aria-haspopup` — `menu`. */
300
+ async getPopupRole() {
301
+ return (await this.trigger()).getAttribute('aria-haspopup');
302
+ }
303
+ /** The role the panel announces — `menu`, matching what the trigger promised. */
304
+ async getPanelRole() {
305
+ return (await this.panel()).getAttribute('role');
306
+ }
307
+ /**
308
+ * The id the trigger publishes as `aria-controls`.
309
+ *
310
+ * Published unconditionally, open or closed — so while the panel is closed this
311
+ * id resolves to nothing in the document. Exposed so a spec can pin that
312
+ * (dangling or not) rather than have the harness quietly decide for it; every
313
+ * panel read goes through the same id but refuses to run while closed.
314
+ */
315
+ async getPanelId() {
316
+ return (await this.trigger()).getAttribute('aria-controls');
317
+ }
318
+ /**
319
+ * Whether the panel now in the overlay is the one this trigger claims to
320
+ * control — `aria-controls` resolving to a real element that carries that id.
321
+ *
322
+ * With several cascaders on a page it is also the check that the reference lands
323
+ * on THIS instance's panel rather than a neighbour's: the overlay container is
324
+ * shared, so panels sit side by side in it with nothing but their ids to tell
325
+ * them apart.
326
+ */
327
+ async isPanelWiredToTrigger() {
328
+ const rendered = await (await this.panel()).getAttribute('id');
329
+ return rendered !== null && rendered === (await this.getPanelId());
330
+ }
331
+ /**
332
+ * Open the panel.
333
+ *
334
+ * Clicks the trigger, because that is the only gesture the component binds. The
335
+ * trigger is a native `<button>`, so a browser turns Enter / Space on it into
336
+ * the same click — there is no separate keyboard route to model here, and jsdom
337
+ * does not synthesise button activation from a key, so an `openByKeyboard()`
338
+ * would only be able to lie.
339
+ */
340
+ async open() {
341
+ if (await this.isOpen())
342
+ return;
343
+ await (await this.trigger()).click();
344
+ if (await this.isOpen())
345
+ return;
346
+ throw new Error('WrCascaderHarness.open(): the panel did not open. A disabled cascader refuses the click — ' +
347
+ 'check isDisabled().');
348
+ }
349
+ /**
350
+ * Close the panel with Escape. A closed cascader is left alone.
351
+ *
352
+ * Escape reaches the panel through the CDK's keyboard dispatcher rather than
353
+ * through the DOM tree, which is why sending it to the trigger works even
354
+ * though the panel is somewhere else entirely.
355
+ */
356
+ async close() {
357
+ if (!(await this.isOpen()))
358
+ return;
359
+ await (await this.trigger()).sendKeys(TestKey.ESCAPE);
360
+ if (await this.isOpen()) {
361
+ throw new Error('WrCascaderHarness.close(): Escape did not close the panel.');
362
+ }
363
+ }
364
+ /** Click the trigger once, whatever that does — opens a closed panel, closes an open one. */
365
+ async clickTrigger() {
366
+ return (await this.trigger()).click();
367
+ }
368
+ /**
369
+ * The columns of the open panel, left to right: column 0 is the root options,
370
+ * and each further one holds the children of its neighbour's active option.
371
+ *
372
+ * Throws while the panel is closed. The columns do not exist anywhere until the
373
+ * portal is attached, and an empty array reads like a panel that rendered
374
+ * nothing — a confusing failure three lines later instead of here.
375
+ */
376
+ async getColumns(filters = {}) {
377
+ const loader = await this.panelLoader();
378
+ return loader.getAllHarnesses(WrCascaderColumnHarness.with(filters));
379
+ }
380
+ /** How many levels the panel is currently showing. */
381
+ async getColumnCount() {
382
+ return (await this.getColumns()).length;
383
+ }
384
+ /**
385
+ * One column by its 0-based level. Throws when the level is not showing, which
386
+ * is the interesting failure: it means the option before it has no children, or
387
+ * has not been expanded yet.
388
+ */
389
+ async getColumn(index) {
390
+ const columns = await this.getColumns();
391
+ const column = columns[index];
392
+ if (!column) {
393
+ throw new Error(`WrCascaderHarness.getColumn(): no column at level ${index} — the panel is showing ` +
394
+ `${columns.length}. A deeper column appears only once a parent with children is expanded.`);
395
+ }
396
+ return column;
397
+ }
398
+ /** The labels offered by every column, outer array left to right. */
399
+ async getColumnLabels() {
400
+ const columns = await this.getColumns();
401
+ return Promise.all(columns.map(column => column.getOptionLabels()));
402
+ }
403
+ /**
404
+ * The expanded trail — the label of the active option in each column, root
405
+ * first.
406
+ *
407
+ * This is the panel's own idea of where the user is, which is NOT always the
408
+ * committed value: drilling into a branch moves the trail without committing
409
+ * anything unless `changeOnSelect` is on. Once a leaf is picked the two agree,
410
+ * and this is the only place the path's segments exist separately in the DOM.
411
+ */
412
+ async getActiveTrail() {
413
+ const trail = [];
414
+ for (const column of await this.getColumns()) {
415
+ const active = await column.getActiveOptionText();
416
+ if (active !== null)
417
+ trail.push(active);
418
+ }
419
+ return trail;
420
+ }
421
+ /**
422
+ * The first option matching the filters, anywhere in the panel. Throws when
423
+ * nothing matches, naming what is on offer.
424
+ *
425
+ * Use {@link getColumn} when the level matters — the same label can legitimately
426
+ * appear at more than one level.
427
+ */
428
+ async getOption(filters) {
429
+ for (const column of await this.getColumns()) {
430
+ const [option] = await column.getOptions(filters);
431
+ if (option)
432
+ return option;
433
+ }
434
+ throw new Error(`WrCascaderHarness.getOption(): no option matched ${JSON.stringify(filters)}. ` +
435
+ `The panel offers: ${(await this.getColumnLabels()).map(labels => labels.join(', ')).join(' | ')}.`);
436
+ }
437
+ /**
438
+ * Walk a path by label, opening the panel first if needed: each label is
439
+ * clicked in the column it belongs to, so `['Europe', 'Germany', 'Berlin']`
440
+ * drills two levels and commits the third.
441
+ *
442
+ * Clicking is the only way down — this cascader does not expand on hover, so
443
+ * neither does the harness. A path that ends on a BRANCH just leaves that
444
+ * branch expanded: the component commits nothing on the way down unless
445
+ * `changeOnSelect` is on, and only a leaf closes the panel.
446
+ */
447
+ async selectPath(labels) {
448
+ if (labels.length === 0) {
449
+ throw new Error('WrCascaderHarness.selectPath(): the path is empty. Pass at least one label, or call clear() ' +
450
+ 'to unset the selection.');
451
+ }
452
+ await this.open();
453
+ for (let level = 0; level < labels.length; level++) {
454
+ const label = labels[level];
455
+ const columns = await this.getColumns();
456
+ const column = columns[level];
457
+ if (!column) {
458
+ throw new Error(`WrCascaderHarness.selectPath(): "${label}" would be at level ${level}, but the panel is ` +
459
+ `showing ${columns.length} column(s) — the step before it opened no deeper level.`);
460
+ }
461
+ const option = await column.getOption({ text: label });
462
+ if (await option.isDisabled()) {
463
+ throw new Error(`WrCascaderHarness.selectPath(): "${label}" is disabled, so no path can pass through it.`);
464
+ }
465
+ const isLast = level === labels.length - 1;
466
+ if (!isLast && !(await option.hasChildren())) {
467
+ throw new Error(`WrCascaderHarness.selectPath(): "${label}" is a leaf, so the path cannot continue to ` +
468
+ `"${labels[level + 1]}" — picking it commits and closes the panel.`);
469
+ }
470
+ await option.click();
471
+ }
472
+ }
473
+ /**
474
+ * Click the clear (×) control on the trigger.
475
+ *
476
+ * Throws when there is none, and both reasons are worth failing on: the
477
+ * cascader is not `clearable`, or nothing is selected — the control is not
478
+ * rendered at all in either case (nor while disabled).
479
+ */
480
+ async clear() {
481
+ const clear = await this.locatorForOptional('.wr-cascader__clear')();
482
+ if (!clear) {
483
+ throw new Error('WrCascaderHarness.clear(): this cascader shows no clear control — it is rendered only when ' +
484
+ '`clearable` is on, something is selected, and the control is enabled.');
485
+ }
486
+ await clear.click();
487
+ }
488
+ /** Move keyboard focus to the trigger. */
489
+ async focus() {
490
+ return (await this.trigger()).focus();
491
+ }
492
+ /** Take focus off the trigger, which is what makes a bound form field touched. */
493
+ async blur() {
494
+ return (await this.trigger()).blur();
495
+ }
496
+ /** Whether the trigger holds keyboard focus. */
497
+ async isFocused() {
498
+ return (await this.trigger()).isFocused();
499
+ }
500
+ /** This cascader's panel element in the overlay — the single-element scoped read. */
501
+ async panel() {
502
+ return this.documentRootLocatorFactory().locatorFor(`#${await this.panelId()}`)();
503
+ }
504
+ /**
505
+ * A loader scoped to THIS cascader's panel — the list scoped read.
506
+ *
507
+ * Scoped by the published id rather than by `.wr-cascader-panel`: the overlay
508
+ * container is shared with every other overlay in the app, so a bare class
509
+ * query would answer with whichever panel happened to be open.
510
+ */
511
+ async panelLoader() {
512
+ return this.documentRootLocatorFactory().harnessLoaderFor(`#${await this.panelId()}`);
513
+ }
514
+ /** The panel id, refusing to hand it out while there is no panel to find. */
515
+ async panelId() {
516
+ if (!(await this.isOpen())) {
517
+ throw new Error('WrCascaderHarness: the panel is closed, so there are no columns to read — call open() or ' +
518
+ 'selectPath() first. The trigger publishes `aria-controls` even while closed, so the id ' +
519
+ 'alone is not proof the panel exists.');
520
+ }
521
+ const id = await this.getPanelId();
522
+ if (!id) {
523
+ throw new Error('WrCascaderHarness: the trigger publishes no `aria-controls`, so its panel cannot be found.');
524
+ }
525
+ return id;
526
+ }
527
+ }
528
+
529
+ /**
530
+ * Generated bundle index. Do not edit.
531
+ */
532
+
533
+ export { WrCascaderColumnHarness, WrCascaderHarness, WrCascaderOptionHarness };
534
+ //# sourceMappingURL=ngwr-cascader-testing.mjs.map