ngwr 10.2.0 → 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 (471) 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 +38 -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 +15 -5
  19. package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
  20. package/fesm2022/ngwr-affix.mjs +43 -16
  21. package/fesm2022/ngwr-affix.mjs.map +1 -1
  22. package/fesm2022/ngwr-alert.mjs +3 -3
  23. package/fesm2022/ngwr-anchor.mjs +20 -8
  24. package/fesm2022/ngwr-anchor.mjs.map +1 -1
  25. package/fesm2022/ngwr-aurora.mjs +4 -4
  26. package/fesm2022/ngwr-aurora.mjs.map +1 -1
  27. package/fesm2022/ngwr-avatar.mjs +33 -9
  28. package/fesm2022/ngwr-avatar.mjs.map +1 -1
  29. package/fesm2022/ngwr-back-top.mjs +8 -4
  30. package/fesm2022/ngwr-back-top.mjs.map +1 -1
  31. package/fesm2022/ngwr-badge.mjs +6 -6
  32. package/fesm2022/ngwr-badge.mjs.map +1 -1
  33. package/fesm2022/ngwr-bar-chart.mjs +32 -11
  34. package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
  35. package/fesm2022/ngwr-blur-text.mjs +4 -4
  36. package/fesm2022/ngwr-blur-text.mjs.map +1 -1
  37. package/fesm2022/ngwr-border-glow.mjs +4 -4
  38. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  39. package/fesm2022/ngwr-breadcrumbs.mjs +9 -8
  40. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  41. package/fesm2022/ngwr-burger.mjs +11 -6
  42. package/fesm2022/ngwr-burger.mjs.map +1 -1
  43. package/fesm2022/ngwr-button-testing.mjs +96 -0
  44. package/fesm2022/ngwr-button-testing.mjs.map +1 -0
  45. package/fesm2022/ngwr-button.mjs +89 -24
  46. package/fesm2022/ngwr-button.mjs.map +1 -1
  47. package/fesm2022/ngwr-calendar-heatmap.mjs +42 -10
  48. package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
  49. package/fesm2022/ngwr-calendar.mjs +108 -9
  50. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  51. package/fesm2022/ngwr-card.mjs +10 -10
  52. package/fesm2022/ngwr-card.mjs.map +1 -1
  53. package/fesm2022/ngwr-carousel-testing.mjs +377 -0
  54. package/fesm2022/ngwr-carousel-testing.mjs.map +1 -0
  55. package/fesm2022/ngwr-carousel.mjs +72 -18
  56. package/fesm2022/ngwr-carousel.mjs.map +1 -1
  57. package/fesm2022/ngwr-cascader-testing.mjs +534 -0
  58. package/fesm2022/ngwr-cascader-testing.mjs.map +1 -0
  59. package/fesm2022/ngwr-cascader.mjs +4 -4
  60. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  61. package/fesm2022/ngwr-checkbox-testing.mjs +90 -0
  62. package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -0
  63. package/fesm2022/ngwr-checkbox.mjs +15 -9
  64. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  65. package/fesm2022/ngwr-circular-text.mjs +4 -4
  66. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  67. package/fesm2022/ngwr-click-spark.mjs +4 -4
  68. package/fesm2022/ngwr-click-spark.mjs.map +1 -1
  69. package/fesm2022/ngwr-clipboard.mjs +18 -4
  70. package/fesm2022/ngwr-clipboard.mjs.map +1 -1
  71. package/fesm2022/ngwr-collapse-testing.mjs +368 -0
  72. package/fesm2022/ngwr-collapse-testing.mjs.map +1 -0
  73. package/fesm2022/ngwr-collapse.mjs +9 -9
  74. package/fesm2022/ngwr-color-picker.mjs +139 -19
  75. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  76. package/fesm2022/ngwr-command-palette-testing.mjs +589 -0
  77. package/fesm2022/ngwr-command-palette-testing.mjs.map +1 -0
  78. package/fesm2022/ngwr-command-palette.mjs +60 -10
  79. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  80. package/fesm2022/ngwr-compare.mjs +105 -15
  81. package/fesm2022/ngwr-compare.mjs.map +1 -1
  82. package/fesm2022/ngwr-confetti.mjs +3 -3
  83. package/fesm2022/ngwr-config.mjs +106 -0
  84. package/fesm2022/ngwr-config.mjs.map +1 -0
  85. package/fesm2022/ngwr-context-menu-testing.mjs +631 -0
  86. package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -0
  87. package/fesm2022/ngwr-context-menu.mjs +104 -18
  88. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  89. package/fesm2022/ngwr-cookie.mjs +8 -4
  90. package/fesm2022/ngwr-cookie.mjs.map +1 -1
  91. package/fesm2022/ngwr-counter.mjs +17 -9
  92. package/fesm2022/ngwr-counter.mjs.map +1 -1
  93. package/fesm2022/ngwr-date-adapter-fns.mjs +3 -3
  94. package/fesm2022/ngwr-date-adapter-luxon.mjs +55 -7
  95. package/fesm2022/ngwr-date-adapter-luxon.mjs.map +1 -1
  96. package/fesm2022/ngwr-date-adapter.mjs +57 -11
  97. package/fesm2022/ngwr-date-adapter.mjs.map +1 -1
  98. package/fesm2022/ngwr-date-picker-testing.mjs +766 -0
  99. package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -0
  100. package/fesm2022/ngwr-date-picker.mjs +409 -57
  101. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  102. package/fesm2022/ngwr-decrypt-text.mjs +30 -12
  103. package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
  104. package/fesm2022/ngwr-density.mjs +6 -6
  105. package/fesm2022/ngwr-descriptions.mjs +6 -6
  106. package/fesm2022/ngwr-dialog-testing.mjs +89 -0
  107. package/fesm2022/ngwr-dialog-testing.mjs.map +1 -0
  108. package/fesm2022/ngwr-dialog.mjs +33 -17
  109. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  110. package/fesm2022/ngwr-directives.mjs +48 -24
  111. package/fesm2022/ngwr-directives.mjs.map +1 -1
  112. package/fesm2022/ngwr-divider.mjs +3 -3
  113. package/fesm2022/ngwr-donut-chart.mjs +24 -7
  114. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  115. package/fesm2022/ngwr-drag-drop.mjs +7 -7
  116. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  117. package/fesm2022/ngwr-drawer-testing.mjs +250 -0
  118. package/fesm2022/ngwr-drawer-testing.mjs.map +1 -0
  119. package/fesm2022/ngwr-drawer.mjs +37 -19
  120. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  121. package/fesm2022/ngwr-dropdown-testing.mjs +291 -0
  122. package/fesm2022/ngwr-dropdown-testing.mjs.map +1 -0
  123. package/fesm2022/ngwr-dropdown.mjs +19 -11
  124. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  125. package/fesm2022/ngwr-empty.mjs +26 -9
  126. package/fesm2022/ngwr-empty.mjs.map +1 -1
  127. package/fesm2022/ngwr-event-calendar.mjs +62 -15
  128. package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
  129. package/fesm2022/ngwr-falling-text.mjs +4 -4
  130. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  131. package/fesm2022/ngwr-file-upload-testing.mjs +332 -0
  132. package/fesm2022/ngwr-file-upload-testing.mjs.map +1 -0
  133. package/fesm2022/ngwr-file-upload.mjs +3 -3
  134. package/fesm2022/ngwr-form-testing.mjs +451 -0
  135. package/fesm2022/ngwr-form-testing.mjs.map +1 -0
  136. package/fesm2022/ngwr-form.mjs +28 -12
  137. package/fesm2022/ngwr-form.mjs.map +1 -1
  138. package/fesm2022/ngwr-fuzzy-text.mjs +11 -4
  139. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  140. package/fesm2022/ngwr-gauge.mjs +21 -7
  141. package/fesm2022/ngwr-gauge.mjs.map +1 -1
  142. package/fesm2022/ngwr-glitch-text.mjs +4 -4
  143. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  144. package/fesm2022/ngwr-gradient-text.mjs +4 -4
  145. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  146. package/fesm2022/ngwr-hotkey.mjs +31 -10
  147. package/fesm2022/ngwr-hotkey.mjs.map +1 -1
  148. package/fesm2022/ngwr-i18n-en.mjs +61 -0
  149. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  150. package/fesm2022/ngwr-i18n-ru.mjs +59 -0
  151. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  152. package/fesm2022/ngwr-i18n.mjs +9 -9
  153. package/fesm2022/ngwr-icon.mjs +6 -6
  154. package/fesm2022/ngwr-image-cropper.mjs +26 -3
  155. package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
  156. package/fesm2022/ngwr-input-number-testing.mjs +306 -0
  157. package/fesm2022/ngwr-input-number-testing.mjs.map +1 -0
  158. package/fesm2022/ngwr-input-number.mjs +37 -5
  159. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  160. package/fesm2022/ngwr-input-otp-testing.mjs +419 -0
  161. package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -0
  162. package/fesm2022/ngwr-input-otp.mjs +39 -8
  163. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  164. package/fesm2022/ngwr-input-testing.mjs +102 -0
  165. package/fesm2022/ngwr-input-testing.mjs.map +1 -0
  166. package/fesm2022/ngwr-input.mjs +62 -25
  167. package/fesm2022/ngwr-input.mjs.map +1 -1
  168. package/fesm2022/ngwr-keyboard.mjs +3 -3
  169. package/fesm2022/ngwr-knob.mjs +46 -10
  170. package/fesm2022/ngwr-knob.mjs.map +1 -1
  171. package/fesm2022/ngwr-layout.mjs +36 -20
  172. package/fesm2022/ngwr-layout.mjs.map +1 -1
  173. package/fesm2022/ngwr-lightbox.mjs +35 -8
  174. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  175. package/fesm2022/ngwr-line-chart.mjs +19 -6
  176. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  177. package/fesm2022/ngwr-list.mjs +14 -9
  178. package/fesm2022/ngwr-list.mjs.map +1 -1
  179. package/fesm2022/ngwr-loading-bar.mjs +71 -31
  180. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  181. package/fesm2022/ngwr-markdown-testing.mjs +516 -0
  182. package/fesm2022/ngwr-markdown-testing.mjs.map +1 -0
  183. package/fesm2022/ngwr-markdown.mjs +1492 -0
  184. package/fesm2022/ngwr-markdown.mjs.map +1 -0
  185. package/fesm2022/ngwr-marquee.mjs +19 -8
  186. package/fesm2022/ngwr-marquee.mjs.map +1 -1
  187. package/fesm2022/ngwr-media.mjs +3 -3
  188. package/fesm2022/ngwr-mention-testing.mjs +513 -0
  189. package/fesm2022/ngwr-mention-testing.mjs.map +1 -0
  190. package/fesm2022/ngwr-mention.mjs +16 -7
  191. package/fesm2022/ngwr-mention.mjs.map +1 -1
  192. package/fesm2022/ngwr-meta.mjs +28 -13
  193. package/fesm2022/ngwr-meta.mjs.map +1 -1
  194. package/fesm2022/ngwr-meter-group.mjs +22 -8
  195. package/fesm2022/ngwr-meter-group.mjs.map +1 -1
  196. package/fesm2022/ngwr-overlay.mjs +57 -8
  197. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  198. package/fesm2022/ngwr-page-header.mjs +3 -3
  199. package/fesm2022/ngwr-pagination-testing.mjs +389 -0
  200. package/fesm2022/ngwr-pagination-testing.mjs.map +1 -0
  201. package/fesm2022/ngwr-pagination.mjs +27 -11
  202. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  203. package/fesm2022/ngwr-pipes.mjs +21 -21
  204. package/fesm2022/ngwr-platform.mjs +9 -9
  205. package/fesm2022/ngwr-popconfirm-testing.mjs +309 -0
  206. package/fesm2022/ngwr-popconfirm-testing.mjs.map +1 -0
  207. package/fesm2022/ngwr-popconfirm.mjs +99 -21
  208. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  209. package/fesm2022/ngwr-popover-testing.mjs +316 -0
  210. package/fesm2022/ngwr-popover-testing.mjs.map +1 -0
  211. package/fesm2022/ngwr-popover.mjs +48 -10
  212. package/fesm2022/ngwr-popover.mjs.map +1 -1
  213. package/fesm2022/ngwr-progress.mjs +3 -3
  214. package/fesm2022/ngwr-pull-to-refresh.mjs +19 -4
  215. package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -1
  216. package/fesm2022/ngwr-qr.mjs +15 -5
  217. package/fesm2022/ngwr-qr.mjs.map +1 -1
  218. package/fesm2022/ngwr-radio-testing.mjs +392 -0
  219. package/fesm2022/ngwr-radio-testing.mjs.map +1 -0
  220. package/fesm2022/ngwr-radio.mjs +16 -9
  221. package/fesm2022/ngwr-radio.mjs.map +1 -1
  222. package/fesm2022/ngwr-rating-testing.mjs +384 -0
  223. package/fesm2022/ngwr-rating-testing.mjs.map +1 -0
  224. package/fesm2022/ngwr-rating.mjs +40 -5
  225. package/fesm2022/ngwr-rating.mjs.map +1 -1
  226. package/fesm2022/ngwr-result.mjs +12 -12
  227. package/fesm2022/ngwr-rotating-text.mjs +3 -3
  228. package/fesm2022/ngwr-scroll.mjs +3 -3
  229. package/fesm2022/ngwr-segmented-testing.mjs +512 -0
  230. package/fesm2022/ngwr-segmented-testing.mjs.map +1 -0
  231. package/fesm2022/ngwr-segmented.mjs +3 -3
  232. package/fesm2022/ngwr-select-testing.mjs +268 -0
  233. package/fesm2022/ngwr-select-testing.mjs.map +1 -0
  234. package/fesm2022/ngwr-select.mjs +96 -25
  235. package/fesm2022/ngwr-select.mjs.map +1 -1
  236. package/fesm2022/ngwr-shiny-text.mjs +7 -7
  237. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  238. package/fesm2022/ngwr-sidebar.mjs +67 -14
  239. package/fesm2022/ngwr-sidebar.mjs.map +1 -1
  240. package/fesm2022/ngwr-skeleton.mjs +3 -3
  241. package/fesm2022/ngwr-slider-testing.mjs +478 -0
  242. package/fesm2022/ngwr-slider-testing.mjs.map +1 -0
  243. package/fesm2022/ngwr-slider.mjs +59 -15
  244. package/fesm2022/ngwr-slider.mjs.map +1 -1
  245. package/fesm2022/ngwr-sparkline.mjs +28 -8
  246. package/fesm2022/ngwr-sparkline.mjs.map +1 -1
  247. package/fesm2022/ngwr-speed-dial.mjs +39 -6
  248. package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
  249. package/fesm2022/ngwr-spinner.mjs +14 -5
  250. package/fesm2022/ngwr-spinner.mjs.map +1 -1
  251. package/fesm2022/ngwr-splash-cursor.mjs +4 -4
  252. package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
  253. package/fesm2022/ngwr-split-text.mjs +4 -4
  254. package/fesm2022/ngwr-split-text.mjs.map +1 -1
  255. package/fesm2022/ngwr-splitter.mjs +72 -11
  256. package/fesm2022/ngwr-splitter.mjs.map +1 -1
  257. package/fesm2022/ngwr-spotlight-card.mjs +7 -7
  258. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  259. package/fesm2022/ngwr-squircle.mjs +6 -6
  260. package/fesm2022/ngwr-star-border.mjs +4 -4
  261. package/fesm2022/ngwr-star-border.mjs.map +1 -1
  262. package/fesm2022/ngwr-statistic.mjs +33 -16
  263. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  264. package/fesm2022/ngwr-stepper-testing.mjs +477 -0
  265. package/fesm2022/ngwr-stepper-testing.mjs.map +1 -0
  266. package/fesm2022/ngwr-stepper.mjs +6 -6
  267. package/fesm2022/ngwr-storage.mjs +27 -17
  268. package/fesm2022/ngwr-storage.mjs.map +1 -1
  269. package/fesm2022/ngwr-switch-testing.mjs +77 -0
  270. package/fesm2022/ngwr-switch-testing.mjs.map +1 -0
  271. package/fesm2022/ngwr-switch.mjs +12 -6
  272. package/fesm2022/ngwr-switch.mjs.map +1 -1
  273. package/fesm2022/ngwr-table-testing.mjs +580 -0
  274. package/fesm2022/ngwr-table-testing.mjs.map +1 -0
  275. package/fesm2022/ngwr-table.mjs +105 -44
  276. package/fesm2022/ngwr-table.mjs.map +1 -1
  277. package/fesm2022/ngwr-tabs-testing.mjs +617 -0
  278. package/fesm2022/ngwr-tabs-testing.mjs.map +1 -0
  279. package/fesm2022/ngwr-tabs.mjs +44 -12
  280. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  281. package/fesm2022/ngwr-textarea-testing.mjs +238 -0
  282. package/fesm2022/ngwr-textarea-testing.mjs.map +1 -0
  283. package/fesm2022/ngwr-textarea.mjs +35 -7
  284. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  285. package/fesm2022/ngwr-theme.mjs +3 -3
  286. package/fesm2022/ngwr-tilt-card.mjs +7 -7
  287. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  288. package/fesm2022/ngwr-timeline.mjs +6 -6
  289. package/fesm2022/ngwr-toast-testing.mjs +101 -0
  290. package/fesm2022/ngwr-toast-testing.mjs.map +1 -0
  291. package/fesm2022/ngwr-toast.mjs +55 -21
  292. package/fesm2022/ngwr-toast.mjs.map +1 -1
  293. package/fesm2022/ngwr-toolbar.mjs +3 -3
  294. package/fesm2022/ngwr-tour.mjs +67 -15
  295. package/fesm2022/ngwr-tour.mjs.map +1 -1
  296. package/fesm2022/ngwr-transfer-testing.mjs +538 -0
  297. package/fesm2022/ngwr-transfer-testing.mjs.map +1 -0
  298. package/fesm2022/ngwr-transfer.mjs +47 -16
  299. package/fesm2022/ngwr-transfer.mjs.map +1 -1
  300. package/fesm2022/ngwr-tree-testing.mjs +734 -0
  301. package/fesm2022/ngwr-tree-testing.mjs.map +1 -0
  302. package/fesm2022/ngwr-tree.mjs +75 -9
  303. package/fesm2022/ngwr-tree.mjs.map +1 -1
  304. package/fesm2022/ngwr-typewriter.mjs +7 -5
  305. package/fesm2022/ngwr-typewriter.mjs.map +1 -1
  306. package/fesm2022/ngwr-typography.mjs +3 -3
  307. package/fesm2022/ngwr-version.mjs +1 -1
  308. package/fesm2022/ngwr-version.mjs.map +1 -1
  309. package/fesm2022/ngwr-virtual-scroll.mjs +33 -7
  310. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  311. package/fesm2022/ngwr-waves.mjs +5 -5
  312. package/fesm2022/ngwr-waves.mjs.map +1 -1
  313. package/fesm2022/ngwr-window.mjs +88 -18
  314. package/fesm2022/ngwr-window.mjs.map +1 -1
  315. package/gauge/styles/_index.scss +1 -1
  316. package/glitch-text/styles/_index.scss +4 -0
  317. package/i18n/en.json +56 -0
  318. package/i18n/ru.json +56 -0
  319. package/image-cropper/styles/_index.scss +13 -1
  320. package/input/styles/_index.scss +2 -2
  321. package/input-number/styles/_index.scss +7 -2
  322. package/knob/styles/_index.scss +8 -1
  323. package/layout/styles/_index.scss +3 -3
  324. package/lightbox/styles/_index.scss +10 -2
  325. package/line-chart/styles/_index.scss +6 -0
  326. package/llms-full.txt +151 -4
  327. package/llms.txt +57 -8
  328. package/loading-bar/styles/_index.scss +1 -2
  329. package/markdown/styles/_index.scss +296 -0
  330. package/marquee/styles/_index.scss +12 -0
  331. package/mcp/api.js +512 -0
  332. package/mcp/catalog.js +157 -0
  333. package/mcp/server.js +273 -0
  334. package/mcp/tools.js +366 -0
  335. package/meter-group/styles/_index.scss +1 -1
  336. package/package.json +186 -35
  337. package/pagination/styles/_index.scss +6 -6
  338. package/popover/styles/_index.scss +37 -5
  339. package/rating/styles/_index.scss +10 -0
  340. package/schematics/use/symbol-map.json +2 -0
  341. package/segmented/styles/_index.scss +7 -0
  342. package/select/styles/_index.scss +29 -9
  343. package/sidebar/styles/_index.scss +30 -5
  344. package/slider/styles/_index.scss +15 -0
  345. package/speed-dial/styles/_index.scss +20 -0
  346. package/split-text/styles/_index.scss +13 -0
  347. package/star-border/styles/_index.scss +2 -0
  348. package/stepper/styles/_index.scss +1 -1
  349. package/styles/_grid.scss +4 -4
  350. package/styles.scss +1 -0
  351. package/switch/styles/_index.scss +5 -3
  352. package/table/styles/_index.scss +22 -11
  353. package/tabs/styles/_index.scss +11 -1
  354. package/textarea/styles/_index.scss +5 -0
  355. package/theme/styles/_colors.scss +29 -13
  356. package/theme/styles/_dark.scss +11 -3
  357. package/theme/styles/_mixins.scss +3 -0
  358. package/timeline/styles/_index.scss +2 -2
  359. package/toast/styles/_index.scss +17 -8
  360. package/toolbar/styles/_index.scss +3 -3
  361. package/tour/styles/_index.scss +7 -1
  362. package/tree/styles/_index.scss +5 -3
  363. package/types/ngwr-action-sheet.d.ts +9 -1
  364. package/types/ngwr-affix.d.ts +7 -1
  365. package/types/ngwr-anchor.d.ts +8 -1
  366. package/types/ngwr-avatar.d.ts +13 -3
  367. package/types/ngwr-bar-chart.d.ts +16 -0
  368. package/types/ngwr-burger.d.ts +6 -2
  369. package/types/ngwr-button-testing.d.ts +85 -0
  370. package/types/ngwr-button.d.ts +58 -10
  371. package/types/ngwr-calendar-heatmap.d.ts +16 -2
  372. package/types/ngwr-calendar.d.ts +37 -1
  373. package/types/ngwr-carousel-testing.d.ts +257 -0
  374. package/types/ngwr-carousel.d.ts +20 -4
  375. package/types/ngwr-cascader-testing.d.ts +392 -0
  376. package/types/ngwr-checkbox-testing.d.ts +77 -0
  377. package/types/ngwr-checkbox.d.ts +7 -2
  378. package/types/ngwr-clipboard.d.ts +8 -1
  379. package/types/ngwr-collapse-testing.d.ts +290 -0
  380. package/types/ngwr-color-picker.d.ts +20 -11
  381. package/types/ngwr-command-palette-testing.d.ts +437 -0
  382. package/types/ngwr-command-palette.d.ts +25 -2
  383. package/types/ngwr-compare.d.ts +50 -2
  384. package/types/ngwr-config.d.ts +176 -0
  385. package/types/ngwr-context-menu-testing.d.ts +401 -0
  386. package/types/ngwr-context-menu.d.ts +65 -17
  387. package/types/ngwr-counter.d.ts +6 -1
  388. package/types/ngwr-date-adapter-luxon.d.ts +26 -0
  389. package/types/ngwr-date-picker-testing.d.ts +518 -0
  390. package/types/ngwr-date-picker.d.ts +128 -8
  391. package/types/ngwr-dialog-testing.d.ts +79 -0
  392. package/types/ngwr-dialog.d.ts +13 -0
  393. package/types/ngwr-directives.d.ts +10 -1
  394. package/types/ngwr-donut-chart.d.ts +8 -1
  395. package/types/ngwr-drawer-testing.d.ts +196 -0
  396. package/types/ngwr-drawer.d.ts +15 -0
  397. package/types/ngwr-dropdown-testing.d.ts +202 -0
  398. package/types/ngwr-dropdown.d.ts +7 -1
  399. package/types/ngwr-empty.d.ts +19 -4
  400. package/types/ngwr-event-calendar.d.ts +26 -1
  401. package/types/ngwr-file-upload-testing.d.ts +194 -0
  402. package/types/ngwr-form-testing.d.ts +379 -0
  403. package/types/ngwr-form.d.ts +17 -0
  404. package/types/ngwr-gauge.d.ts +13 -1
  405. package/types/ngwr-hotkey.d.ts +2 -0
  406. package/types/ngwr-image-cropper.d.ts +10 -0
  407. package/types/ngwr-input-number-testing.d.ts +226 -0
  408. package/types/ngwr-input-number.d.ts +29 -1
  409. package/types/ngwr-input-otp-testing.d.ts +299 -0
  410. package/types/ngwr-input-otp.d.ts +23 -2
  411. package/types/ngwr-input-testing.d.ts +84 -0
  412. package/types/ngwr-input.d.ts +20 -6
  413. package/types/ngwr-knob.d.ts +18 -0
  414. package/types/ngwr-layout.d.ts +1 -0
  415. package/types/ngwr-lightbox.d.ts +17 -3
  416. package/types/ngwr-line-chart.d.ts +9 -2
  417. package/types/ngwr-list.d.ts +7 -2
  418. package/types/ngwr-loading-bar.d.ts +4 -7
  419. package/types/ngwr-markdown-testing.d.ts +462 -0
  420. package/types/ngwr-markdown.d.ts +534 -0
  421. package/types/ngwr-marquee.d.ts +12 -2
  422. package/types/ngwr-mention-testing.d.ts +359 -0
  423. package/types/ngwr-meta.d.ts +4 -2
  424. package/types/ngwr-meter-group.d.ts +11 -1
  425. package/types/ngwr-overlay.d.ts +33 -2
  426. package/types/ngwr-pagination-testing.d.ts +291 -0
  427. package/types/ngwr-pagination.d.ts +7 -1
  428. package/types/ngwr-popconfirm-testing.d.ts +235 -0
  429. package/types/ngwr-popconfirm.d.ts +31 -21
  430. package/types/ngwr-popover-testing.d.ts +221 -0
  431. package/types/ngwr-popover.d.ts +19 -2
  432. package/types/ngwr-pull-to-refresh.d.ts +7 -0
  433. package/types/ngwr-qr.d.ts +9 -1
  434. package/types/ngwr-radio-testing.d.ts +296 -0
  435. package/types/ngwr-radio.d.ts +8 -2
  436. package/types/ngwr-rating-testing.d.ts +291 -0
  437. package/types/ngwr-rating.d.ts +23 -0
  438. package/types/ngwr-segmented-testing.d.ts +401 -0
  439. package/types/ngwr-select-testing.d.ts +175 -0
  440. package/types/ngwr-select.d.ts +45 -4
  441. package/types/ngwr-sidebar.d.ts +17 -2
  442. package/types/ngwr-slider-testing.d.ts +329 -0
  443. package/types/ngwr-slider.d.ts +35 -1
  444. package/types/ngwr-sparkline.d.ts +12 -2
  445. package/types/ngwr-speed-dial.d.ts +17 -18
  446. package/types/ngwr-spinner.d.ts +8 -1
  447. package/types/ngwr-splitter.d.ts +24 -1
  448. package/types/ngwr-statistic.d.ts +12 -2
  449. package/types/ngwr-stepper-testing.d.ts +346 -0
  450. package/types/ngwr-storage.d.ts +10 -1
  451. package/types/ngwr-switch-testing.d.ts +66 -0
  452. package/types/ngwr-switch.d.ts +7 -2
  453. package/types/ngwr-table-testing.d.ts +423 -0
  454. package/types/ngwr-table.d.ts +42 -0
  455. package/types/ngwr-tabs-testing.d.ts +470 -0
  456. package/types/ngwr-tabs.d.ts +9 -0
  457. package/types/ngwr-textarea-testing.d.ts +184 -0
  458. package/types/ngwr-textarea.d.ts +7 -2
  459. package/types/ngwr-toast-testing.d.ts +80 -0
  460. package/types/ngwr-toast.d.ts +19 -4
  461. package/types/ngwr-tour.d.ts +27 -0
  462. package/types/ngwr-transfer-testing.d.ts +444 -0
  463. package/types/ngwr-transfer.d.ts +16 -1
  464. package/types/ngwr-tree-testing.d.ts +501 -0
  465. package/types/ngwr-tree.d.ts +33 -0
  466. package/types/ngwr-version.d.ts +1 -1
  467. package/types/ngwr-virtual-scroll.d.ts +13 -1
  468. package/types/ngwr-window.d.ts +23 -2
  469. package/typewriter/styles/_index.scss +1 -1
  470. package/typography/styles/_index.scss +1 -1
  471. package/window/styles/_index.scss +32 -9
@@ -49,6 +49,18 @@ function computeOrder(len, dir) {
49
49
  }
50
50
  return order.slice(0, len);
51
51
  }
52
+ /**
53
+ * How many characters the animation walks — CODE POINTS, not UTF-16 units.
54
+ *
55
+ * Every index in this component (`revealedIndices`, the sequential order, the
56
+ * per-character render) counts the same way `[...txt]` does. Using `txt.length`
57
+ * for the total counted an emoji twice, so a sequential reveal spent extra ticks
58
+ * on indices past the end of the text and the "everything revealed" test never
59
+ * lined up with what was on screen.
60
+ */
61
+ function charCount(txt) {
62
+ return [...txt].length;
63
+ }
52
64
  function fillAllIndices(len) {
53
65
  const s = new Set();
54
66
  for (let i = 0; i < len; i++)
@@ -240,10 +252,10 @@ class WrDecryptText {
240
252
  triggerReverse() {
241
253
  const txt = this.text();
242
254
  if (this.sequential()) {
243
- this.reverseOrder = computeOrder(txt.length, this.revealDirection()).slice().reverse();
255
+ this.reverseOrder = computeOrder(charCount(txt), this.revealDirection()).slice().reverse();
244
256
  this.reversePointer = 0;
245
257
  }
246
- const all = fillAllIndices(txt.length);
258
+ const all = fillAllIndices(charCount(txt));
247
259
  this.revealedIndices.set(all);
248
260
  this.displayText.set(this.shuffle(txt, all));
249
261
  this.direction.set('reverse');
@@ -280,8 +292,8 @@ class WrDecryptText {
280
292
  const max = this.maxIterations();
281
293
  const revealed = this.revealedIndices();
282
294
  if (seq && dir === 'forward') {
283
- if (revealed.size < txt.length) {
284
- const nextIdx = this.nextSequentialIndex(revealed, txt.length);
295
+ if (revealed.size < charCount(txt)) {
296
+ const nextIdx = this.nextSequentialIndex(revealed, charCount(txt));
285
297
  const next = new Set(revealed);
286
298
  next.add(nextIdx);
287
299
  this.revealedIndices.set(next);
@@ -325,8 +337,8 @@ class WrDecryptText {
325
337
  if (!seq && dir === 'reverse') {
326
338
  let current = revealed;
327
339
  if (current.size === 0)
328
- current = fillAllIndices(txt.length);
329
- const removeCount = Math.max(1, Math.ceil(txt.length / Math.max(1, max)));
340
+ current = fillAllIndices(charCount(txt));
341
+ const removeCount = Math.max(1, Math.ceil(charCount(txt) / Math.max(1, max)));
330
342
  const next = removeRandomIndices(current, removeCount);
331
343
  this.revealedIndices.set(next);
332
344
  this.displayText.set(this.shuffle(txt, next));
@@ -360,9 +372,15 @@ class WrDecryptText {
360
372
  }
361
373
  }
362
374
  shuffle(txt, revealed) {
375
+ // Every index here counts CODE POINTS, because that is what `[...txt]`
376
+ // produces and what `revealed` was built against. `split('')` counts UTF-16
377
+ // units instead, so an emoji in the text (or in a custom alphabet) put half a
378
+ // surrogate pair in the pool; and reading the revealed character back as
379
+ // `txt[i]` mixed the two index spaces, so every character after the first
380
+ // astral one revealed as the WRONG one.
363
381
  const pool = this.useOriginalCharsOnly()
364
- ? Array.from(new Set(txt.split(''))).filter(ch => ch !== ' ')
365
- : this.characters().split('');
382
+ ? Array.from(new Set([...txt])).filter(ch => ch !== ' ')
383
+ : [...this.characters()];
366
384
  if (pool.length === 0)
367
385
  return txt;
368
386
  return [...txt]
@@ -370,15 +388,15 @@ class WrDecryptText {
370
388
  if (ch === ' ')
371
389
  return ' ';
372
390
  if (revealed.has(i))
373
- return txt[i];
391
+ return ch;
374
392
  return pool[Math.floor(Math.random() * pool.length)];
375
393
  })
376
394
  .join('');
377
395
  }
378
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDecryptText, deps: [], target: i0.ɵɵFactoryTarget.Component });
379
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrDecryptText, isStandalone: true, selector: "wr-decrypt-text", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null }, speed: { classPropertyName: "speed", publicName: "speed", isSignal: true, isRequired: false, transformFunction: null }, maxIterations: { classPropertyName: "maxIterations", publicName: "maxIterations", isSignal: true, isRequired: false, transformFunction: null }, sequential: { classPropertyName: "sequential", publicName: "sequential", isSignal: true, isRequired: false, transformFunction: null }, revealDirection: { classPropertyName: "revealDirection", publicName: "revealDirection", isSignal: true, isRequired: false, transformFunction: null }, useOriginalCharsOnly: { classPropertyName: "useOriginalCharsOnly", publicName: "useOriginalCharsOnly", isSignal: true, isRequired: false, transformFunction: null }, characters: { classPropertyName: "characters", publicName: "characters", isSignal: true, isRequired: false, transformFunction: null }, animateOn: { classPropertyName: "animateOn", publicName: "animateOn", isSignal: true, isRequired: false, transformFunction: null }, clickMode: { classPropertyName: "clickMode", publicName: "clickMode", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "click": "onClick()" }, classAttribute: "wr-decrypt-text" }, ngImport: i0, template: "<span class=\"wr-decrypt-text__sr-only\">{{ text() }}</span>\n<span aria-hidden=\"true\">\n @for (c of chars(); track $index) {\n <span [class]=\"c.revealed ? 'wr-decrypt-text__char' : 'wr-decrypt-text__char wr-decrypt-text__char--encrypted'\">{{\n c.ch\n }}</span>\n }\n</span>\n", styles: [".wr-decrypt-text{display:inline-block;white-space:pre-wrap}.wr-decrypt-text__sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}.wr-decrypt-text__char{display:inline}\n"], encapsulation: i0.ViewEncapsulation.None });
396
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDecryptText, deps: [], target: i0.ɵɵFactoryTarget.Component });
397
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: WrDecryptText, isStandalone: true, selector: "wr-decrypt-text", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null }, speed: { classPropertyName: "speed", publicName: "speed", isSignal: true, isRequired: false, transformFunction: null }, maxIterations: { classPropertyName: "maxIterations", publicName: "maxIterations", isSignal: true, isRequired: false, transformFunction: null }, sequential: { classPropertyName: "sequential", publicName: "sequential", isSignal: true, isRequired: false, transformFunction: null }, revealDirection: { classPropertyName: "revealDirection", publicName: "revealDirection", isSignal: true, isRequired: false, transformFunction: null }, useOriginalCharsOnly: { classPropertyName: "useOriginalCharsOnly", publicName: "useOriginalCharsOnly", isSignal: true, isRequired: false, transformFunction: null }, characters: { classPropertyName: "characters", publicName: "characters", isSignal: true, isRequired: false, transformFunction: null }, animateOn: { classPropertyName: "animateOn", publicName: "animateOn", isSignal: true, isRequired: false, transformFunction: null }, clickMode: { classPropertyName: "clickMode", publicName: "clickMode", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "click": "onClick()" }, classAttribute: "wr-decrypt-text" }, ngImport: i0, template: "<span class=\"wr-decrypt-text__sr-only\">{{ text() }}</span>\n<span aria-hidden=\"true\">\n @for (c of chars(); track $index) {\n <span [class]=\"c.revealed ? 'wr-decrypt-text__char' : 'wr-decrypt-text__char wr-decrypt-text__char--encrypted'\">{{\n c.ch\n }}</span>\n }\n</span>\n", styles: [".wr-decrypt-text{display:inline-block;white-space:pre-wrap}.wr-decrypt-text__sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}.wr-decrypt-text__char{display:inline}\n"], encapsulation: i0.ViewEncapsulation.None });
380
398
  }
381
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDecryptText, decorators: [{
399
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDecryptText, decorators: [{
382
400
  type: Component,
383
401
  args: [{ selector: 'wr-decrypt-text', encapsulation: ViewEncapsulation.None, host: {
384
402
  class: 'wr-decrypt-text',
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-decrypt-text.mjs","sources":["../../../projects/lib/decrypt-text/decrypt-text.ts","../../../projects/lib/decrypt-text/decrypt-text.html","../../../projects/lib/decrypt-text/ngwr-decrypt-text.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 * Angular adaptation of the DecryptedText effect by David Haz / reactbits.dev.\n * Original: https://www.reactbits.dev/text-animations/decrypted-text\n *\n * The reactbits version uses `motion/react` for the wrapper. This port\n * is dependency-free — vanilla signals + `setInterval` for the tick loop.\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n signal,\n} from '@angular/core';\n\nimport { WrPlatform } from 'ngwr/platform';\nimport { numAttr } from 'ngwr/utils';\n\nimport type { WrDecryptTextAnimateOn, WrDecryptTextRevealDirection, WrDecryptTextClickMode } from './interfaces';\n\nconst DEFAULT_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()_+';\n\nfunction computeOrder(len: number, dir: WrDecryptTextRevealDirection): readonly number[] {\n const order: number[] = [];\n if (len <= 0) return order;\n if (dir === 'start') {\n for (let i = 0; i < len; i++) order.push(i);\n return order;\n }\n if (dir === 'end') {\n for (let i = len - 1; i >= 0; i--) order.push(i);\n return order;\n }\n const middle = Math.floor(len / 2);\n let off = 0;\n while (order.length < len) {\n if (off % 2 === 0) {\n const idx = middle + off / 2;\n if (idx >= 0 && idx < len) order.push(idx);\n } else {\n const idx = middle - Math.ceil(off / 2);\n if (idx >= 0 && idx < len) order.push(idx);\n }\n off++;\n }\n return order.slice(0, len);\n}\n\nfunction fillAllIndices(len: number): Set<number> {\n const s = new Set<number>();\n for (let i = 0; i < len; i++) s.add(i);\n return s;\n}\n\nfunction removeRandomIndices(set: ReadonlySet<number>, count: number): Set<number> {\n const arr = Array.from(set);\n for (let i = 0; i < count && arr.length > 0; i++) {\n arr.splice(Math.floor(Math.random() * arr.length), 1);\n }\n return new Set(arr);\n}\n\n/**\n * Reveals a string by scrambling characters and progressively replacing\n * scramble glyphs with the originals. Supports sequential reveal in\n * three directions, or non-sequential \"settle\" after N iterations, and\n * four trigger modes (hover, click, view, in-view + hover).\n *\n * @example\n * ```html\n * <wr-decrypt-text text=\"Hello, ngwr!\" animateOn=\"hover\" />\n * <wr-decrypt-text\n * text=\"Reveal from the center\"\n * [sequential]=\"true\"\n * revealDirection=\"center\"\n * animateOn=\"view\"\n * />\n * ```\n *\n * @see https://www.reactbits.dev/text-animations/decrypted-text\n */\n@Component({\n selector: 'wr-decrypt-text',\n templateUrl: './decrypt-text.html',\n styleUrl: './decrypt-text.scss',\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-decrypt-text',\n '(mouseenter)': 'onMouseEnter()',\n '(mouseleave)': 'onMouseLeave()',\n '(click)': 'onClick()',\n },\n})\nexport class WrDecryptText {\n /** Text to reveal. Required. */\n readonly text = input.required<string>();\n\n /** Tick interval in ms. @default 50 */\n readonly speed = input(50, { transform: numAttr(50) });\n\n /** Non-sequential mode only — total scramble ticks before snapping to plain. @default 10 */\n readonly maxIterations = input(10, { transform: numAttr(10) });\n\n /** Reveal one char per tick instead of scrambling all of them. @default false */\n readonly sequential = input(false, { transform: coerceBooleanProperty });\n\n /** Order in which chars are revealed in sequential mode. @default 'start' */\n readonly revealDirection = input<WrDecryptTextRevealDirection>('start');\n\n /** Scramble using only the glyphs present in `text` (minus spaces). @default false */\n readonly useOriginalCharsOnly = input(false, { transform: coerceBooleanProperty });\n\n /** Pool of glyphs to scramble through (used when `useOriginalCharsOnly` is false). */\n readonly characters = input(DEFAULT_CHARS);\n\n /** When to start the animation. @default 'hover' */\n readonly animateOn = input<WrDecryptTextAnimateOn>('hover');\n\n /** Click behaviour. `'once'` decrypts then stops; `'toggle'` flips state on each click. @default 'once' */\n readonly clickMode = input<WrDecryptTextClickMode>('once');\n\n private readonly displayText = signal('');\n private readonly revealedIndices = signal<ReadonlySet<number>>(new Set());\n private readonly isAnimating = signal(false);\n private readonly isDecrypted = signal(true);\n private readonly direction = signal<'forward' | 'reverse'>('forward');\n\n /** Per-char render data. */\n protected readonly chars = computed(() => {\n const display = this.displayText();\n const revealed = this.revealedIndices();\n const decrypted = this.isDecrypted();\n const animating = this.isAnimating();\n return [...display].map((ch, i) => ({\n ch,\n revealed: revealed.has(i) || (!animating && decrypted),\n }));\n });\n\n /** Sequential reverse order — captured when reverse starts. */\n private reverseOrder: readonly number[] = [];\n private reversePointer = 0;\n private iterationCount = 0;\n private intervalId: ReturnType<typeof setInterval> | undefined;\n private hasAnimatedOnce = false;\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly platform = inject(WrPlatform);\n\n constructor() {\n if (!this.isBrowser) {\n // SSR: render plain text.\n effect(() => this.displayText.set(this.text()));\n return;\n }\n\n // Reset state whenever `text` or `animateOn` changes.\n effect(() => {\n const txt = this.text();\n const mode = this.animateOn();\n this.stopInterval();\n if (mode === 'click') {\n this.encryptInstantly(txt);\n } else {\n this.displayText.set(txt);\n this.isDecrypted.set(true);\n }\n this.revealedIndices.set(new Set());\n this.direction.set('forward');\n this.hasAnimatedOnce = false;\n });\n\n afterNextRender(() => {\n const mode = this.animateOn();\n if (mode === 'view' || mode === 'inViewHover') this.setupIntersectionObserver();\n });\n\n this.destroyRef.onDestroy(() => this.stopInterval());\n }\n\n // Trigger handlers\n\n protected onMouseEnter(): void {\n const mode = this.animateOn();\n if (mode !== 'hover' && mode !== 'inViewHover') return;\n this.triggerHoverDecrypt();\n }\n\n protected onMouseLeave(): void {\n const mode = this.animateOn();\n if (mode !== 'hover' && mode !== 'inViewHover') return;\n this.resetToPlain();\n }\n\n protected onClick(): void {\n if (this.animateOn() !== 'click') return;\n if (this.clickMode() === 'once') {\n if (this.isDecrypted()) return;\n this.direction.set('forward');\n this.triggerDecrypt();\n return;\n }\n if (this.isDecrypted()) this.triggerReverse();\n else {\n this.direction.set('forward');\n this.triggerDecrypt();\n }\n }\n\n // Internals\n\n private setupIntersectionObserver(): void {\n const io = new IntersectionObserver(\n (entries, obs) => {\n for (const e of entries) {\n if (e.isIntersecting && !this.hasAnimatedOnce) {\n obs.disconnect();\n this.hasAnimatedOnce = true;\n this.triggerDecrypt();\n break;\n }\n }\n },\n { threshold: 0.1, rootMargin: '0px' }\n );\n io.observe(this.host.nativeElement);\n this.destroyRef.onDestroy(() => io.disconnect());\n }\n\n private triggerHoverDecrypt(): void {\n if (this.isAnimating()) return;\n this.revealedIndices.set(new Set());\n this.isDecrypted.set(false);\n this.displayText.set(this.text());\n this.direction.set('forward');\n this.startInterval();\n }\n\n private resetToPlain(): void {\n this.stopInterval();\n this.revealedIndices.set(new Set());\n this.displayText.set(this.text());\n this.isDecrypted.set(true);\n this.direction.set('forward');\n }\n\n private triggerDecrypt(): void {\n if (this.sequential()) {\n this.revealedIndices.set(new Set());\n } else {\n this.revealedIndices.set(new Set());\n }\n this.direction.set('forward');\n this.startInterval();\n }\n\n private triggerReverse(): void {\n const txt = this.text();\n if (this.sequential()) {\n this.reverseOrder = computeOrder(txt.length, this.revealDirection()).slice().reverse();\n this.reversePointer = 0;\n }\n const all = fillAllIndices(txt.length);\n this.revealedIndices.set(all);\n this.displayText.set(this.shuffle(txt, all));\n this.direction.set('reverse');\n this.startInterval();\n }\n\n private encryptInstantly(txt: string): void {\n this.revealedIndices.set(new Set());\n this.displayText.set(this.shuffle(txt, new Set()));\n this.isDecrypted.set(false);\n }\n\n private startInterval(): void {\n // Reduced motion: every trigger funnels through here — skip the\n // scramble loop and jump straight to the plain, decrypted text.\n if (this.platform.prefersReducedMotion()) {\n this.resetToPlain();\n return;\n }\n\n this.stopInterval();\n this.isAnimating.set(true);\n this.iterationCount = 0;\n this.intervalId = setInterval(() => this.tick(), this.speed());\n }\n\n private stopInterval(): void {\n if (this.intervalId !== undefined) {\n clearInterval(this.intervalId);\n this.intervalId = undefined;\n }\n this.isAnimating.set(false);\n }\n\n private tick(): void {\n const txt = this.text();\n const seq = this.sequential();\n const dir = this.direction();\n const max = this.maxIterations();\n const revealed = this.revealedIndices();\n\n if (seq && dir === 'forward') {\n if (revealed.size < txt.length) {\n const nextIdx = this.nextSequentialIndex(revealed, txt.length);\n const next = new Set(revealed);\n next.add(nextIdx);\n this.revealedIndices.set(next);\n this.displayText.set(this.shuffle(txt, next));\n } else {\n this.stopInterval();\n this.isDecrypted.set(true);\n this.displayText.set(txt);\n }\n return;\n }\n\n if (seq && dir === 'reverse') {\n if (this.reversePointer < this.reverseOrder.length) {\n const idx = this.reverseOrder[this.reversePointer++];\n const next = new Set(revealed);\n next.delete(idx);\n this.revealedIndices.set(next);\n this.displayText.set(this.shuffle(txt, next));\n if (next.size === 0) {\n this.stopInterval();\n this.isDecrypted.set(false);\n }\n } else {\n this.stopInterval();\n this.isDecrypted.set(false);\n }\n return;\n }\n\n if (!seq && dir === 'forward') {\n this.displayText.set(this.shuffle(txt, revealed));\n this.iterationCount++;\n if (this.iterationCount >= max) {\n this.stopInterval();\n this.displayText.set(txt);\n this.isDecrypted.set(true);\n }\n return;\n }\n\n if (!seq && dir === 'reverse') {\n let current = revealed;\n if (current.size === 0) current = fillAllIndices(txt.length);\n const removeCount = Math.max(1, Math.ceil(txt.length / Math.max(1, max)));\n const next = removeRandomIndices(current, removeCount);\n this.revealedIndices.set(next);\n this.displayText.set(this.shuffle(txt, next));\n this.iterationCount++;\n if (next.size === 0 || this.iterationCount >= max) {\n this.stopInterval();\n this.isDecrypted.set(false);\n this.displayText.set(this.shuffle(txt, new Set()));\n this.revealedIndices.set(new Set());\n }\n }\n }\n\n private nextSequentialIndex(revealed: ReadonlySet<number>, len: number): number {\n switch (this.revealDirection()) {\n case 'end':\n return len - 1 - revealed.size;\n case 'center': {\n const middle = Math.floor(len / 2);\n const offset = Math.floor(revealed.size / 2);\n const candidate = revealed.size % 2 === 0 ? middle + offset : middle - offset - 1;\n if (candidate >= 0 && candidate < len && !revealed.has(candidate)) return candidate;\n for (let i = 0; i < len; i++) if (!revealed.has(i)) return i;\n return 0;\n }\n case 'start':\n default:\n return revealed.size;\n }\n }\n\n private shuffle(txt: string, revealed: ReadonlySet<number>): string {\n const pool = this.useOriginalCharsOnly()\n ? Array.from(new Set(txt.split(''))).filter(ch => ch !== ' ')\n : this.characters().split('');\n if (pool.length === 0) return txt;\n return [...txt]\n .map((ch, i) => {\n if (ch === ' ') return ' ';\n if (revealed.has(i)) return txt[i];\n return pool[Math.floor(Math.random() * pool.length)];\n })\n .join('');\n }\n}\n\nexport type { WrDecryptTextAnimateOn, WrDecryptTextRevealDirection, WrDecryptTextClickMode } from './interfaces';\n","<span class=\"wr-decrypt-text__sr-only\">{{ text() }}</span>\n<span aria-hidden=\"true\">\n @for (c of chars(); track $index) {\n <span [class]=\"c.revealed ? 'wr-decrypt-text__char' : 'wr-decrypt-text__char wr-decrypt-text__char--encrypted'\">{{\n c.ch\n }}</span>\n }\n</span>\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-decrypt-text.mjs","sources":["../../../projects/lib/decrypt-text/decrypt-text.ts","../../../projects/lib/decrypt-text/decrypt-text.html","../../../projects/lib/decrypt-text/ngwr-decrypt-text.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 * Angular adaptation of the DecryptedText effect by David Haz / reactbits.dev.\n * Original: https://www.reactbits.dev/text-animations/decrypted-text\n *\n * The reactbits version uses `motion/react` for the wrapper. This port\n * is dependency-free — vanilla signals + `setInterval` for the tick loop.\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n signal,\n} from '@angular/core';\n\nimport { WrPlatform } from 'ngwr/platform';\nimport { numAttr } from 'ngwr/utils';\n\nimport type { WrDecryptTextAnimateOn, WrDecryptTextRevealDirection, WrDecryptTextClickMode } from './interfaces';\n\nconst DEFAULT_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()_+';\n\nfunction computeOrder(len: number, dir: WrDecryptTextRevealDirection): readonly number[] {\n const order: number[] = [];\n if (len <= 0) return order;\n if (dir === 'start') {\n for (let i = 0; i < len; i++) order.push(i);\n return order;\n }\n if (dir === 'end') {\n for (let i = len - 1; i >= 0; i--) order.push(i);\n return order;\n }\n const middle = Math.floor(len / 2);\n let off = 0;\n while (order.length < len) {\n if (off % 2 === 0) {\n const idx = middle + off / 2;\n if (idx >= 0 && idx < len) order.push(idx);\n } else {\n const idx = middle - Math.ceil(off / 2);\n if (idx >= 0 && idx < len) order.push(idx);\n }\n off++;\n }\n return order.slice(0, len);\n}\n\n/**\n * How many characters the animation walks — CODE POINTS, not UTF-16 units.\n *\n * Every index in this component (`revealedIndices`, the sequential order, the\n * per-character render) counts the same way `[...txt]` does. Using `txt.length`\n * for the total counted an emoji twice, so a sequential reveal spent extra ticks\n * on indices past the end of the text and the \"everything revealed\" test never\n * lined up with what was on screen.\n */\nfunction charCount(txt: string): number {\n return [...txt].length;\n}\n\nfunction fillAllIndices(len: number): Set<number> {\n const s = new Set<number>();\n for (let i = 0; i < len; i++) s.add(i);\n return s;\n}\n\nfunction removeRandomIndices(set: ReadonlySet<number>, count: number): Set<number> {\n const arr = Array.from(set);\n for (let i = 0; i < count && arr.length > 0; i++) {\n arr.splice(Math.floor(Math.random() * arr.length), 1);\n }\n return new Set(arr);\n}\n\n/**\n * Reveals a string by scrambling characters and progressively replacing\n * scramble glyphs with the originals. Supports sequential reveal in\n * three directions, or non-sequential \"settle\" after N iterations, and\n * four trigger modes (hover, click, view, in-view + hover).\n *\n * @example\n * ```html\n * <wr-decrypt-text text=\"Hello, ngwr!\" animateOn=\"hover\" />\n * <wr-decrypt-text\n * text=\"Reveal from the center\"\n * [sequential]=\"true\"\n * revealDirection=\"center\"\n * animateOn=\"view\"\n * />\n * ```\n *\n * @see https://www.reactbits.dev/text-animations/decrypted-text\n */\n@Component({\n selector: 'wr-decrypt-text',\n templateUrl: './decrypt-text.html',\n styleUrl: './decrypt-text.scss',\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-decrypt-text',\n '(mouseenter)': 'onMouseEnter()',\n '(mouseleave)': 'onMouseLeave()',\n '(click)': 'onClick()',\n },\n})\nexport class WrDecryptText {\n /** Text to reveal. Required. */\n readonly text = input.required<string>();\n\n /** Tick interval in ms. @default 50 */\n readonly speed = input(50, { transform: numAttr(50) });\n\n /** Non-sequential mode only — total scramble ticks before snapping to plain. @default 10 */\n readonly maxIterations = input(10, { transform: numAttr(10) });\n\n /** Reveal one char per tick instead of scrambling all of them. @default false */\n readonly sequential = input(false, { transform: coerceBooleanProperty });\n\n /** Order in which chars are revealed in sequential mode. @default 'start' */\n readonly revealDirection = input<WrDecryptTextRevealDirection>('start');\n\n /** Scramble using only the glyphs present in `text` (minus spaces). @default false */\n readonly useOriginalCharsOnly = input(false, { transform: coerceBooleanProperty });\n\n /** Pool of glyphs to scramble through (used when `useOriginalCharsOnly` is false). */\n readonly characters = input(DEFAULT_CHARS);\n\n /** When to start the animation. @default 'hover' */\n readonly animateOn = input<WrDecryptTextAnimateOn>('hover');\n\n /** Click behaviour. `'once'` decrypts then stops; `'toggle'` flips state on each click. @default 'once' */\n readonly clickMode = input<WrDecryptTextClickMode>('once');\n\n private readonly displayText = signal('');\n private readonly revealedIndices = signal<ReadonlySet<number>>(new Set());\n private readonly isAnimating = signal(false);\n private readonly isDecrypted = signal(true);\n private readonly direction = signal<'forward' | 'reverse'>('forward');\n\n /** Per-char render data. */\n protected readonly chars = computed(() => {\n const display = this.displayText();\n const revealed = this.revealedIndices();\n const decrypted = this.isDecrypted();\n const animating = this.isAnimating();\n return [...display].map((ch, i) => ({\n ch,\n revealed: revealed.has(i) || (!animating && decrypted),\n }));\n });\n\n /** Sequential reverse order — captured when reverse starts. */\n private reverseOrder: readonly number[] = [];\n private reversePointer = 0;\n private iterationCount = 0;\n private intervalId: ReturnType<typeof setInterval> | undefined;\n private hasAnimatedOnce = false;\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly platform = inject(WrPlatform);\n\n constructor() {\n if (!this.isBrowser) {\n // SSR: render plain text.\n effect(() => this.displayText.set(this.text()));\n return;\n }\n\n // Reset state whenever `text` or `animateOn` changes.\n effect(() => {\n const txt = this.text();\n const mode = this.animateOn();\n this.stopInterval();\n if (mode === 'click') {\n this.encryptInstantly(txt);\n } else {\n this.displayText.set(txt);\n this.isDecrypted.set(true);\n }\n this.revealedIndices.set(new Set());\n this.direction.set('forward');\n this.hasAnimatedOnce = false;\n });\n\n afterNextRender(() => {\n const mode = this.animateOn();\n if (mode === 'view' || mode === 'inViewHover') this.setupIntersectionObserver();\n });\n\n this.destroyRef.onDestroy(() => this.stopInterval());\n }\n\n // Trigger handlers\n\n protected onMouseEnter(): void {\n const mode = this.animateOn();\n if (mode !== 'hover' && mode !== 'inViewHover') return;\n this.triggerHoverDecrypt();\n }\n\n protected onMouseLeave(): void {\n const mode = this.animateOn();\n if (mode !== 'hover' && mode !== 'inViewHover') return;\n this.resetToPlain();\n }\n\n protected onClick(): void {\n if (this.animateOn() !== 'click') return;\n if (this.clickMode() === 'once') {\n if (this.isDecrypted()) return;\n this.direction.set('forward');\n this.triggerDecrypt();\n return;\n }\n if (this.isDecrypted()) this.triggerReverse();\n else {\n this.direction.set('forward');\n this.triggerDecrypt();\n }\n }\n\n // Internals\n\n private setupIntersectionObserver(): void {\n const io = new IntersectionObserver(\n (entries, obs) => {\n for (const e of entries) {\n if (e.isIntersecting && !this.hasAnimatedOnce) {\n obs.disconnect();\n this.hasAnimatedOnce = true;\n this.triggerDecrypt();\n break;\n }\n }\n },\n { threshold: 0.1, rootMargin: '0px' }\n );\n io.observe(this.host.nativeElement);\n this.destroyRef.onDestroy(() => io.disconnect());\n }\n\n private triggerHoverDecrypt(): void {\n if (this.isAnimating()) return;\n this.revealedIndices.set(new Set());\n this.isDecrypted.set(false);\n this.displayText.set(this.text());\n this.direction.set('forward');\n this.startInterval();\n }\n\n private resetToPlain(): void {\n this.stopInterval();\n this.revealedIndices.set(new Set());\n this.displayText.set(this.text());\n this.isDecrypted.set(true);\n this.direction.set('forward');\n }\n\n private triggerDecrypt(): void {\n if (this.sequential()) {\n this.revealedIndices.set(new Set());\n } else {\n this.revealedIndices.set(new Set());\n }\n this.direction.set('forward');\n this.startInterval();\n }\n\n private triggerReverse(): void {\n const txt = this.text();\n if (this.sequential()) {\n this.reverseOrder = computeOrder(charCount(txt), this.revealDirection()).slice().reverse();\n this.reversePointer = 0;\n }\n const all = fillAllIndices(charCount(txt));\n this.revealedIndices.set(all);\n this.displayText.set(this.shuffle(txt, all));\n this.direction.set('reverse');\n this.startInterval();\n }\n\n private encryptInstantly(txt: string): void {\n this.revealedIndices.set(new Set());\n this.displayText.set(this.shuffle(txt, new Set()));\n this.isDecrypted.set(false);\n }\n\n private startInterval(): void {\n // Reduced motion: every trigger funnels through here — skip the\n // scramble loop and jump straight to the plain, decrypted text.\n if (this.platform.prefersReducedMotion()) {\n this.resetToPlain();\n return;\n }\n\n this.stopInterval();\n this.isAnimating.set(true);\n this.iterationCount = 0;\n this.intervalId = setInterval(() => this.tick(), this.speed());\n }\n\n private stopInterval(): void {\n if (this.intervalId !== undefined) {\n clearInterval(this.intervalId);\n this.intervalId = undefined;\n }\n this.isAnimating.set(false);\n }\n\n private tick(): void {\n const txt = this.text();\n const seq = this.sequential();\n const dir = this.direction();\n const max = this.maxIterations();\n const revealed = this.revealedIndices();\n\n if (seq && dir === 'forward') {\n if (revealed.size < charCount(txt)) {\n const nextIdx = this.nextSequentialIndex(revealed, charCount(txt));\n const next = new Set(revealed);\n next.add(nextIdx);\n this.revealedIndices.set(next);\n this.displayText.set(this.shuffle(txt, next));\n } else {\n this.stopInterval();\n this.isDecrypted.set(true);\n this.displayText.set(txt);\n }\n return;\n }\n\n if (seq && dir === 'reverse') {\n if (this.reversePointer < this.reverseOrder.length) {\n const idx = this.reverseOrder[this.reversePointer++];\n const next = new Set(revealed);\n next.delete(idx);\n this.revealedIndices.set(next);\n this.displayText.set(this.shuffle(txt, next));\n if (next.size === 0) {\n this.stopInterval();\n this.isDecrypted.set(false);\n }\n } else {\n this.stopInterval();\n this.isDecrypted.set(false);\n }\n return;\n }\n\n if (!seq && dir === 'forward') {\n this.displayText.set(this.shuffle(txt, revealed));\n this.iterationCount++;\n if (this.iterationCount >= max) {\n this.stopInterval();\n this.displayText.set(txt);\n this.isDecrypted.set(true);\n }\n return;\n }\n\n if (!seq && dir === 'reverse') {\n let current = revealed;\n if (current.size === 0) current = fillAllIndices(charCount(txt));\n const removeCount = Math.max(1, Math.ceil(charCount(txt) / Math.max(1, max)));\n const next = removeRandomIndices(current, removeCount);\n this.revealedIndices.set(next);\n this.displayText.set(this.shuffle(txt, next));\n this.iterationCount++;\n if (next.size === 0 || this.iterationCount >= max) {\n this.stopInterval();\n this.isDecrypted.set(false);\n this.displayText.set(this.shuffle(txt, new Set()));\n this.revealedIndices.set(new Set());\n }\n }\n }\n\n private nextSequentialIndex(revealed: ReadonlySet<number>, len: number): number {\n switch (this.revealDirection()) {\n case 'end':\n return len - 1 - revealed.size;\n case 'center': {\n const middle = Math.floor(len / 2);\n const offset = Math.floor(revealed.size / 2);\n const candidate = revealed.size % 2 === 0 ? middle + offset : middle - offset - 1;\n if (candidate >= 0 && candidate < len && !revealed.has(candidate)) return candidate;\n for (let i = 0; i < len; i++) if (!revealed.has(i)) return i;\n return 0;\n }\n case 'start':\n default:\n return revealed.size;\n }\n }\n\n private shuffle(txt: string, revealed: ReadonlySet<number>): string {\n // Every index here counts CODE POINTS, because that is what `[...txt]`\n // produces and what `revealed` was built against. `split('')` counts UTF-16\n // units instead, so an emoji in the text (or in a custom alphabet) put half a\n // surrogate pair in the pool; and reading the revealed character back as\n // `txt[i]` mixed the two index spaces, so every character after the first\n // astral one revealed as the WRONG one.\n const pool = this.useOriginalCharsOnly()\n ? Array.from(new Set([...txt])).filter(ch => ch !== ' ')\n : [...this.characters()];\n if (pool.length === 0) return txt;\n return [...txt]\n .map((ch, i) => {\n if (ch === ' ') return ' ';\n if (revealed.has(i)) return ch;\n return pool[Math.floor(Math.random() * pool.length)];\n })\n .join('');\n }\n}\n\nexport type { WrDecryptTextAnimateOn, WrDecryptTextRevealDirection, WrDecryptTextClickMode } from './interfaces';\n","<span class=\"wr-decrypt-text__sr-only\">{{ text() }}</span>\n<span aria-hidden=\"true\">\n @for (c of chars(); track $index) {\n <span [class]=\"c.revealed ? 'wr-decrypt-text__char' : 'wr-decrypt-text__char wr-decrypt-text__char--encrypted'\">{{\n c.ch\n }}</span>\n }\n</span>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -89,10 +89,10 @@ class WrDensity {
89
89
  return;
90
90
  this.storage.set(this.config.storageKey, density);
91
91
  }
92
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDensity, deps: [], target: i0.ɵɵFactoryTarget.Service });
93
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.0", ngImport: i0, type: WrDensity });
92
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDensity, deps: [], target: i0.ɵɵFactoryTarget.Service });
93
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.1", ngImport: i0, type: WrDensity });
94
94
  }
95
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDensity, decorators: [{
95
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDensity, decorators: [{
96
96
  type: Service
97
97
  }], ctorParameters: () => [] });
98
98
 
@@ -126,10 +126,10 @@ class WrDensityDirective {
126
126
  this.host.nativeElement.setAttribute(this.config.attribute, this.wrDensity());
127
127
  });
128
128
  }
129
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDensityDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
130
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.0", type: WrDensityDirective, isStandalone: true, selector: "[wrDensity]", inputs: { wrDensity: { classPropertyName: "wrDensity", publicName: "wrDensity", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
129
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDensityDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
130
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.1", type: WrDensityDirective, isStandalone: true, selector: "[wrDensity]", inputs: { wrDensity: { classPropertyName: "wrDensity", publicName: "wrDensity", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
131
131
  }
132
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDensityDirective, decorators: [{
132
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDensityDirective, decorators: [{
133
133
  type: Directive,
134
134
  args: [{
135
135
  selector: '[wrDensity]',
@@ -50,10 +50,10 @@ class WrDescriptions {
50
50
  return parts.join(' ');
51
51
  }, /* @ts-ignore */
52
52
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
53
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDescriptions, deps: [], target: i0.ɵɵFactoryTarget.Component });
54
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrDescriptions, isStandalone: true, selector: "wr-descriptions", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, inline: { classPropertyName: "inline", publicName: "inline", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: "@if (title()) {\n <div class=\"wr-descriptions__title\">{{ title() }}</div>\n}\n<!--\n A plain <div> with ARIA term/definition roles on the item, not a <dl>:\n the rows are their own component, so the real DOM is\n `<dl><wr-description-item><dt>\u2026` \u2014 which the HTML content model forbids and\n which breaks the term/definition association in AT. `role=\"term\"` /\n `role=\"definition\"` carry the same semantics with no required parent, so they\n survive the component boundary (and `display: contents` on the row).\n-->\n<div class=\"wr-descriptions__list\">\n <ng-content />\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
53
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDescriptions, deps: [], target: i0.ɵɵFactoryTarget.Component });
54
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: WrDescriptions, isStandalone: true, selector: "wr-descriptions", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, inline: { classPropertyName: "inline", publicName: "inline", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: "@if (title()) {\n <div class=\"wr-descriptions__title\">{{ title() }}</div>\n}\n<!--\n A plain <div> with ARIA term/definition roles on the item, not a <dl>:\n the rows are their own component, so the real DOM is\n `<dl><wr-description-item><dt>\u2026` \u2014 which the HTML content model forbids and\n which breaks the term/definition association in AT. `role=\"term\"` /\n `role=\"definition\"` carry the same semantics with no required parent, so they\n survive the component boundary (and `display: contents` on the row).\n-->\n<div class=\"wr-descriptions__list\">\n <ng-content />\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
55
55
  }
56
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDescriptions, decorators: [{
56
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDescriptions, decorators: [{
57
57
  type: Component,
58
58
  args: [{ selector: 'wr-descriptions', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, template: "@if (title()) {\n <div class=\"wr-descriptions__title\">{{ title() }}</div>\n}\n<!--\n A plain <div> with ARIA term/definition roles on the item, not a <dl>:\n the rows are their own component, so the real DOM is\n `<dl><wr-description-item><dt>\u2026` \u2014 which the HTML content model forbids and\n which breaks the term/definition association in AT. `role=\"term\"` /\n `role=\"definition\"` carry the same semantics with no required parent, so they\n survive the component boundary (and `display: contents` on the row).\n-->\n<div class=\"wr-descriptions__list\">\n <ng-content />\n</div>\n" }]
59
59
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], inline: [{ type: i0.Input, args: [{ isSignal: true, alias: "inline", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }] } });
@@ -71,10 +71,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
71
71
  class WrDescriptionItem {
72
72
  label = input('', /* @ts-ignore */
73
73
  ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
74
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDescriptionItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
75
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: WrDescriptionItem, isStandalone: true, selector: "wr-description-item", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-descriptions__row" }, ngImport: i0, template: "<div class=\"wr-descriptions__label\" role=\"term\">{{ label() }}</div><div class=\"wr-descriptions__value\" role=\"definition\"><ng-content /></div>", isInline: true, encapsulation: i0.ViewEncapsulation.None });
74
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDescriptionItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
75
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.1", type: WrDescriptionItem, isStandalone: true, selector: "wr-description-item", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-descriptions__row" }, ngImport: i0, template: "<div class=\"wr-descriptions__label\" role=\"term\">{{ label() }}</div><div class=\"wr-descriptions__value\" role=\"definition\"><ng-content /></div>", isInline: true, encapsulation: i0.ViewEncapsulation.None });
76
76
  }
77
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDescriptionItem, decorators: [{
77
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDescriptionItem, decorators: [{
78
78
  type: Component,
79
79
  args: [{
80
80
  selector: 'wr-description-item',
@@ -0,0 +1,89 @@
1
+ import { ContentContainerComponentHarness, 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 a dialog opened with `WrDialog.open()`.
11
+ *
12
+ * A dialog is never inside the fixture — `WrDialog` attaches it to the overlay
13
+ * container — so load this from `TestbedHarnessEnvironment.documentRootLoader()`
14
+ * rather than from `loader()`. The harness is a CONTENT CONTAINER, which is what
15
+ * makes the interesting assertions possible: the buttons and fields it holds are
16
+ * the consumer's own components, so `dialog.getHarness(WrButtonHarness…)` reads
17
+ * them without the spec ever touching the overlay.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const rootLoader = TestbedHarnessEnvironment.documentRootLoader(fixture);
22
+ * const dialog = await rootLoader.getHarness(WrDialogHarness);
23
+ *
24
+ * expect(await dialog.getTitleText()).toBe('Delete this item?');
25
+ * await (await dialog.getHarness(WrButtonHarness.with({ text: 'Delete' }))).click();
26
+ * ```
27
+ *
28
+ * @see https://ngwr.dev/guides/testing
29
+ */
30
+ class WrDialogHarness extends ContentContainerComponentHarness {
31
+ /** The overlay panel `WrDialog` creates. */
32
+ static hostSelector = '.wr-dialog-panel';
33
+ /** Build a predicate that narrows the query — useful when two dialogs are stacked. */
34
+ static with(options = {}) {
35
+ return new HarnessPredicate(WrDialogHarness, options).addOption('title', options.title, (harness, title) => HarnessPredicate.stringMatches(harness.getTitleText(), title));
36
+ }
37
+ /** The `[wrDialogTitle]` text, or `null` when the dialog has no title. */
38
+ async getTitleText() {
39
+ const title = await this.locatorForOptional('.wr-dialog__title')();
40
+ return title ? title.text() : null;
41
+ }
42
+ /** The `[wrDialogContent]` text, or `null` when the dialog projects no content region. */
43
+ async getContentText() {
44
+ const content = await this.locatorForOptional('.wr-dialog__content')();
45
+ return content ? content.text() : null;
46
+ }
47
+ /**
48
+ * The role and modality the dialog announces.
49
+ *
50
+ * Worth asserting rather than assuming: `WrDialog` sets these on the OVERLAY
51
+ * element, not on the component it renders, so a consumer looking for them on
52
+ * their own host would not find them.
53
+ */
54
+ async getRole() {
55
+ return (await this.host()).getAttribute('role');
56
+ }
57
+ /** Whether the dialog is marked `aria-modal`. */
58
+ async isModal() {
59
+ return (await (await this.host()).getAttribute('aria-modal')) === 'true';
60
+ }
61
+ /** Whether the built-in dismiss button is present (`closable`, the default). */
62
+ async isClosable() {
63
+ return (await this.locatorForOptional('.wr-dialog__close')()) !== null;
64
+ }
65
+ /** The dismiss button's accessible name — the string a screen reader reads out. */
66
+ async getCloseLabel() {
67
+ const close = await this.locatorForOptional('.wr-dialog__close')();
68
+ return close ? close.getAttribute('aria-label') : null;
69
+ }
70
+ /** Click the built-in dismiss button. Throws when the dialog was opened `closable: false`. */
71
+ async close() {
72
+ await (await this.locatorFor('.wr-dialog__close')()).click();
73
+ }
74
+ /** Press Escape. A dialog opened `closeOnEscape: false` ignores it — assert, do not assume. */
75
+ async sendEscape() {
76
+ await (await this.host()).sendKeys(TestKey.ESCAPE);
77
+ }
78
+ /** Whether focus is currently somewhere inside the dialog, where the trap should keep it. */
79
+ async isFocusTrapped() {
80
+ return (await this.host()).matchesSelector(':focus-within');
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Generated bundle index. Do not edit.
86
+ */
87
+
88
+ export { WrDialogHarness };
89
+ //# sourceMappingURL=ngwr-dialog-testing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngwr-dialog-testing.mjs","sources":["../../../projects/lib/dialog/testing/wr-dialog-harness.ts","../../../projects/lib/dialog/testing/ngwr-dialog-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 { ContentContainerComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';\n\nimport type { WrDialogHarnessFilters } from './interfaces';\n\n/**\n * Test harness for a dialog opened with `WrDialog.open()`.\n *\n * A dialog is never inside the fixture — `WrDialog` attaches it to the overlay\n * container — so load this from `TestbedHarnessEnvironment.documentRootLoader()`\n * rather than from `loader()`. The harness is a CONTENT CONTAINER, which is what\n * makes the interesting assertions possible: the buttons and fields it holds are\n * the consumer's own components, so `dialog.getHarness(WrButtonHarness…)` reads\n * them without the spec ever touching the overlay.\n *\n * @example\n * ```ts\n * const rootLoader = TestbedHarnessEnvironment.documentRootLoader(fixture);\n * const dialog = await rootLoader.getHarness(WrDialogHarness);\n *\n * expect(await dialog.getTitleText()).toBe('Delete this item?');\n * await (await dialog.getHarness(WrButtonHarness.with({ text: 'Delete' }))).click();\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrDialogHarness extends ContentContainerComponentHarness {\n /** The overlay panel `WrDialog` creates. */\n static hostSelector = '.wr-dialog-panel';\n\n /** Build a predicate that narrows the query — useful when two dialogs are stacked. */\n static with(options: WrDialogHarnessFilters = {}): HarnessPredicate<WrDialogHarness> {\n return new HarnessPredicate(WrDialogHarness, options).addOption('title', options.title, (harness, title) =>\n HarnessPredicate.stringMatches(harness.getTitleText(), title)\n );\n }\n\n /** The `[wrDialogTitle]` text, or `null` when the dialog has no title. */\n async getTitleText(): Promise<string | null> {\n const title = await this.locatorForOptional('.wr-dialog__title')();\n return title ? title.text() : null;\n }\n\n /** The `[wrDialogContent]` text, or `null` when the dialog projects no content region. */\n async getContentText(): Promise<string | null> {\n const content = await this.locatorForOptional('.wr-dialog__content')();\n return content ? content.text() : null;\n }\n\n /**\n * The role and modality the dialog announces.\n *\n * Worth asserting rather than assuming: `WrDialog` sets these on the OVERLAY\n * element, not on the component it renders, so a consumer looking for them on\n * their own host would not find them.\n */\n async getRole(): Promise<string | null> {\n return (await this.host()).getAttribute('role');\n }\n\n /** Whether the dialog is marked `aria-modal`. */\n async isModal(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-modal')) === 'true';\n }\n\n /** Whether the built-in dismiss button is present (`closable`, the default). */\n async isClosable(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-dialog__close')()) !== null;\n }\n\n /** The dismiss button's accessible name — the string a screen reader reads out. */\n async getCloseLabel(): Promise<string | null> {\n const close = await this.locatorForOptional('.wr-dialog__close')();\n return close ? close.getAttribute('aria-label') : null;\n }\n\n /** Click the built-in dismiss button. Throws when the dialog was opened `closable: false`. */\n async close(): Promise<void> {\n await (await this.locatorFor('.wr-dialog__close')()).click();\n }\n\n /** Press Escape. A dialog opened `closeOnEscape: false` ignores it — assert, do not assume. */\n async sendEscape(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.ESCAPE);\n }\n\n /** Whether focus is currently somewhere inside the dialog, where the trap should keep it. */\n async isFocusTrapped(): Promise<boolean> {\n return (await this.host()).matchesSelector(':focus-within');\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAMH;;;;;;;;;;;;;;;;;;;;AAoBG;AACG,MAAO,eAAgB,SAAQ,gCAAgC,CAAA;;AAEnE,IAAA,OAAO,YAAY,GAAG,kBAAkB;;AAGxC,IAAA,OAAO,IAAI,CAAC,OAAA,GAAkC,EAAE,EAAA;AAC9C,QAAA,OAAO,IAAI,gBAAgB,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,KACrG,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,KAAK,CAAC,CAC9D;IACH;;AAGA,IAAA,MAAM,YAAY,GAAA;QAChB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,EAAE;AAClE,QAAA,OAAO,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,GAAG,IAAI;IACpC;;AAGA,IAAA,MAAM,cAAc,GAAA;QAClB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,qBAAqB,CAAC,EAAE;AACtE,QAAA,OAAO,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI;IACxC;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,MAAM,CAAC;IACjD;;AAGA,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,YAAY,CAAC,MAAM,MAAM;IAC1E;;AAGA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,EAAE,MAAM,IAAI;IACxE;;AAGA,IAAA,MAAM,aAAa,GAAA;QACjB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,EAAE;AAClE,QAAA,OAAO,KAAK,GAAG,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC,GAAG,IAAI;IACxD;;AAGA,IAAA,MAAM,KAAK,GAAA;AACT,QAAA,MAAM,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,EAAE,KAAK,EAAE;IAC9D;;AAGA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;IACpD;;AAGA,IAAA,MAAM,cAAc,GAAA;AAClB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,eAAe,CAAC,eAAe,CAAC;IAC7D;;;AC/FF;;AAEG;;;;"}
@@ -208,7 +208,7 @@ class WrDialog {
208
208
  focusTrapFactory = inject(ConfigurableFocusTrapFactory);
209
209
  isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
210
210
  responsiveConfig = inject(WR_RESPONSIVE_OVERLAYS);
211
- i18n = inject(WrI18n);
211
+ i18n = inject(WrI18n, { optional: true });
212
212
  open(component, options = {}) {
213
213
  const panelClasses = [DEFAULT_PANEL_CLASS];
214
214
  const extra = options.panelClass;
@@ -259,7 +259,7 @@ class WrDialog {
259
259
  // it, and marked on the panel so the title reserves the corner gutter.
260
260
  if (options.closable !== false) {
261
261
  host.classList.add('wr-dialog-panel--closable');
262
- const label = options.closeLabel ?? this.i18n.t('dialog.close');
262
+ const label = options.closeLabel ?? this.closeLabel();
263
263
  wrAppendOverlayClose(host, 'wr-dialog__close', label, () => dialogRef.close());
264
264
  }
265
265
  // Wire aria-labelledby to wrDialogTitle's auto-id once content is in DOM.
@@ -291,10 +291,26 @@ class WrDialog {
291
291
  }
292
292
  return dialogRef;
293
293
  }
294
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDialog, deps: [], target: i0.ɵɵFactoryTarget.Service });
295
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.0", ngImport: i0, type: WrDialog });
294
+ /**
295
+ * The dismiss button's accessible name.
296
+ *
297
+ * Two failure modes, and resolving PER OPEN is what covers both. `t()` hands
298
+ * back the KEY on a miss, and `WrI18n` is root-provided with an empty catalog
299
+ * by default, so an app that never configured i18n named its dismiss button
300
+ * "dialog.close" — a name axe cannot fault, because a name is present, and a
301
+ * screen reader reads out verbatim. Resolving once at injection time fixed
302
+ * that but froze the answer: this is a root service, constructed before an
303
+ * async catalog has loaded, so a localized app got the English fallback on
304
+ * every dialog it ever opened.
305
+ */
306
+ closeLabel() {
307
+ const resolved = this.i18n?.t('dialog.close');
308
+ return !resolved || resolved === 'dialog.close' ? 'Close dialog' : resolved;
309
+ }
310
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDialog, deps: [], target: i0.ɵɵFactoryTarget.Service });
311
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.1", ngImport: i0, type: WrDialog });
296
312
  }
297
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDialog, decorators: [{
313
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDialog, decorators: [{
298
314
  type: Service
299
315
  }] });
300
316
 
@@ -320,10 +336,10 @@ class WrDialogTitle {
320
336
  id = `wr-dialog-title-${++uid}`;
321
337
  /** @internal */
322
338
  elementRef = inject((ElementRef));
323
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDialogTitle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
324
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.0", type: WrDialogTitle, isStandalone: true, selector: "[wrDialogTitle]", host: { properties: { "attr.id": "id" }, classAttribute: "wr-dialog__title" }, ngImport: i0 });
339
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDialogTitle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
340
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.1", type: WrDialogTitle, isStandalone: true, selector: "[wrDialogTitle]", host: { properties: { "attr.id": "id" }, classAttribute: "wr-dialog__title" }, ngImport: i0 });
325
341
  }
326
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDialogTitle, decorators: [{
342
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDialogTitle, decorators: [{
327
343
  type: Directive,
328
344
  args: [{
329
345
  selector: '[wrDialogTitle]',
@@ -346,10 +362,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
346
362
  * ```
347
363
  */
348
364
  class WrDialogContent {
349
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDialogContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
350
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.0", type: WrDialogContent, isStandalone: true, selector: "[wrDialogContent]", host: { classAttribute: "wr-dialog__content" }, ngImport: i0 });
365
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDialogContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
366
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.1", type: WrDialogContent, isStandalone: true, selector: "[wrDialogContent]", host: { classAttribute: "wr-dialog__content" }, ngImport: i0 });
351
367
  }
352
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDialogContent, decorators: [{
368
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDialogContent, decorators: [{
353
369
  type: Directive,
354
370
  args: [{
355
371
  selector: '[wrDialogContent]',
@@ -384,10 +400,10 @@ class WrDialogFooter {
384
400
  ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
385
401
  classes = computed(() => `wr-dialog__footer wr-dialog__footer--${this.align()}`, /* @ts-ignore */
386
402
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
387
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDialogFooter, deps: [], target: i0.ɵɵFactoryTarget.Directive });
388
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.0", type: WrDialogFooter, isStandalone: true, selector: "[wrDialogFooter]", inputs: { align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0 });
403
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDialogFooter, deps: [], target: i0.ɵɵFactoryTarget.Directive });
404
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.1", type: WrDialogFooter, isStandalone: true, selector: "[wrDialogFooter]", inputs: { align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0 });
389
405
  }
390
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDialogFooter, decorators: [{
406
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDialogFooter, decorators: [{
391
407
  type: Directive,
392
408
  args: [{
393
409
  selector: '[wrDialogFooter]',
@@ -425,10 +441,10 @@ class WrDialogClose {
425
441
  onClick() {
426
442
  this.ref?.close(this.result());
427
443
  }
428
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDialogClose, deps: [], target: i0.ɵɵFactoryTarget.Directive });
429
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.0", type: WrDialogClose, isStandalone: true, selector: "[wrDialogClose]", inputs: { result: { classPropertyName: "result", publicName: "wrDialogClose", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick()" } }, ngImport: i0 });
444
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDialogClose, deps: [], target: i0.ɵɵFactoryTarget.Directive });
445
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.1", type: WrDialogClose, isStandalone: true, selector: "[wrDialogClose]", inputs: { result: { classPropertyName: "result", publicName: "wrDialogClose", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick()" } }, ngImport: i0 });
430
446
  }
431
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDialogClose, decorators: [{
447
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrDialogClose, decorators: [{
432
448
  type: Directive,
433
449
  args: [{
434
450
  selector: '[wrDialogClose]',