ngwr 10.2.1 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) hide show
  1. package/README.md +39 -19
  2. package/anchor/styles/_index.scss +4 -4
  3. package/back-top/styles/_index.scss +6 -1
  4. package/blur-text/styles/_index.scss +13 -0
  5. package/button/styles/_index.scss +11 -6
  6. package/carousel/styles/_index.scss +13 -2
  7. package/cascader/styles/_index.scss +2 -2
  8. package/circular-text/styles/_index.scss +2 -0
  9. package/collapse/styles/_index.scss +1 -1
  10. package/color-picker/styles/_index.scss +6 -1
  11. package/compare/styles/_index.scss +1 -2
  12. package/context-menu/styles/_index.scss +6 -1
  13. package/descriptions/styles/_index.scss +2 -2
  14. package/dialog/styles/_index.scss +7 -0
  15. package/drawer/styles/_index.scss +20 -1
  16. package/dropdown/styles/_index.scss +19 -5
  17. package/empty/styles/_index.scss +10 -0
  18. package/fesm2022/ngwr-action-sheet.mjs +13 -3
  19. package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
  20. package/fesm2022/ngwr-affix.mjs +40 -13
  21. package/fesm2022/ngwr-affix.mjs.map +1 -1
  22. package/fesm2022/ngwr-anchor.mjs +18 -6
  23. package/fesm2022/ngwr-anchor.mjs.map +1 -1
  24. package/fesm2022/ngwr-aurora.mjs +2 -2
  25. package/fesm2022/ngwr-aurora.mjs.map +1 -1
  26. package/fesm2022/ngwr-avatar.mjs +31 -7
  27. package/fesm2022/ngwr-avatar.mjs.map +1 -1
  28. package/fesm2022/ngwr-back-top.mjs +6 -2
  29. package/fesm2022/ngwr-back-top.mjs.map +1 -1
  30. package/fesm2022/ngwr-badge.mjs +1 -1
  31. package/fesm2022/ngwr-badge.mjs.map +1 -1
  32. package/fesm2022/ngwr-bar-chart.mjs +30 -9
  33. package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
  34. package/fesm2022/ngwr-blur-text.mjs +2 -2
  35. package/fesm2022/ngwr-blur-text.mjs.map +1 -1
  36. package/fesm2022/ngwr-border-glow.mjs +2 -2
  37. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  38. package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
  39. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  40. package/fesm2022/ngwr-burger.mjs +9 -4
  41. package/fesm2022/ngwr-burger.mjs.map +1 -1
  42. package/fesm2022/ngwr-button-testing.mjs +96 -0
  43. package/fesm2022/ngwr-button-testing.mjs.map +1 -0
  44. package/fesm2022/ngwr-button.mjs +31 -14
  45. package/fesm2022/ngwr-button.mjs.map +1 -1
  46. package/fesm2022/ngwr-calendar-heatmap.mjs +40 -8
  47. package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
  48. package/fesm2022/ngwr-calendar.mjs +20 -1
  49. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  50. package/fesm2022/ngwr-card.mjs +2 -2
  51. package/fesm2022/ngwr-card.mjs.map +1 -1
  52. package/fesm2022/ngwr-carousel-testing.mjs +377 -0
  53. package/fesm2022/ngwr-carousel-testing.mjs.map +1 -0
  54. package/fesm2022/ngwr-carousel.mjs +67 -13
  55. package/fesm2022/ngwr-carousel.mjs.map +1 -1
  56. package/fesm2022/ngwr-cascader-testing.mjs +534 -0
  57. package/fesm2022/ngwr-cascader-testing.mjs.map +1 -0
  58. package/fesm2022/ngwr-cascader.mjs +2 -2
  59. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  60. package/fesm2022/ngwr-checkbox-testing.mjs +90 -0
  61. package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -0
  62. package/fesm2022/ngwr-checkbox.mjs +9 -3
  63. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  64. package/fesm2022/ngwr-circular-text.mjs +2 -2
  65. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  66. package/fesm2022/ngwr-click-spark.mjs +2 -2
  67. package/fesm2022/ngwr-click-spark.mjs.map +1 -1
  68. package/fesm2022/ngwr-collapse-testing.mjs +368 -0
  69. package/fesm2022/ngwr-collapse-testing.mjs.map +1 -0
  70. package/fesm2022/ngwr-color-picker.mjs +134 -14
  71. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  72. package/fesm2022/ngwr-command-palette-testing.mjs +589 -0
  73. package/fesm2022/ngwr-command-palette-testing.mjs.map +1 -0
  74. package/fesm2022/ngwr-command-palette.mjs +58 -8
  75. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  76. package/fesm2022/ngwr-compare.mjs +103 -13
  77. package/fesm2022/ngwr-compare.mjs.map +1 -1
  78. package/fesm2022/ngwr-config.mjs +106 -0
  79. package/fesm2022/ngwr-config.mjs.map +1 -0
  80. package/fesm2022/ngwr-context-menu-testing.mjs +631 -0
  81. package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -0
  82. package/fesm2022/ngwr-context-menu.mjs +94 -8
  83. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  84. package/fesm2022/ngwr-cookie.mjs +5 -1
  85. package/fesm2022/ngwr-cookie.mjs.map +1 -1
  86. package/fesm2022/ngwr-counter.mjs +11 -3
  87. package/fesm2022/ngwr-counter.mjs.map +1 -1
  88. package/fesm2022/ngwr-date-adapter-luxon.mjs +52 -4
  89. package/fesm2022/ngwr-date-adapter-luxon.mjs.map +1 -1
  90. package/fesm2022/ngwr-date-adapter.mjs +54 -8
  91. package/fesm2022/ngwr-date-adapter.mjs.map +1 -1
  92. package/fesm2022/ngwr-date-picker-testing.mjs +766 -0
  93. package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -0
  94. package/fesm2022/ngwr-date-picker.mjs +73 -3
  95. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  96. package/fesm2022/ngwr-decrypt-text.mjs +27 -9
  97. package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
  98. package/fesm2022/ngwr-dialog-testing.mjs +89 -0
  99. package/fesm2022/ngwr-dialog-testing.mjs.map +1 -0
  100. package/fesm2022/ngwr-directives.mjs +36 -12
  101. package/fesm2022/ngwr-directives.mjs.map +1 -1
  102. package/fesm2022/ngwr-donut-chart.mjs +22 -5
  103. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  104. package/fesm2022/ngwr-drag-drop.mjs +2 -2
  105. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  106. package/fesm2022/ngwr-drawer-testing.mjs +250 -0
  107. package/fesm2022/ngwr-drawer-testing.mjs.map +1 -0
  108. package/fesm2022/ngwr-dropdown-testing.mjs +291 -0
  109. package/fesm2022/ngwr-dropdown-testing.mjs.map +1 -0
  110. package/fesm2022/ngwr-dropdown.mjs +10 -2
  111. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  112. package/fesm2022/ngwr-empty.mjs +24 -7
  113. package/fesm2022/ngwr-empty.mjs.map +1 -1
  114. package/fesm2022/ngwr-event-calendar.mjs +57 -10
  115. package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
  116. package/fesm2022/ngwr-falling-text.mjs +2 -2
  117. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  118. package/fesm2022/ngwr-file-upload-testing.mjs +332 -0
  119. package/fesm2022/ngwr-file-upload-testing.mjs.map +1 -0
  120. package/fesm2022/ngwr-form-testing.mjs +451 -0
  121. package/fesm2022/ngwr-form-testing.mjs.map +1 -0
  122. package/fesm2022/ngwr-form.mjs +19 -3
  123. package/fesm2022/ngwr-form.mjs.map +1 -1
  124. package/fesm2022/ngwr-fuzzy-text.mjs +9 -2
  125. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  126. package/fesm2022/ngwr-gauge.mjs +19 -5
  127. package/fesm2022/ngwr-gauge.mjs.map +1 -1
  128. package/fesm2022/ngwr-glitch-text.mjs +2 -2
  129. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  130. package/fesm2022/ngwr-gradient-text.mjs +2 -2
  131. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  132. package/fesm2022/ngwr-i18n-en.mjs +50 -0
  133. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  134. package/fesm2022/ngwr-i18n-ru.mjs +48 -0
  135. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  136. package/fesm2022/ngwr-image-cropper.mjs +23 -0
  137. package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
  138. package/fesm2022/ngwr-input-number-testing.mjs +306 -0
  139. package/fesm2022/ngwr-input-number-testing.mjs.map +1 -0
  140. package/fesm2022/ngwr-input-number.mjs +35 -3
  141. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  142. package/fesm2022/ngwr-input-otp-testing.mjs +419 -0
  143. package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -0
  144. package/fesm2022/ngwr-input-otp.mjs +36 -5
  145. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  146. package/fesm2022/ngwr-input-testing.mjs +102 -0
  147. package/fesm2022/ngwr-input-testing.mjs.map +1 -0
  148. package/fesm2022/ngwr-input.mjs +47 -10
  149. package/fesm2022/ngwr-input.mjs.map +1 -1
  150. package/fesm2022/ngwr-knob.mjs +44 -8
  151. package/fesm2022/ngwr-knob.mjs.map +1 -1
  152. package/fesm2022/ngwr-layout.mjs +21 -5
  153. package/fesm2022/ngwr-layout.mjs.map +1 -1
  154. package/fesm2022/ngwr-lightbox.mjs +33 -6
  155. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  156. package/fesm2022/ngwr-line-chart.mjs +17 -4
  157. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  158. package/fesm2022/ngwr-list.mjs +2 -2
  159. package/fesm2022/ngwr-list.mjs.map +1 -1
  160. package/fesm2022/ngwr-loading-bar.mjs +2 -2
  161. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  162. package/fesm2022/ngwr-markdown-testing.mjs +516 -0
  163. package/fesm2022/ngwr-markdown-testing.mjs.map +1 -0
  164. package/fesm2022/ngwr-markdown.mjs +1492 -0
  165. package/fesm2022/ngwr-markdown.mjs.map +1 -0
  166. package/fesm2022/ngwr-marquee.mjs +17 -6
  167. package/fesm2022/ngwr-marquee.mjs.map +1 -1
  168. package/fesm2022/ngwr-mention-testing.mjs +513 -0
  169. package/fesm2022/ngwr-mention-testing.mjs.map +1 -0
  170. package/fesm2022/ngwr-mention.mjs +10 -1
  171. package/fesm2022/ngwr-mention.mjs.map +1 -1
  172. package/fesm2022/ngwr-meta.mjs +22 -7
  173. package/fesm2022/ngwr-meta.mjs.map +1 -1
  174. package/fesm2022/ngwr-meter-group.mjs +19 -5
  175. package/fesm2022/ngwr-meter-group.mjs.map +1 -1
  176. package/fesm2022/ngwr-overlay.mjs +41 -1
  177. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  178. package/fesm2022/ngwr-pagination-testing.mjs +389 -0
  179. package/fesm2022/ngwr-pagination-testing.mjs.map +1 -0
  180. package/fesm2022/ngwr-pagination.mjs +14 -2
  181. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  182. package/fesm2022/ngwr-popconfirm-testing.mjs +309 -0
  183. package/fesm2022/ngwr-popconfirm-testing.mjs.map +1 -0
  184. package/fesm2022/ngwr-popconfirm.mjs +95 -17
  185. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  186. package/fesm2022/ngwr-popover-testing.mjs +316 -0
  187. package/fesm2022/ngwr-popover-testing.mjs.map +1 -0
  188. package/fesm2022/ngwr-popover.mjs +21 -3
  189. package/fesm2022/ngwr-popover.mjs.map +1 -1
  190. package/fesm2022/ngwr-pull-to-refresh.mjs +17 -2
  191. package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -1
  192. package/fesm2022/ngwr-qr.mjs +13 -3
  193. package/fesm2022/ngwr-qr.mjs.map +1 -1
  194. package/fesm2022/ngwr-radio-testing.mjs +392 -0
  195. package/fesm2022/ngwr-radio-testing.mjs.map +1 -0
  196. package/fesm2022/ngwr-radio.mjs +10 -3
  197. package/fesm2022/ngwr-radio.mjs.map +1 -1
  198. package/fesm2022/ngwr-rating-testing.mjs +384 -0
  199. package/fesm2022/ngwr-rating-testing.mjs.map +1 -0
  200. package/fesm2022/ngwr-rating.mjs +37 -2
  201. package/fesm2022/ngwr-rating.mjs.map +1 -1
  202. package/fesm2022/ngwr-segmented-testing.mjs +512 -0
  203. package/fesm2022/ngwr-segmented-testing.mjs.map +1 -0
  204. package/fesm2022/ngwr-select-testing.mjs +268 -0
  205. package/fesm2022/ngwr-select-testing.mjs.map +1 -0
  206. package/fesm2022/ngwr-select.mjs +87 -16
  207. package/fesm2022/ngwr-select.mjs.map +1 -1
  208. package/fesm2022/ngwr-shiny-text.mjs +2 -2
  209. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  210. package/fesm2022/ngwr-sidebar.mjs +65 -12
  211. package/fesm2022/ngwr-sidebar.mjs.map +1 -1
  212. package/fesm2022/ngwr-slider-testing.mjs +478 -0
  213. package/fesm2022/ngwr-slider-testing.mjs.map +1 -0
  214. package/fesm2022/ngwr-slider.mjs +57 -13
  215. package/fesm2022/ngwr-slider.mjs.map +1 -1
  216. package/fesm2022/ngwr-sparkline.mjs +26 -6
  217. package/fesm2022/ngwr-sparkline.mjs.map +1 -1
  218. package/fesm2022/ngwr-speed-dial.mjs +37 -4
  219. package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
  220. package/fesm2022/ngwr-spinner.mjs +12 -3
  221. package/fesm2022/ngwr-spinner.mjs.map +1 -1
  222. package/fesm2022/ngwr-splash-cursor.mjs +2 -2
  223. package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
  224. package/fesm2022/ngwr-split-text.mjs +2 -2
  225. package/fesm2022/ngwr-split-text.mjs.map +1 -1
  226. package/fesm2022/ngwr-splitter.mjs +70 -9
  227. package/fesm2022/ngwr-splitter.mjs.map +1 -1
  228. package/fesm2022/ngwr-spotlight-card.mjs +2 -2
  229. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  230. package/fesm2022/ngwr-star-border.mjs +2 -2
  231. package/fesm2022/ngwr-star-border.mjs.map +1 -1
  232. package/fesm2022/ngwr-statistic.mjs +24 -7
  233. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  234. package/fesm2022/ngwr-stepper-testing.mjs +477 -0
  235. package/fesm2022/ngwr-stepper-testing.mjs.map +1 -0
  236. package/fesm2022/ngwr-switch-testing.mjs +77 -0
  237. package/fesm2022/ngwr-switch-testing.mjs.map +1 -0
  238. package/fesm2022/ngwr-switch.mjs +9 -3
  239. package/fesm2022/ngwr-switch.mjs.map +1 -1
  240. package/fesm2022/ngwr-table-testing.mjs +580 -0
  241. package/fesm2022/ngwr-table-testing.mjs.map +1 -0
  242. package/fesm2022/ngwr-table.mjs +87 -14
  243. package/fesm2022/ngwr-table.mjs.map +1 -1
  244. package/fesm2022/ngwr-tabs-testing.mjs +617 -0
  245. package/fesm2022/ngwr-tabs-testing.mjs.map +1 -0
  246. package/fesm2022/ngwr-tabs.mjs +38 -6
  247. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  248. package/fesm2022/ngwr-textarea-testing.mjs +238 -0
  249. package/fesm2022/ngwr-textarea-testing.mjs.map +1 -0
  250. package/fesm2022/ngwr-textarea.mjs +32 -4
  251. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  252. package/fesm2022/ngwr-tilt-card.mjs +2 -2
  253. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  254. package/fesm2022/ngwr-toast-testing.mjs +101 -0
  255. package/fesm2022/ngwr-toast-testing.mjs.map +1 -0
  256. package/fesm2022/ngwr-toast.mjs +2 -2
  257. package/fesm2022/ngwr-toast.mjs.map +1 -1
  258. package/fesm2022/ngwr-tour.mjs +61 -9
  259. package/fesm2022/ngwr-tour.mjs.map +1 -1
  260. package/fesm2022/ngwr-transfer-testing.mjs +538 -0
  261. package/fesm2022/ngwr-transfer-testing.mjs.map +1 -0
  262. package/fesm2022/ngwr-transfer.mjs +45 -14
  263. package/fesm2022/ngwr-transfer.mjs.map +1 -1
  264. package/fesm2022/ngwr-tree-testing.mjs +734 -0
  265. package/fesm2022/ngwr-tree-testing.mjs.map +1 -0
  266. package/fesm2022/ngwr-tree.mjs +73 -7
  267. package/fesm2022/ngwr-tree.mjs.map +1 -1
  268. package/fesm2022/ngwr-typewriter.mjs +5 -3
  269. package/fesm2022/ngwr-typewriter.mjs.map +1 -1
  270. package/fesm2022/ngwr-version.mjs +1 -1
  271. package/fesm2022/ngwr-version.mjs.map +1 -1
  272. package/fesm2022/ngwr-virtual-scroll.mjs +31 -5
  273. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  274. package/fesm2022/ngwr-waves.mjs +3 -3
  275. package/fesm2022/ngwr-waves.mjs.map +1 -1
  276. package/fesm2022/ngwr-window.mjs +8 -0
  277. package/fesm2022/ngwr-window.mjs.map +1 -1
  278. package/gauge/styles/_index.scss +1 -1
  279. package/glitch-text/styles/_index.scss +4 -0
  280. package/i18n/en.json +48 -0
  281. package/i18n/ru.json +48 -0
  282. package/image-cropper/styles/_index.scss +13 -1
  283. package/input/styles/_index.scss +2 -2
  284. package/input-number/styles/_index.scss +7 -2
  285. package/knob/styles/_index.scss +8 -1
  286. package/layout/styles/_index.scss +3 -3
  287. package/lightbox/styles/_index.scss +10 -2
  288. package/line-chart/styles/_index.scss +6 -0
  289. package/llms-full.txt +151 -4
  290. package/llms.txt +57 -8
  291. package/loading-bar/styles/_index.scss +1 -2
  292. package/markdown/styles/_index.scss +296 -0
  293. package/marquee/styles/_index.scss +12 -0
  294. package/mcp/api.js +512 -0
  295. package/mcp/catalog.js +157 -0
  296. package/mcp/server.js +273 -0
  297. package/mcp/tools.js +366 -0
  298. package/meter-group/styles/_index.scss +1 -1
  299. package/package.json +186 -35
  300. package/pagination/styles/_index.scss +6 -6
  301. package/popover/styles/_index.scss +37 -5
  302. package/rating/styles/_index.scss +10 -0
  303. package/schematics/use/symbol-map.json +2 -0
  304. package/segmented/styles/_index.scss +7 -0
  305. package/select/styles/_index.scss +29 -9
  306. package/sidebar/styles/_index.scss +30 -5
  307. package/slider/styles/_index.scss +15 -0
  308. package/speed-dial/styles/_index.scss +20 -0
  309. package/split-text/styles/_index.scss +13 -0
  310. package/star-border/styles/_index.scss +2 -0
  311. package/stepper/styles/_index.scss +1 -1
  312. package/styles/_grid.scss +4 -4
  313. package/styles.scss +1 -0
  314. package/switch/styles/_index.scss +5 -3
  315. package/table/styles/_index.scss +22 -11
  316. package/tabs/styles/_index.scss +11 -1
  317. package/textarea/styles/_index.scss +5 -0
  318. package/theme/styles/_colors.scss +29 -13
  319. package/theme/styles/_dark.scss +11 -3
  320. package/theme/styles/_mixins.scss +3 -0
  321. package/timeline/styles/_index.scss +2 -2
  322. package/toast/styles/_index.scss +17 -8
  323. package/toolbar/styles/_index.scss +3 -3
  324. package/tour/styles/_index.scss +7 -1
  325. package/tree/styles/_index.scss +5 -3
  326. package/types/ngwr-action-sheet.d.ts +9 -1
  327. package/types/ngwr-affix.d.ts +7 -1
  328. package/types/ngwr-anchor.d.ts +8 -1
  329. package/types/ngwr-avatar.d.ts +13 -3
  330. package/types/ngwr-bar-chart.d.ts +16 -0
  331. package/types/ngwr-burger.d.ts +6 -2
  332. package/types/ngwr-button-testing.d.ts +85 -0
  333. package/types/ngwr-button.d.ts +26 -10
  334. package/types/ngwr-calendar-heatmap.d.ts +16 -2
  335. package/types/ngwr-calendar.d.ts +10 -0
  336. package/types/ngwr-carousel-testing.d.ts +257 -0
  337. package/types/ngwr-carousel.d.ts +20 -4
  338. package/types/ngwr-cascader-testing.d.ts +392 -0
  339. package/types/ngwr-checkbox-testing.d.ts +77 -0
  340. package/types/ngwr-checkbox.d.ts +7 -2
  341. package/types/ngwr-collapse-testing.d.ts +290 -0
  342. package/types/ngwr-color-picker.d.ts +20 -11
  343. package/types/ngwr-command-palette-testing.d.ts +437 -0
  344. package/types/ngwr-command-palette.d.ts +25 -2
  345. package/types/ngwr-compare.d.ts +50 -2
  346. package/types/ngwr-config.d.ts +176 -0
  347. package/types/ngwr-context-menu-testing.d.ts +401 -0
  348. package/types/ngwr-context-menu.d.ts +65 -17
  349. package/types/ngwr-counter.d.ts +6 -1
  350. package/types/ngwr-date-adapter-luxon.d.ts +26 -0
  351. package/types/ngwr-date-picker-testing.d.ts +518 -0
  352. package/types/ngwr-date-picker.d.ts +4 -0
  353. package/types/ngwr-dialog-testing.d.ts +79 -0
  354. package/types/ngwr-directives.d.ts +10 -1
  355. package/types/ngwr-donut-chart.d.ts +8 -1
  356. package/types/ngwr-drawer-testing.d.ts +196 -0
  357. package/types/ngwr-dropdown-testing.d.ts +202 -0
  358. package/types/ngwr-dropdown.d.ts +7 -1
  359. package/types/ngwr-empty.d.ts +19 -4
  360. package/types/ngwr-event-calendar.d.ts +26 -1
  361. package/types/ngwr-file-upload-testing.d.ts +194 -0
  362. package/types/ngwr-form-testing.d.ts +379 -0
  363. package/types/ngwr-form.d.ts +17 -0
  364. package/types/ngwr-gauge.d.ts +13 -1
  365. package/types/ngwr-image-cropper.d.ts +10 -0
  366. package/types/ngwr-input-number-testing.d.ts +226 -0
  367. package/types/ngwr-input-number.d.ts +29 -1
  368. package/types/ngwr-input-otp-testing.d.ts +299 -0
  369. package/types/ngwr-input-otp.d.ts +23 -2
  370. package/types/ngwr-input-testing.d.ts +84 -0
  371. package/types/ngwr-input.d.ts +20 -6
  372. package/types/ngwr-knob.d.ts +18 -0
  373. package/types/ngwr-layout.d.ts +1 -0
  374. package/types/ngwr-lightbox.d.ts +17 -3
  375. package/types/ngwr-line-chart.d.ts +9 -2
  376. package/types/ngwr-markdown-testing.d.ts +462 -0
  377. package/types/ngwr-markdown.d.ts +534 -0
  378. package/types/ngwr-marquee.d.ts +12 -2
  379. package/types/ngwr-mention-testing.d.ts +359 -0
  380. package/types/ngwr-meta.d.ts +4 -2
  381. package/types/ngwr-meter-group.d.ts +11 -1
  382. package/types/ngwr-overlay.d.ts +33 -2
  383. package/types/ngwr-pagination-testing.d.ts +291 -0
  384. package/types/ngwr-pagination.d.ts +1 -0
  385. package/types/ngwr-popconfirm-testing.d.ts +235 -0
  386. package/types/ngwr-popconfirm.d.ts +31 -21
  387. package/types/ngwr-popover-testing.d.ts +221 -0
  388. package/types/ngwr-popover.d.ts +9 -0
  389. package/types/ngwr-pull-to-refresh.d.ts +7 -0
  390. package/types/ngwr-qr.d.ts +9 -1
  391. package/types/ngwr-radio-testing.d.ts +296 -0
  392. package/types/ngwr-radio.d.ts +8 -2
  393. package/types/ngwr-rating-testing.d.ts +291 -0
  394. package/types/ngwr-rating.d.ts +23 -0
  395. package/types/ngwr-segmented-testing.d.ts +401 -0
  396. package/types/ngwr-select-testing.d.ts +175 -0
  397. package/types/ngwr-select.d.ts +45 -4
  398. package/types/ngwr-sidebar.d.ts +17 -2
  399. package/types/ngwr-slider-testing.d.ts +329 -0
  400. package/types/ngwr-slider.d.ts +35 -1
  401. package/types/ngwr-sparkline.d.ts +12 -2
  402. package/types/ngwr-speed-dial.d.ts +17 -18
  403. package/types/ngwr-spinner.d.ts +8 -1
  404. package/types/ngwr-splitter.d.ts +24 -1
  405. package/types/ngwr-statistic.d.ts +12 -2
  406. package/types/ngwr-stepper-testing.d.ts +346 -0
  407. package/types/ngwr-switch-testing.d.ts +66 -0
  408. package/types/ngwr-switch.d.ts +7 -2
  409. package/types/ngwr-table-testing.d.ts +423 -0
  410. package/types/ngwr-table.d.ts +42 -0
  411. package/types/ngwr-tabs-testing.d.ts +470 -0
  412. package/types/ngwr-tabs.d.ts +9 -0
  413. package/types/ngwr-textarea-testing.d.ts +184 -0
  414. package/types/ngwr-textarea.d.ts +7 -2
  415. package/types/ngwr-toast-testing.d.ts +80 -0
  416. package/types/ngwr-tour.d.ts +27 -0
  417. package/types/ngwr-transfer-testing.d.ts +444 -0
  418. package/types/ngwr-transfer.d.ts +16 -1
  419. package/types/ngwr-tree-testing.d.ts +501 -0
  420. package/types/ngwr-tree.d.ts +33 -0
  421. package/types/ngwr-version.d.ts +1 -1
  422. package/types/ngwr-virtual-scroll.d.ts +13 -1
  423. package/typewriter/styles/_index.scss +1 -1
  424. package/typography/styles/_index.scss +1 -1
  425. package/window/styles/_index.scss +32 -9
@@ -0,0 +1,377 @@
1
+ import { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
2
+
3
+ /**
4
+ * @license
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
8
+ */
9
+ /**
10
+ * The settled percentage out of `translateX(-100%)`, and out of the mid-drag
11
+ * `translateX(calc(-100% + 12px))` — the pixel half is the finger, not the slide.
12
+ */
13
+ const TRACK_OFFSET = /translateX\(\s*(?:calc\(\s*)?(-?[\d.]+)%/;
14
+ /**
15
+ * Test harness for `<wr-carousel>` — drive the strip the way someone on the page
16
+ * drives it.
17
+ *
18
+ * Everything it reads is public API: the `.wr-carousel__*` elements, the dots'
19
+ * `aria-current`, and the `aria-roledescription` the viewport and each slide
20
+ * publish. Two things are worth knowing before writing an assertion against it:
21
+ *
22
+ * - **The slides do not say which one is showing.** A `<wr-carousel-slide>` carries
23
+ * `role="group"` and `aria-roledescription="slide"` and nothing else — no
24
+ * `aria-current`, no `aria-hidden` on the ones off-screen. The current slide is
25
+ * published in exactly two places, the dot carrying `aria-current="true"` and the
26
+ * track's own offset, and {@link getActiveIndex} reads them in that order. There
27
+ * is likewise no live region: the component announces a move to nobody, so a
28
+ * harness cannot report one.
29
+ * - **It never drags.** The swipe the component supports is a touch gesture
30
+ * measured against the viewport's own width, and jsdom has no layout — that width
31
+ * is 0, so the "20% of the viewport" threshold is 0 too and EVERY drag clears it,
32
+ * a 1px twitch included. The result says nothing about a real finger, and the spec
33
+ * pins that artifact rather than pretending otherwise. Every move here goes
34
+ * through the arrow buttons and the dots instead, which is the accessible path
35
+ * anyway. `carousel.spec.ts` is where the gesture itself is pinned, by staging the
36
+ * touch events and declaring an `offsetWidth`.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * const loader = TestbedHarnessEnvironment.loader(fixture);
41
+ * const gallery = await loader.getHarness(WrCarouselHarness.with({ ariaLabel: 'Gallery' }));
42
+ *
43
+ * expect(await gallery.getSlideCount()).toBe(3);
44
+ * await gallery.next();
45
+ * expect(await gallery.getActiveIndex()).toBe(1);
46
+ *
47
+ * await gallery.goTo(2);
48
+ * expect(await gallery.getActiveSlideText()).toBe('Dunes');
49
+ * ```
50
+ *
51
+ * @see https://ngwr.dev/guides/testing
52
+ */
53
+ class WrCarouselHarness extends ComponentHarness {
54
+ static hostSelector = 'wr-carousel';
55
+ /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
56
+ static with(options = {}) {
57
+ return new HarnessPredicate(WrCarouselHarness, options)
58
+ .addOption('ariaLabel', options.ariaLabel, (harness, label) => HarnessPredicate.stringMatches(harness.getAccessibleName(), label))
59
+ .addOption('slideCount', options.slideCount, async (harness, count) => (await harness.getSlideCount()) === count)
60
+ .addOption('slideText', options.slideText, async (harness, text) => {
61
+ for (const slide of await harness.getSlideTexts()) {
62
+ if (await HarnessPredicate.stringMatches(slide, text))
63
+ return true;
64
+ }
65
+ return false;
66
+ });
67
+ }
68
+ // What the carousel announces
69
+ /**
70
+ * The role the strip announces — `group`, which is what lets
71
+ * `aria-roledescription` mean anything.
72
+ *
73
+ * Read off the VIEWPORT rather than the host, and that is the whole point of the
74
+ * pairing: `aria-roledescription` is dropped on an element with no semantic role,
75
+ * and the host element (`<wr-carousel>`) has none.
76
+ */
77
+ async getRole() {
78
+ return (await this.viewport()).getAttribute('role');
79
+ }
80
+ /** How the strip describes itself to a screen reader — `carousel`. */
81
+ async getRoleDescription() {
82
+ return (await this.viewport()).getAttribute('aria-roledescription');
83
+ }
84
+ /**
85
+ * The carousel's accessible name.
86
+ *
87
+ * The RESOLVED one, which is the only one the page has: the `ariaLabel` input
88
+ * defaults to `null` and the component runs it through the `ngwr/i18n` catalog
89
+ * (`carousel.label`, falling back to `'Carousel'`), so a consumer who passed
90
+ * nothing still gets a named group and this still answers. Reporting the raw
91
+ * input would say `null` about a carousel that announces itself perfectly well.
92
+ */
93
+ async getAccessibleName() {
94
+ return (await this.viewport()).getAttribute('aria-label');
95
+ }
96
+ /** The accessible name of the previous-slide button. Throws when the arrows are not rendered. */
97
+ async getPreviousLabel() {
98
+ return (await this.nav('prev', 'getPreviousLabel')).getAttribute('aria-label');
99
+ }
100
+ /** The accessible name of the next-slide button. Throws when the arrows are not rendered. */
101
+ async getNextLabel() {
102
+ return (await this.nav('next', 'getNextLabel')).getAttribute('aria-label');
103
+ }
104
+ /**
105
+ * The accessible name of the dot group — what names the row of dots as a set
106
+ * rather than leaving a screen reader with N unexplained buttons.
107
+ *
108
+ * Throws when the dots are not rendered: there is no group to name then, and a
109
+ * `null` would read like a group that lost its label.
110
+ */
111
+ async getPaginationLabel() {
112
+ const dots = await this.locatorForOptional('.wr-carousel__dots')();
113
+ if (!dots) {
114
+ throw new Error('WrCarouselHarness.getPaginationLabel(): this carousel renders no dot group — the dots are dropped ' +
115
+ 'when [showDots] is false or when there are fewer than two slides.');
116
+ }
117
+ return dots.getAttribute('aria-label');
118
+ }
119
+ /**
120
+ * What each slide announces itself as — `slide`, on every one of them, in DOM
121
+ * order.
122
+ *
123
+ * The one piece of ARIA the slides carry, and the reason it is worth asking: it
124
+ * is set on the slide component's own host, so a slide reaching the page through
125
+ * some other element would come back `null` here while the carousel kept working.
126
+ */
127
+ async getSlideRoleDescriptions() {
128
+ const slides = await this.slides();
129
+ return Promise.all(slides.map(slide => slide.getAttribute('aria-roledescription')));
130
+ }
131
+ // What the carousel is showing
132
+ /** How many slides the carousel holds. */
133
+ async getSlideCount() {
134
+ return (await this.slides()).length;
135
+ }
136
+ /** The text of every slide, in DOM order. */
137
+ async getSlideTexts() {
138
+ const slides = await this.slides();
139
+ return Promise.all(slides.map(slide => slide.text()));
140
+ }
141
+ /**
142
+ * Which slide is showing, as a zero-based index.
143
+ *
144
+ * Taken from the dot carrying `aria-current="true"` whenever the dots are
145
+ * rendered — that attribute is the only thing on the page that tells a screen
146
+ * reader where in the strip it has got to, so it is the answer that matters —
147
+ * and derived from the track's rendered offset when they are not, `[showDots]`
148
+ * being off and a single-slide carousel both dropping the strip entirely.
149
+ *
150
+ * That fallback takes the MAGNITUDE of the offset on purpose. The transform is
151
+ * physical while the slides sit on the inline axis, so a mirrored carousel paints
152
+ * `translateX(100%)` for the very slide an LTR one paints `translateX(-100%)`
153
+ * for; signed, this reported slide -1 for a perfectly healthy RTL carousel.
154
+ *
155
+ * Throws on a carousel with no slides at all — nothing is showing there, and `0`
156
+ * would read like the first slide.
157
+ */
158
+ async getActiveIndex() {
159
+ const count = await this.getSlideCount();
160
+ if (count === 0) {
161
+ throw new Error('WrCarouselHarness.getActiveIndex(): this carousel has no <wr-carousel-slide> children, so no slide is ' +
162
+ 'current — 0 would read like the first one.');
163
+ }
164
+ const dots = await this.dots();
165
+ if (dots.length) {
166
+ for (let index = 0; index < dots.length; index++) {
167
+ if ((await dots[index].getAttribute('aria-current')) === 'true')
168
+ return index;
169
+ }
170
+ throw new Error('WrCarouselHarness.getActiveIndex(): the dots are rendered but none of them carries aria-current, so the ' +
171
+ 'page tells a screen reader that no slide is current. The component clamps `active` into range, so look ' +
172
+ 'for a lost aria-current binding rather than an out-of-range index — the `--active` class alone is paint.');
173
+ }
174
+ return Math.round(Math.abs(await this.getTrackOffsetPercent()) / 100);
175
+ }
176
+ /** The text of the slide that is showing. Throws on a carousel with no slides. */
177
+ async getActiveSlideText() {
178
+ const index = await this.getActiveIndex();
179
+ return (await this.slides())[index].text();
180
+ }
181
+ /**
182
+ * The track's rendered offset, as a percentage of one viewport: `-100` for the
183
+ * second slide of an LTR carousel, `+100` for the second slide of a mirrored one.
184
+ *
185
+ * Read off the inline `style` attribute rather than through `getCssValue()`,
186
+ * because the percentage only survives where the component wrote it. jsdom hands
187
+ * a declared `transform` straight back through `getComputedStyle`, so
188
+ * `getCssValue()` answers correctly HERE and would stop the moment the same
189
+ * harness ran against a real browser, which resolves the property to a pixel
190
+ * matrix — a green unit test would be hiding it. Mid-drag the component writes
191
+ * `translateX(calc(-100% + 12px))` and this reports the settled `-100`: the pixel
192
+ * half is the finger's own displacement, which is physical in both directions and
193
+ * belongs to no slide.
194
+ *
195
+ * Worth asserting next to {@link getActiveIndex}: it is the same fact painted
196
+ * instead of announced, and a carousel that lights the right dot while parking
197
+ * the track in blank space is exactly the failure nobody sees in a spec.
198
+ */
199
+ async getTrackOffsetPercent() {
200
+ const style = (await (await this.track()).getAttribute('style')) ?? '';
201
+ const match = TRACK_OFFSET.exec(style);
202
+ if (!match) {
203
+ throw new Error(`WrCarouselHarness.getTrackOffsetPercent(): the track carries no translateX() offset (style: "${style}"). ` +
204
+ 'That transform is how the carousel moves at all, so it should always be there.');
205
+ }
206
+ return Number(match[1]);
207
+ }
208
+ // The controls the carousel renders
209
+ /** Whether the prev / next arrows are on the page. Both are dropped together. */
210
+ async hasArrows() {
211
+ return (await this.locatorForOptional('.wr-carousel__nav--next')()) !== null;
212
+ }
213
+ /** Whether the dot strip is on the page. */
214
+ async hasDots() {
215
+ return (await this.locatorForOptional('.wr-carousel__dots')()) !== null;
216
+ }
217
+ /** How many dots are rendered — one per slide, or `0` while the strip is hidden. */
218
+ async getDotCount() {
219
+ return (await this.dots()).length;
220
+ }
221
+ /**
222
+ * The accessible name of every dot, in order — `'Go to slide 1'`, … resolved
223
+ * through the `ngwr/i18n` catalog.
224
+ *
225
+ * A dot is a bare button with no text of its own, so this label is all a screen
226
+ * reader has to tell one from another. `[]` when the strip is hidden, matching
227
+ * {@link getDotCount}.
228
+ */
229
+ async getDotLabels() {
230
+ const dots = await this.dots();
231
+ return Promise.all(dots.map(dot => dot.getAttribute('aria-label')));
232
+ }
233
+ // Moving the carousel
234
+ /**
235
+ * Click the next-slide arrow.
236
+ *
237
+ * "Next" is the next SLIDE, not the next thing on the right: the buttons keep
238
+ * their semantics under `dir="rtl"` and only the travel under them turns around.
239
+ * At the last slide this wraps to the first one, unless `[loop]` is off — in
240
+ * which case it legitimately does nothing, so nothing is asserted about the move.
241
+ */
242
+ async next() {
243
+ return (await this.nav('next', 'next')).click();
244
+ }
245
+ /** Click the previous-slide arrow. Wraps to the last slide unless `[loop]` is off. */
246
+ async previous() {
247
+ return (await this.nav('prev', 'previous')).click();
248
+ }
249
+ /**
250
+ * Jump to a slide by clicking its dot — the only way the page offers to reach a
251
+ * slide directly.
252
+ *
253
+ * Throws when the dots are hidden (the component's own `goTo()` is still there
254
+ * for a spec holding the instance, but nothing on the page can be clicked) and
255
+ * throws on an index no slide has, rather than clicking nothing and leaving the
256
+ * carousel where it was.
257
+ */
258
+ async goTo(index) {
259
+ const dots = await this.dots();
260
+ if (!dots.length) {
261
+ throw new Error(`WrCarouselHarness.goTo(${index}): this carousel renders no dots, and they are the only way to reach a ` +
262
+ 'slide directly from the page — they are dropped when [showDots] is false or when there are fewer than ' +
263
+ 'two slides. Use next() / previous(), or write the active index from the host.');
264
+ }
265
+ if (!Number.isInteger(index) || index < 0 || index >= dots.length) {
266
+ throw new Error(`WrCarouselHarness.goTo(${index}): out of range — this carousel has ${dots.length} slides, so the index ` +
267
+ `must be a whole number between 0 and ${dots.length - 1}.`);
268
+ }
269
+ return dots[index].click();
270
+ }
271
+ // Holding autoplay
272
+ /**
273
+ * Move the pointer onto the carousel, which is what HOLDS autoplay.
274
+ *
275
+ * Aimed at the host and not the viewport, deliberately: the arrows and the dots
276
+ * are the viewport's SIBLINGS, so a viewport-scoped hover would let a slide
277
+ * change under a cursor that is aiming at an arrow.
278
+ */
279
+ async hover() {
280
+ return (await this.host()).hover();
281
+ }
282
+ /** Move the pointer away again, releasing the hold. */
283
+ async mouseAway() {
284
+ return (await this.host()).mouseAway();
285
+ }
286
+ /**
287
+ * Put keyboard focus on the first control the carousel renders — the previous
288
+ * arrow, or the first dot when the arrows are hidden.
289
+ *
290
+ * This is the keyboard half of the autoplay hold: WCAG 2.2.2 wants a way to stop
291
+ * moving content, and hovering is not one for someone who never touches a mouse,
292
+ * so the component listens for `focusin` on its host as well. Focus lands on the
293
+ * carousel's OWN controls; anything focusable a slide happens to project is not
294
+ * this harness's business, though in a browser it would hold autoplay just the
295
+ * same.
296
+ *
297
+ * Note what this is NOT: the dot of the slide showing. The dots are ordinary
298
+ * buttons with no roving `tabindex`, so each of them is a tab stop of its own and
299
+ * the first one a Tab press meets is the prev arrow whatever slide is current —
300
+ * two different questions, answered here and by {@link getActiveIndex}.
301
+ *
302
+ * Throws when the carousel renders no controls at all, because then there is
303
+ * nothing for a Tab press to land on and no keyboard mechanism to assert.
304
+ */
305
+ async focus() {
306
+ const [first] = await this.controls();
307
+ if (!first) {
308
+ throw new Error('WrCarouselHarness.focus(): this carousel renders no controls of its own — the arrows and the dots are ' +
309
+ 'both gone (a single slide, or [showArrows] and [showDots] switched off), so a Tab press has nothing ' +
310
+ 'inside it to land on.');
311
+ }
312
+ return first.focus();
313
+ }
314
+ /**
315
+ * Take focus off whichever of the carousel's controls holds it, releasing the
316
+ * hold {@link focus} started.
317
+ *
318
+ * Throws when none of them is focused: `focusout` is what the component listens
319
+ * for, and blurring an element that never had focus fires nothing — a quiet
320
+ * no-op here surfaces as an autoplay assertion failing three lines later.
321
+ */
322
+ async blur() {
323
+ for (const control of await this.controls()) {
324
+ if (await control.isFocused())
325
+ return control.blur();
326
+ }
327
+ throw new Error('WrCarouselHarness.blur(): none of the controls this carousel renders holds focus, so there is no focus to ' +
328
+ 'release. Call focus() first — the hold is released by blurring the element that took it.');
329
+ }
330
+ /** Whether one of the carousel's own controls holds focus — which is what holds autoplay. */
331
+ async isFocused() {
332
+ for (const control of await this.controls()) {
333
+ if (await control.isFocused())
334
+ return true;
335
+ }
336
+ return false;
337
+ }
338
+ // Internals
339
+ /** The element that carries the carousel's role and name. */
340
+ async viewport() {
341
+ return this.locatorFor('.wr-carousel__viewport')();
342
+ }
343
+ /** The moving strip, whose inline transform is where the carousel IS. */
344
+ async track() {
345
+ return this.locatorFor('.wr-carousel__track')();
346
+ }
347
+ async slides() {
348
+ return this.locatorForAll('wr-carousel-slide')();
349
+ }
350
+ async dots() {
351
+ return this.locatorForAll('.wr-carousel__dot')();
352
+ }
353
+ /**
354
+ * Every control the carousel renders itself, in the order a Tab press meets
355
+ * them: the two arrows, then the dots.
356
+ */
357
+ async controls() {
358
+ const navs = await this.locatorForAll('.wr-carousel__nav')();
359
+ return [...navs, ...(await this.dots())];
360
+ }
361
+ /** One arrow, or a failure naming both reasons it might not be there. */
362
+ async nav(side, caller) {
363
+ const button = await this.locatorForOptional(`.wr-carousel__nav--${side}`)();
364
+ if (!button) {
365
+ throw new Error(`WrCarouselHarness.${caller}(): this carousel renders no ${side} arrow — the arrows are dropped when ` +
366
+ '[showArrows] is false or when there are fewer than two slides to page through.');
367
+ }
368
+ return button;
369
+ }
370
+ }
371
+
372
+ /**
373
+ * Generated bundle index. Do not edit.
374
+ */
375
+
376
+ export { WrCarouselHarness };
377
+ //# sourceMappingURL=ngwr-carousel-testing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngwr-carousel-testing.mjs","sources":["../../../projects/lib/carousel/testing/wr-carousel-harness.ts","../../../projects/lib/carousel/testing/ngwr-carousel-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate, type TestElement } from '@angular/cdk/testing';\n\nimport type { WrCarouselHarnessFilters } from './interfaces';\n\n/**\n * The settled percentage out of `translateX(-100%)`, and out of the mid-drag\n * `translateX(calc(-100% + 12px))` — the pixel half is the finger, not the slide.\n */\nconst TRACK_OFFSET = /translateX\\(\\s*(?:calc\\(\\s*)?(-?[\\d.]+)%/;\n\n/**\n * Test harness for `<wr-carousel>` — drive the strip the way someone on the page\n * drives it.\n *\n * Everything it reads is public API: the `.wr-carousel__*` elements, the dots'\n * `aria-current`, and the `aria-roledescription` the viewport and each slide\n * publish. Two things are worth knowing before writing an assertion against it:\n *\n * - **The slides do not say which one is showing.** A `<wr-carousel-slide>` carries\n * `role=\"group\"` and `aria-roledescription=\"slide\"` and nothing else — no\n * `aria-current`, no `aria-hidden` on the ones off-screen. The current slide is\n * published in exactly two places, the dot carrying `aria-current=\"true\"` and the\n * track's own offset, and {@link getActiveIndex} reads them in that order. There\n * is likewise no live region: the component announces a move to nobody, so a\n * harness cannot report one.\n * - **It never drags.** The swipe the component supports is a touch gesture\n * measured against the viewport's own width, and jsdom has no layout — that width\n * is 0, so the \"20% of the viewport\" threshold is 0 too and EVERY drag clears it,\n * a 1px twitch included. The result says nothing about a real finger, and the spec\n * pins that artifact rather than pretending otherwise. Every move here goes\n * through the arrow buttons and the dots instead, which is the accessible path\n * anyway. `carousel.spec.ts` is where the gesture itself is pinned, by staging the\n * touch events and declaring an `offsetWidth`.\n *\n * @example\n * ```ts\n * const loader = TestbedHarnessEnvironment.loader(fixture);\n * const gallery = await loader.getHarness(WrCarouselHarness.with({ ariaLabel: 'Gallery' }));\n *\n * expect(await gallery.getSlideCount()).toBe(3);\n * await gallery.next();\n * expect(await gallery.getActiveIndex()).toBe(1);\n *\n * await gallery.goTo(2);\n * expect(await gallery.getActiveSlideText()).toBe('Dunes');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrCarouselHarness extends ComponentHarness {\n static hostSelector = 'wr-carousel';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrCarouselHarnessFilters = {}): HarnessPredicate<WrCarouselHarness> {\n return new HarnessPredicate(WrCarouselHarness, options)\n .addOption('ariaLabel', options.ariaLabel, (harness, label) =>\n HarnessPredicate.stringMatches(harness.getAccessibleName(), label)\n )\n .addOption('slideCount', options.slideCount, async (harness, count) => (await harness.getSlideCount()) === count)\n .addOption('slideText', options.slideText, async (harness, text) => {\n for (const slide of await harness.getSlideTexts()) {\n if (await HarnessPredicate.stringMatches(slide, text)) return true;\n }\n return false;\n });\n }\n\n // What the carousel announces\n\n /**\n * The role the strip announces — `group`, which is what lets\n * `aria-roledescription` mean anything.\n *\n * Read off the VIEWPORT rather than the host, and that is the whole point of the\n * pairing: `aria-roledescription` is dropped on an element with no semantic role,\n * and the host element (`<wr-carousel>`) has none.\n */\n async getRole(): Promise<string | null> {\n return (await this.viewport()).getAttribute('role');\n }\n\n /** How the strip describes itself to a screen reader — `carousel`. */\n async getRoleDescription(): Promise<string | null> {\n return (await this.viewport()).getAttribute('aria-roledescription');\n }\n\n /**\n * The carousel's accessible name.\n *\n * The RESOLVED one, which is the only one the page has: the `ariaLabel` input\n * defaults to `null` and the component runs it through the `ngwr/i18n` catalog\n * (`carousel.label`, falling back to `'Carousel'`), so a consumer who passed\n * nothing still gets a named group and this still answers. Reporting the raw\n * input would say `null` about a carousel that announces itself perfectly well.\n */\n async getAccessibleName(): Promise<string | null> {\n return (await this.viewport()).getAttribute('aria-label');\n }\n\n /** The accessible name of the previous-slide button. Throws when the arrows are not rendered. */\n async getPreviousLabel(): Promise<string | null> {\n return (await this.nav('prev', 'getPreviousLabel')).getAttribute('aria-label');\n }\n\n /** The accessible name of the next-slide button. Throws when the arrows are not rendered. */\n async getNextLabel(): Promise<string | null> {\n return (await this.nav('next', 'getNextLabel')).getAttribute('aria-label');\n }\n\n /**\n * The accessible name of the dot group — what names the row of dots as a set\n * rather than leaving a screen reader with N unexplained buttons.\n *\n * Throws when the dots are not rendered: there is no group to name then, and a\n * `null` would read like a group that lost its label.\n */\n async getPaginationLabel(): Promise<string | null> {\n const dots = await this.locatorForOptional('.wr-carousel__dots')();\n if (!dots) {\n throw new Error(\n 'WrCarouselHarness.getPaginationLabel(): this carousel renders no dot group — the dots are dropped ' +\n 'when [showDots] is false or when there are fewer than two slides.'\n );\n }\n return dots.getAttribute('aria-label');\n }\n\n /**\n * What each slide announces itself as — `slide`, on every one of them, in DOM\n * order.\n *\n * The one piece of ARIA the slides carry, and the reason it is worth asking: it\n * is set on the slide component's own host, so a slide reaching the page through\n * some other element would come back `null` here while the carousel kept working.\n */\n async getSlideRoleDescriptions(): Promise<(string | null)[]> {\n const slides = await this.slides();\n return Promise.all(slides.map(slide => slide.getAttribute('aria-roledescription')));\n }\n\n // What the carousel is showing\n\n /** How many slides the carousel holds. */\n async getSlideCount(): Promise<number> {\n return (await this.slides()).length;\n }\n\n /** The text of every slide, in DOM order. */\n async getSlideTexts(): Promise<string[]> {\n const slides = await this.slides();\n return Promise.all(slides.map(slide => slide.text()));\n }\n\n /**\n * Which slide is showing, as a zero-based index.\n *\n * Taken from the dot carrying `aria-current=\"true\"` whenever the dots are\n * rendered — that attribute is the only thing on the page that tells a screen\n * reader where in the strip it has got to, so it is the answer that matters —\n * and derived from the track's rendered offset when they are not, `[showDots]`\n * being off and a single-slide carousel both dropping the strip entirely.\n *\n * That fallback takes the MAGNITUDE of the offset on purpose. The transform is\n * physical while the slides sit on the inline axis, so a mirrored carousel paints\n * `translateX(100%)` for the very slide an LTR one paints `translateX(-100%)`\n * for; signed, this reported slide -1 for a perfectly healthy RTL carousel.\n *\n * Throws on a carousel with no slides at all — nothing is showing there, and `0`\n * would read like the first slide.\n */\n async getActiveIndex(): Promise<number> {\n const count = await this.getSlideCount();\n if (count === 0) {\n throw new Error(\n 'WrCarouselHarness.getActiveIndex(): this carousel has no <wr-carousel-slide> children, so no slide is ' +\n 'current — 0 would read like the first one.'\n );\n }\n\n const dots = await this.dots();\n if (dots.length) {\n for (let index = 0; index < dots.length; index++) {\n if ((await dots[index].getAttribute('aria-current')) === 'true') return index;\n }\n throw new Error(\n 'WrCarouselHarness.getActiveIndex(): the dots are rendered but none of them carries aria-current, so the ' +\n 'page tells a screen reader that no slide is current. The component clamps `active` into range, so look ' +\n 'for a lost aria-current binding rather than an out-of-range index — the `--active` class alone is paint.'\n );\n }\n\n return Math.round(Math.abs(await this.getTrackOffsetPercent()) / 100);\n }\n\n /** The text of the slide that is showing. Throws on a carousel with no slides. */\n async getActiveSlideText(): Promise<string> {\n const index = await this.getActiveIndex();\n return (await this.slides())[index].text();\n }\n\n /**\n * The track's rendered offset, as a percentage of one viewport: `-100` for the\n * second slide of an LTR carousel, `+100` for the second slide of a mirrored one.\n *\n * Read off the inline `style` attribute rather than through `getCssValue()`,\n * because the percentage only survives where the component wrote it. jsdom hands\n * a declared `transform` straight back through `getComputedStyle`, so\n * `getCssValue()` answers correctly HERE and would stop the moment the same\n * harness ran against a real browser, which resolves the property to a pixel\n * matrix — a green unit test would be hiding it. Mid-drag the component writes\n * `translateX(calc(-100% + 12px))` and this reports the settled `-100`: the pixel\n * half is the finger's own displacement, which is physical in both directions and\n * belongs to no slide.\n *\n * Worth asserting next to {@link getActiveIndex}: it is the same fact painted\n * instead of announced, and a carousel that lights the right dot while parking\n * the track in blank space is exactly the failure nobody sees in a spec.\n */\n async getTrackOffsetPercent(): Promise<number> {\n const style = (await (await this.track()).getAttribute('style')) ?? '';\n const match = TRACK_OFFSET.exec(style);\n if (!match) {\n throw new Error(\n `WrCarouselHarness.getTrackOffsetPercent(): the track carries no translateX() offset (style: \"${style}\"). ` +\n 'That transform is how the carousel moves at all, so it should always be there.'\n );\n }\n return Number(match[1]);\n }\n\n // The controls the carousel renders\n\n /** Whether the prev / next arrows are on the page. Both are dropped together. */\n async hasArrows(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-carousel__nav--next')()) !== null;\n }\n\n /** Whether the dot strip is on the page. */\n async hasDots(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-carousel__dots')()) !== null;\n }\n\n /** How many dots are rendered — one per slide, or `0` while the strip is hidden. */\n async getDotCount(): Promise<number> {\n return (await this.dots()).length;\n }\n\n /**\n * The accessible name of every dot, in order — `'Go to slide 1'`, … resolved\n * through the `ngwr/i18n` catalog.\n *\n * A dot is a bare button with no text of its own, so this label is all a screen\n * reader has to tell one from another. `[]` when the strip is hidden, matching\n * {@link getDotCount}.\n */\n async getDotLabels(): Promise<(string | null)[]> {\n const dots = await this.dots();\n return Promise.all(dots.map(dot => dot.getAttribute('aria-label')));\n }\n\n // Moving the carousel\n\n /**\n * Click the next-slide arrow.\n *\n * \"Next\" is the next SLIDE, not the next thing on the right: the buttons keep\n * their semantics under `dir=\"rtl\"` and only the travel under them turns around.\n * At the last slide this wraps to the first one, unless `[loop]` is off — in\n * which case it legitimately does nothing, so nothing is asserted about the move.\n */\n async next(): Promise<void> {\n return (await this.nav('next', 'next')).click();\n }\n\n /** Click the previous-slide arrow. Wraps to the last slide unless `[loop]` is off. */\n async previous(): Promise<void> {\n return (await this.nav('prev', 'previous')).click();\n }\n\n /**\n * Jump to a slide by clicking its dot — the only way the page offers to reach a\n * slide directly.\n *\n * Throws when the dots are hidden (the component's own `goTo()` is still there\n * for a spec holding the instance, but nothing on the page can be clicked) and\n * throws on an index no slide has, rather than clicking nothing and leaving the\n * carousel where it was.\n */\n async goTo(index: number): Promise<void> {\n const dots = await this.dots();\n if (!dots.length) {\n throw new Error(\n `WrCarouselHarness.goTo(${index}): this carousel renders no dots, and they are the only way to reach a ` +\n 'slide directly from the page — they are dropped when [showDots] is false or when there are fewer than ' +\n 'two slides. Use next() / previous(), or write the active index from the host.'\n );\n }\n if (!Number.isInteger(index) || index < 0 || index >= dots.length) {\n throw new Error(\n `WrCarouselHarness.goTo(${index}): out of range — this carousel has ${dots.length} slides, so the index ` +\n `must be a whole number between 0 and ${dots.length - 1}.`\n );\n }\n return dots[index].click();\n }\n\n // Holding autoplay\n\n /**\n * Move the pointer onto the carousel, which is what HOLDS autoplay.\n *\n * Aimed at the host and not the viewport, deliberately: the arrows and the dots\n * are the viewport's SIBLINGS, so a viewport-scoped hover would let a slide\n * change under a cursor that is aiming at an arrow.\n */\n async hover(): Promise<void> {\n return (await this.host()).hover();\n }\n\n /** Move the pointer away again, releasing the hold. */\n async mouseAway(): Promise<void> {\n return (await this.host()).mouseAway();\n }\n\n /**\n * Put keyboard focus on the first control the carousel renders — the previous\n * arrow, or the first dot when the arrows are hidden.\n *\n * This is the keyboard half of the autoplay hold: WCAG 2.2.2 wants a way to stop\n * moving content, and hovering is not one for someone who never touches a mouse,\n * so the component listens for `focusin` on its host as well. Focus lands on the\n * carousel's OWN controls; anything focusable a slide happens to project is not\n * this harness's business, though in a browser it would hold autoplay just the\n * same.\n *\n * Note what this is NOT: the dot of the slide showing. The dots are ordinary\n * buttons with no roving `tabindex`, so each of them is a tab stop of its own and\n * the first one a Tab press meets is the prev arrow whatever slide is current —\n * two different questions, answered here and by {@link getActiveIndex}.\n *\n * Throws when the carousel renders no controls at all, because then there is\n * nothing for a Tab press to land on and no keyboard mechanism to assert.\n */\n async focus(): Promise<void> {\n const [first] = await this.controls();\n if (!first) {\n throw new Error(\n 'WrCarouselHarness.focus(): this carousel renders no controls of its own — the arrows and the dots are ' +\n 'both gone (a single slide, or [showArrows] and [showDots] switched off), so a Tab press has nothing ' +\n 'inside it to land on.'\n );\n }\n return first.focus();\n }\n\n /**\n * Take focus off whichever of the carousel's controls holds it, releasing the\n * hold {@link focus} started.\n *\n * Throws when none of them is focused: `focusout` is what the component listens\n * for, and blurring an element that never had focus fires nothing — a quiet\n * no-op here surfaces as an autoplay assertion failing three lines later.\n */\n async blur(): Promise<void> {\n for (const control of await this.controls()) {\n if (await control.isFocused()) return control.blur();\n }\n throw new Error(\n 'WrCarouselHarness.blur(): none of the controls this carousel renders holds focus, so there is no focus to ' +\n 'release. Call focus() first — the hold is released by blurring the element that took it.'\n );\n }\n\n /** Whether one of the carousel's own controls holds focus — which is what holds autoplay. */\n async isFocused(): Promise<boolean> {\n for (const control of await this.controls()) {\n if (await control.isFocused()) return true;\n }\n return false;\n }\n\n // Internals\n\n /** The element that carries the carousel's role and name. */\n private async viewport(): Promise<TestElement> {\n return this.locatorFor('.wr-carousel__viewport')();\n }\n\n /** The moving strip, whose inline transform is where the carousel IS. */\n private async track(): Promise<TestElement> {\n return this.locatorFor('.wr-carousel__track')();\n }\n\n private async slides(): Promise<TestElement[]> {\n return this.locatorForAll('wr-carousel-slide')();\n }\n\n private async dots(): Promise<TestElement[]> {\n return this.locatorForAll('.wr-carousel__dot')();\n }\n\n /**\n * Every control the carousel renders itself, in the order a Tab press meets\n * them: the two arrows, then the dots.\n */\n private async controls(): Promise<TestElement[]> {\n const navs = await this.locatorForAll('.wr-carousel__nav')();\n return [...navs, ...(await this.dots())];\n }\n\n /** One arrow, or a failure naming both reasons it might not be there. */\n private async nav(side: 'prev' | 'next', caller: string): Promise<TestElement> {\n const button = await this.locatorForOptional(`.wr-carousel__nav--${side}`)();\n if (!button) {\n throw new Error(\n `WrCarouselHarness.${caller}(): this carousel renders no ${side} arrow — the arrows are dropped when ` +\n '[showArrows] is false or when there are fewer than two slides to page through.'\n );\n }\n return button;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAMH;;;AAGG;AACH,MAAM,YAAY,GAAG,0CAA0C;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCG;AACG,MAAO,iBAAkB,SAAQ,gBAAgB,CAAA;AACrD,IAAA,OAAO,YAAY,GAAG,aAAa;;AAGnC,IAAA,OAAO,IAAI,CAAC,OAAA,GAAoC,EAAE,EAAA;AAChD,QAAA,OAAO,IAAI,gBAAgB,CAAC,iBAAiB,EAAE,OAAO;aACnD,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,KAAK,KACxD,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,KAAK,CAAC;aAEnE,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,OAAO,EAAE,KAAK,KAAK,CAAC,MAAM,OAAO,CAAC,aAAa,EAAE,MAAM,KAAK;AAC/G,aAAA,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,OAAO,EAAE,IAAI,KAAI;YACjE,KAAK,MAAM,KAAK,IAAI,MAAM,OAAO,CAAC,aAAa,EAAE,EAAE;gBACjD,IAAI,MAAM,gBAAgB,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC;AAAE,oBAAA,OAAO,IAAI;YACpE;AACA,YAAA,OAAO,KAAK;AACd,QAAA,CAAC,CAAC;IACN;;AAIA;;;;;;;AAOG;AACH,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,EAAE,YAAY,CAAC,MAAM,CAAC;IACrD;;AAGA,IAAA,MAAM,kBAAkB,GAAA;AACtB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,EAAE,YAAY,CAAC,sBAAsB,CAAC;IACrE;AAEA;;;;;;;;AAQG;AACH,IAAA,MAAM,iBAAiB,GAAA;AACrB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,EAAE,YAAY,CAAC,YAAY,CAAC;IAC3D;;AAGA,IAAA,MAAM,gBAAgB,GAAA;AACpB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC;IAChF;;AAGA,IAAA,MAAM,YAAY,GAAA;AAChB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC;IAC5E;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,kBAAkB,GAAA;QACtB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,EAAE;QAClE,IAAI,CAAC,IAAI,EAAE;YACT,MAAM,IAAI,KAAK,CACb,oGAAoG;AAClG,gBAAA,mEAAmE,CACtE;QACH;AACA,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;IACxC;AAEA;;;;;;;AAOG;AACH,IAAA,MAAM,wBAAwB,GAAA;AAC5B,QAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE;QAClC,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,YAAY,CAAC,sBAAsB,CAAC,CAAC,CAAC;IACrF;;;AAKA,IAAA,MAAM,aAAa,GAAA;QACjB,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM;IACrC;;AAGA,IAAA,MAAM,aAAa,GAAA;AACjB,QAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE;AAClC,QAAA,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACvD;AAEA;;;;;;;;;;;;;;;;AAgBG;AACH,IAAA,MAAM,cAAc,GAAA;AAClB,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE;AACxC,QAAA,IAAI,KAAK,KAAK,CAAC,EAAE;YACf,MAAM,IAAI,KAAK,CACb,wGAAwG;AACtG,gBAAA,4CAA4C,CAC/C;QACH;AAEA,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;AAC9B,QAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACf,YAAA,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;AAChD,gBAAA,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,cAAc,CAAC,MAAM,MAAM;AAAE,oBAAA,OAAO,KAAK;YAC/E;YACA,MAAM,IAAI,KAAK,CACb,0GAA0G;gBACxG,yGAAyG;AACzG,gBAAA,0GAA0G,CAC7G;QACH;AAEA,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC,GAAG,GAAG,CAAC;IACvE;;AAGA,IAAA,MAAM,kBAAkB,GAAA;AACtB,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE;AACzC,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE;IAC5C;AAEA;;;;;;;;;;;;;;;;;AAiBG;AACH,IAAA,MAAM,qBAAqB,GAAA;AACzB,QAAA,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE;QACtE,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QACtC,IAAI,CAAC,KAAK,EAAE;AACV,YAAA,MAAM,IAAI,KAAK,CACb,CAAA,6FAAA,EAAgG,KAAK,CAAA,IAAA,CAAM;AACzG,gBAAA,gFAAgF,CACnF;QACH;AACA,QAAA,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB;;;AAKA,IAAA,MAAM,SAAS,GAAA;AACb,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,yBAAyB,CAAC,EAAE,MAAM,IAAI;IAC9E;;AAGA,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,EAAE,MAAM,IAAI;IACzE;;AAGA,IAAA,MAAM,WAAW,GAAA;QACf,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM;IACnC;AAEA;;;;;;;AAOG;AACH,IAAA,MAAM,YAAY,GAAA;AAChB,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;QAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC;IACrE;;AAIA;;;;;;;AAOG;AACH,IAAA,MAAM,IAAI,GAAA;AACR,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE;IACjD;;AAGA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,KAAK,EAAE;IACrD;AAEA;;;;;;;;AAQG;IACH,MAAM,IAAI,CAAC,KAAa,EAAA;AACtB,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;AAC9B,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;AAChB,YAAA,MAAM,IAAI,KAAK,CACb,CAAA,uBAAA,EAA0B,KAAK,CAAA,uEAAA,CAAyE;gBACtG,wGAAwG;AACxG,gBAAA,+EAA+E,CAClF;QACH;AACA,QAAA,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE;YACjE,MAAM,IAAI,KAAK,CACb,CAAA,uBAAA,EAA0B,KAAK,CAAA,oCAAA,EAAuC,IAAI,CAAC,MAAM,CAAA,sBAAA,CAAwB;AACvG,gBAAA,CAAA,qCAAA,EAAwC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA,CAAA,CAAG,CAC7D;QACH;AACA,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE;IAC5B;;AAIA;;;;;;AAMG;AACH,IAAA,MAAM,KAAK,GAAA;QACT,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE;IACpC;;AAGA,IAAA,MAAM,SAAS,GAAA;QACb,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE;IACxC;AAEA;;;;;;;;;;;;;;;;;;AAkBG;AACH,IAAA,MAAM,KAAK,GAAA;QACT,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;QACrC,IAAI,CAAC,KAAK,EAAE;YACV,MAAM,IAAI,KAAK,CACb,wGAAwG;gBACtG,sGAAsG;AACtG,gBAAA,uBAAuB,CAC1B;QACH;AACA,QAAA,OAAO,KAAK,CAAC,KAAK,EAAE;IACtB;AAEA;;;;;;;AAOG;AACH,IAAA,MAAM,IAAI,GAAA;QACR,KAAK,MAAM,OAAO,IAAI,MAAM,IAAI,CAAC,QAAQ,EAAE,EAAE;AAC3C,YAAA,IAAI,MAAM,OAAO,CAAC,SAAS,EAAE;AAAE,gBAAA,OAAO,OAAO,CAAC,IAAI,EAAE;QACtD;QACA,MAAM,IAAI,KAAK,CACb,4GAA4G;AAC1G,YAAA,0FAA0F,CAC7F;IACH;;AAGA,IAAA,MAAM,SAAS,GAAA;QACb,KAAK,MAAM,OAAO,IAAI,MAAM,IAAI,CAAC,QAAQ,EAAE,EAAE;AAC3C,YAAA,IAAI,MAAM,OAAO,CAAC,SAAS,EAAE;AAAE,gBAAA,OAAO,IAAI;QAC5C;AACA,QAAA,OAAO,KAAK;IACd;;;AAKQ,IAAA,MAAM,QAAQ,GAAA;AACpB,QAAA,OAAO,IAAI,CAAC,UAAU,CAAC,wBAAwB,CAAC,EAAE;IACpD;;AAGQ,IAAA,MAAM,KAAK,GAAA;AACjB,QAAA,OAAO,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE;IACjD;AAEQ,IAAA,MAAM,MAAM,GAAA;AAClB,QAAA,OAAO,IAAI,CAAC,aAAa,CAAC,mBAAmB,CAAC,EAAE;IAClD;AAEQ,IAAA,MAAM,IAAI,GAAA;AAChB,QAAA,OAAO,IAAI,CAAC,aAAa,CAAC,mBAAmB,CAAC,EAAE;IAClD;AAEA;;;AAGG;AACK,IAAA,MAAM,QAAQ,GAAA;QACpB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,mBAAmB,CAAC,EAAE;AAC5D,QAAA,OAAO,CAAC,GAAG,IAAI,EAAE,IAAI,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1C;;AAGQ,IAAA,MAAM,GAAG,CAAC,IAAqB,EAAE,MAAc,EAAA;AACrD,QAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,CAAA,mBAAA,EAAsB,IAAI,CAAA,CAAE,CAAC,EAAE;QAC5E,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,MAAM,IAAI,KAAK,CACb,qBAAqB,MAAM,CAAA,6BAAA,EAAgC,IAAI,CAAA,qCAAA,CAAuC;AACpG,gBAAA,gFAAgF,CACnF;QACH;AACA,QAAA,OAAO,MAAM;IACf;;;AC3aF;;AAEG;;;;"}
@@ -1,7 +1,9 @@
1
+ import { Directionality } from '@angular/cdk/bidi';
1
2
  import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
3
+ import { isPlatformBrowser } from '@angular/common';
2
4
  import * as i0 from '@angular/core';
3
- import { ViewEncapsulation, Component, input, model, contentChildren, computed, signal, inject, DestroyRef, effect } from '@angular/core';
4
- import { useI18nText } from 'ngwr/i18n';
5
+ import { ViewEncapsulation, Component, input, model, contentChildren, computed, signal, inject, DestroyRef, PLATFORM_ID, effect } from '@angular/core';
6
+ import { useI18nText, useI18nFormatter } from 'ngwr/i18n';
5
7
 
6
8
  /**
7
9
  * @license
@@ -49,7 +51,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
49
51
  * @see https://ngwr.dev/reference/components/carousel
50
52
  */
51
53
  class WrCarousel {
52
- /** Active slide index. Two-way bindable. @default 0 */
53
54
  /** Accessible name of the previous-slide button. Falls back to `carousel.prev`. */
54
55
  prevLabel = input(null, /* @ts-ignore */
55
56
  ...(ngDevMode ? [{ debugName: "prevLabel" }] : /* istanbul ignore next */ []));
@@ -62,6 +63,14 @@ class WrCarousel {
62
63
  resolvedPrevLabel = useI18nText(this.prevLabel, 'carousel.prev', 'Previous slide');
63
64
  resolvedNextLabel = useI18nText(this.nextLabel, 'carousel.next', 'Next slide');
64
65
  resolvedPaginationLabel = useI18nText(this.paginationLabel, 'carousel.pagination', 'Carousel pagination');
66
+ /** Accessible name of the carousel itself. Falls back to `carousel.label`. */
67
+ ariaLabel = input(null, /* @ts-ignore */
68
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
69
+ resolvedAriaLabel = useI18nText(this.ariaLabel, 'carousel.label', 'Carousel');
70
+ // The three labels above route through the catalog; this one was a hard-coded
71
+ // English template, so a localized app got two languages in one pagination strip.
72
+ slideLabel = useI18nFormatter('carousel.goToSlide', 'Go to slide {{index}}');
73
+ /** Active slide index. Two-way bindable. @default 0 */
65
74
  active = model(0, /* @ts-ignore */
66
75
  ...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
67
76
  /** Show prev / next arrow buttons. @default true */
@@ -83,9 +92,26 @@ class WrCarousel {
83
92
  ...(ngDevMode ? [{ debugName: "dragX" }] : /* istanbul ignore next */ []));
84
93
  dragging = signal(false, /* @ts-ignore */
85
94
  ...(ngDevMode ? [{ debugName: "dragging" }] : /* istanbul ignore next */ []));
95
+ dir = inject(Directionality, { optional: true });
96
+ /**
97
+ * Reading direction of the track. `Directionality` is root-provided, so this
98
+ * always resolves — `optional` only guards a consumer who has deliberately
99
+ * torn the provider out. It reads the document once at construction; a
100
+ * subtree that overrides the direction does it with the CDK's `Dir`
101
+ * directive, which writes `valueSignal`, so `trackStyle` re-renders instead
102
+ * of leaving the track parked on the old side.
103
+ */
104
+ isRtl = computed(() => this.dir?.valueSignal() === 'rtl', /* @ts-ignore */
105
+ ...(ngDevMode ? [{ debugName: "isRtl" }] : /* istanbul ignore next */ []));
86
106
  /** CSS transform for the track — the per-slide offset plus any live drag. */
87
107
  trackStyle = computed(() => {
88
- const base = -this.active() * 100;
108
+ // `translateX` is PHYSICAL while the slides are laid out on the inline axis:
109
+ // under `dir="rtl"` the flex track runs right-to-left, so slide 1 sits to the
110
+ // LEFT of slide 0 and reaching it means moving the track the other way. Left
111
+ // unsigned, every RTL carousel translated itself off into blank space.
112
+ const base = (this.isRtl() ? 1 : -1) * this.active() * 100;
113
+ // The drag stays physical on purpose: it is the finger's own displacement,
114
+ // and the track follows the finger in both directions.
89
115
  const drag = this.dragX();
90
116
  return drag === 0 ? `translateX(${base}%)` : `translateX(calc(${base}% + ${drag}px))`;
91
117
  }, /* @ts-ignore */
@@ -94,25 +120,39 @@ class WrCarousel {
94
120
  paused = signal(false, /* @ts-ignore */
95
121
  ...(ngDevMode ? [{ debugName: "paused" }] : /* istanbul ignore next */ []));
96
122
  destroyRef = inject(DestroyRef);
123
+ isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
97
124
  constructor() {
98
125
  effect(() => {
99
126
  if (this.timer)
100
127
  clearInterval(this.timer);
101
128
  this.timer = null;
102
- if (!this.autoplay() || this.paused() || this.count() < 2)
129
+ // `isBrowser` first: without it the prerender ran the timer too, doing work
130
+ // nobody will ever see on a slide index that then gets serialized.
131
+ if (!this.isBrowser || !this.autoplay() || this.paused() || this.count() < 2)
103
132
  return;
104
133
  const interval = this.intervalMs();
105
134
  this.timer = setInterval(() => this.next(), interval);
106
135
  });
136
+ // `active` is a plain `model`, so `[(active)]` and a shrinking slide list both
137
+ // write into it unchecked — a filtered list left it pointing past the end,
138
+ // translating the track into blank space with no dot lit.
139
+ effect(() => {
140
+ const max = this.count() - 1;
141
+ if (max < 0)
142
+ return;
143
+ const clamped = Math.min(Math.max(0, this.active()), max);
144
+ if (clamped !== this.active())
145
+ this.active.set(clamped);
146
+ });
107
147
  this.destroyRef.onDestroy(() => {
108
148
  if (this.timer)
109
149
  clearInterval(this.timer);
110
150
  });
111
151
  }
112
- onMouseEnter() {
152
+ onPauseIn() {
113
153
  this.paused.set(true);
114
154
  }
115
- onMouseLeave() {
155
+ onPauseOut() {
116
156
  this.paused.set(false);
117
157
  }
118
158
  // Imperative
@@ -135,7 +175,9 @@ class WrCarousel {
135
175
  this.goTo(this.active() - 1);
136
176
  }
137
177
  // Swipe navigation — the track follows the finger; releasing past ~20% of the
138
- // viewport advances a slide (left = next, right = prev), otherwise snaps back.
178
+ // viewport advances a slide, otherwise snaps back. Which way that is follows
179
+ // the reading direction: dragging toward the inline start (left in LTR, right
180
+ // in RTL) pulls the next slide into view.
139
181
  swipeStartX = 0;
140
182
  onSwipeStart(event) {
141
183
  const touch = event.touches[0];
@@ -161,18 +203,30 @@ class WrCarousel {
161
203
  this.dragX.set(0);
162
204
  this.paused.set(false);
163
205
  const threshold = (viewport.offsetWidth || 0) * 0.2;
164
- if (dx <= -threshold)
206
+ // `dx` is a physical delta. The next slide sits to the physical RIGHT in LTR
207
+ // and to the LEFT in RTL, so the drag that pulls it into view — and with it
208
+ // the sign that advances — turns around with the direction. The buttons keep
209
+ // their semantics either way; only the gesture is physical.
210
+ const advance = this.isRtl() ? dx >= threshold : dx <= -threshold;
211
+ const retreat = this.isRtl() ? dx <= -threshold : dx >= threshold;
212
+ if (advance)
165
213
  this.next();
166
- else if (dx >= threshold)
214
+ else if (retreat)
167
215
  this.prev();
168
216
  }
169
217
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrCarousel, deps: [], target: i0.ɵɵFactoryTarget.Component });
170
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: WrCarousel, isStandalone: true, selector: "wr-carousel", inputs: { prevLabel: { classPropertyName: "prevLabel", publicName: "prevLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, paginationLabel: { classPropertyName: "paginationLabel", publicName: "paginationLabel", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, showArrows: { classPropertyName: "showArrows", publicName: "showArrows", isSignal: true, isRequired: false, transformFunction: null }, showDots: { classPropertyName: "showDots", publicName: "showDots", isSignal: true, isRequired: false, transformFunction: null }, autoplay: { classPropertyName: "autoplay", publicName: "autoplay", isSignal: true, isRequired: false, transformFunction: null }, intervalMs: { classPropertyName: "intervalMs", publicName: "intervalMs", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { active: "activeChange" }, host: { classAttribute: "wr-carousel" }, queries: [{ propertyName: "slides", predicate: WrCarouselSlide, isSignal: true }], ngImport: i0, template: "<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", encapsulation: i0.ViewEncapsulation.None });
218
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: WrCarousel, isStandalone: true, selector: "wr-carousel", inputs: { prevLabel: { classPropertyName: "prevLabel", publicName: "prevLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, paginationLabel: { classPropertyName: "paginationLabel", publicName: "paginationLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, showArrows: { classPropertyName: "showArrows", publicName: "showArrows", isSignal: true, isRequired: false, transformFunction: null }, showDots: { classPropertyName: "showDots", publicName: "showDots", isSignal: true, isRequired: false, transformFunction: null }, autoplay: { classPropertyName: "autoplay", publicName: "autoplay", isSignal: true, isRequired: false, transformFunction: null }, intervalMs: { classPropertyName: "intervalMs", publicName: "intervalMs", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { active: "activeChange" }, host: { listeners: { "mouseenter": "onPauseIn()", "mouseleave": "onPauseOut()", "focusin": "onPauseIn()", "focusout": "onPauseOut()" }, classAttribute: "wr-carousel" }, queries: [{ propertyName: "slides", predicate: WrCarouselSlide, isSignal: true }], ngImport: i0, template: "<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", encapsulation: i0.ViewEncapsulation.None });
171
219
  }
172
220
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrCarousel, decorators: [{
173
221
  type: Component,
174
- args: [{ selector: 'wr-carousel', encapsulation: ViewEncapsulation.None, host: { class: 'wr-carousel' }, template: "<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" }]
175
- }], ctorParameters: () => [], propDecorators: { prevLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "prevLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], paginationLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationLabel", required: false }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }, { type: i0.Output, args: ["activeChange"] }], showArrows: [{ type: i0.Input, args: [{ isSignal: true, alias: "showArrows", required: false }] }], showDots: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDots", required: false }] }], autoplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplay", required: false }] }], intervalMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "intervalMs", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], slides: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => WrCarouselSlide), { isSignal: true }] }] } });
222
+ args: [{ selector: 'wr-carousel', encapsulation: ViewEncapsulation.None, host: {
223
+ class: 'wr-carousel',
224
+ '(mouseenter)': 'onPauseIn()',
225
+ '(mouseleave)': 'onPauseOut()',
226
+ '(focusin)': 'onPauseIn()',
227
+ '(focusout)': 'onPauseOut()',
228
+ }, template: "<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" }]
229
+ }], ctorParameters: () => [], propDecorators: { prevLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "prevLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], paginationLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationLabel", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }, { type: i0.Output, args: ["activeChange"] }], showArrows: [{ type: i0.Input, args: [{ isSignal: true, alias: "showArrows", required: false }] }], showDots: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDots", required: false }] }], autoplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplay", required: false }] }], intervalMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "intervalMs", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], slides: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => WrCarouselSlide), { isSignal: true }] }] } });
176
230
 
177
231
  /**
178
232
  * Generated bundle index. Do not edit.