ngwr 14.7.0 → 14.9.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 (482) hide show
  1. package/README.md +66 -332
  2. package/alert/styles/_index.scss +10 -0
  3. package/avatar/styles/_index.scss +18 -7
  4. package/badge/styles/_index.scss +7 -0
  5. package/badge/styles/_tag.scss +7 -1
  6. package/bar-chart/styles/_index.scss +1 -0
  7. package/button/styles/_index.scss +6 -0
  8. package/calendar-heatmap/styles/_index.scss +1 -0
  9. package/cascader/styles/_rules.scss +87 -15
  10. package/checkbox/styles/_index.scss +4 -0
  11. package/command-palette/styles/_index.scss +1 -1
  12. package/date-picker/styles/_index.scss +30 -0
  13. package/density/styles/_index.scss +4 -2
  14. package/divider/styles/_index.scss +2 -0
  15. package/donut-chart/styles/_index.scss +10 -0
  16. package/dropdown/styles/_index.scss +67 -5
  17. package/editor/styles/_index.scss +441 -0
  18. package/event-calendar/styles/_index.scss +209 -35
  19. package/fesm2022/ngwr-action-sheet-testing.mjs.map +1 -1
  20. package/fesm2022/ngwr-action-sheet.mjs +3 -3
  21. package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
  22. package/fesm2022/ngwr-affix.mjs +3 -3
  23. package/fesm2022/ngwr-affix.mjs.map +1 -1
  24. package/fesm2022/ngwr-alert.mjs +3 -3
  25. package/fesm2022/ngwr-alert.mjs.map +1 -1
  26. package/fesm2022/ngwr-anchor.mjs +3 -3
  27. package/fesm2022/ngwr-anchor.mjs.map +1 -1
  28. package/fesm2022/ngwr-aurora.mjs +3 -3
  29. package/fesm2022/ngwr-aurora.mjs.map +1 -1
  30. package/fesm2022/ngwr-avatar.mjs +3 -3
  31. package/fesm2022/ngwr-avatar.mjs.map +1 -1
  32. package/fesm2022/ngwr-back-top.mjs +3 -3
  33. package/fesm2022/ngwr-back-top.mjs.map +1 -1
  34. package/fesm2022/ngwr-badge.mjs +28 -13
  35. package/fesm2022/ngwr-badge.mjs.map +1 -1
  36. package/fesm2022/ngwr-bar-chart-testing.mjs.map +1 -1
  37. package/fesm2022/ngwr-bar-chart.mjs +31 -6
  38. package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
  39. package/fesm2022/ngwr-blur-text-testing.mjs.map +1 -1
  40. package/fesm2022/ngwr-blur-text.mjs +3 -3
  41. package/fesm2022/ngwr-blur-text.mjs.map +1 -1
  42. package/fesm2022/ngwr-border-glow-testing.mjs.map +1 -1
  43. package/fesm2022/ngwr-border-glow.mjs +3 -3
  44. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  45. package/fesm2022/ngwr-breadcrumbs.mjs +6 -6
  46. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  47. package/fesm2022/ngwr-burger.mjs +3 -3
  48. package/fesm2022/ngwr-burger.mjs.map +1 -1
  49. package/fesm2022/ngwr-button-testing.mjs.map +1 -1
  50. package/fesm2022/ngwr-button.mjs +6 -6
  51. package/fesm2022/ngwr-button.mjs.map +1 -1
  52. package/fesm2022/ngwr-calendar-heatmap-testing.mjs.map +1 -1
  53. package/fesm2022/ngwr-calendar-heatmap.mjs +61 -6
  54. package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
  55. package/fesm2022/ngwr-calendar-testing.mjs.map +1 -1
  56. package/fesm2022/ngwr-calendar.mjs +3 -3
  57. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  58. package/fesm2022/ngwr-card.mjs +9 -9
  59. package/fesm2022/ngwr-card.mjs.map +1 -1
  60. package/fesm2022/ngwr-carousel-testing.mjs.map +1 -1
  61. package/fesm2022/ngwr-carousel.mjs +6 -6
  62. package/fesm2022/ngwr-carousel.mjs.map +1 -1
  63. package/fesm2022/ngwr-cascader-testing.mjs.map +1 -1
  64. package/fesm2022/ngwr-cascader.mjs +4 -4
  65. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  66. package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -1
  67. package/fesm2022/ngwr-checkbox.mjs +18 -8
  68. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  69. package/fesm2022/ngwr-circular-text-testing.mjs.map +1 -1
  70. package/fesm2022/ngwr-circular-text.mjs +3 -3
  71. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  72. package/fesm2022/ngwr-click-spark.mjs +3 -3
  73. package/fesm2022/ngwr-click-spark.mjs.map +1 -1
  74. package/fesm2022/ngwr-clipboard.mjs +3 -3
  75. package/fesm2022/ngwr-clipboard.mjs.map +1 -1
  76. package/fesm2022/ngwr-collapse-testing.mjs.map +1 -1
  77. package/fesm2022/ngwr-collapse.mjs +9 -9
  78. package/fesm2022/ngwr-collapse.mjs.map +1 -1
  79. package/fesm2022/ngwr-color-picker-testing.mjs.map +1 -1
  80. package/fesm2022/ngwr-color-picker.mjs +6 -6
  81. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  82. package/fesm2022/ngwr-command-palette-testing.mjs.map +1 -1
  83. package/fesm2022/ngwr-command-palette.mjs +3 -3
  84. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  85. package/fesm2022/ngwr-compare.mjs +3 -3
  86. package/fesm2022/ngwr-compare.mjs.map +1 -1
  87. package/fesm2022/ngwr-confetti.mjs +3 -3
  88. package/fesm2022/ngwr-confetti.mjs.map +1 -1
  89. package/fesm2022/ngwr-config.mjs.map +1 -1
  90. package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -1
  91. package/fesm2022/ngwr-context-menu.mjs +12 -12
  92. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  93. package/fesm2022/ngwr-cookie.mjs +3 -3
  94. package/fesm2022/ngwr-cookie.mjs.map +1 -1
  95. package/fesm2022/ngwr-counter.mjs +6 -6
  96. package/fesm2022/ngwr-counter.mjs.map +1 -1
  97. package/fesm2022/ngwr-date-adapters-fns.mjs +3 -3
  98. package/fesm2022/ngwr-date-adapters-fns.mjs.map +1 -1
  99. package/fesm2022/ngwr-date-adapters-luxon.mjs +3 -3
  100. package/fesm2022/ngwr-date-adapters-luxon.mjs.map +1 -1
  101. package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -1
  102. package/fesm2022/ngwr-date-picker.mjs +721 -62
  103. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  104. package/fesm2022/ngwr-date.mjs +3 -3
  105. package/fesm2022/ngwr-date.mjs.map +1 -1
  106. package/fesm2022/ngwr-decrypt-text-testing.mjs.map +1 -1
  107. package/fesm2022/ngwr-decrypt-text.mjs +3 -3
  108. package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
  109. package/fesm2022/ngwr-density.mjs +6 -6
  110. package/fesm2022/ngwr-density.mjs.map +1 -1
  111. package/fesm2022/ngwr-descriptions.mjs +6 -6
  112. package/fesm2022/ngwr-descriptions.mjs.map +1 -1
  113. package/fesm2022/ngwr-dialog-testing.mjs.map +1 -1
  114. package/fesm2022/ngwr-dialog.mjs +15 -15
  115. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  116. package/fesm2022/ngwr-directives.mjs +12 -12
  117. package/fesm2022/ngwr-directives.mjs.map +1 -1
  118. package/fesm2022/ngwr-divider.mjs +3 -3
  119. package/fesm2022/ngwr-divider.mjs.map +1 -1
  120. package/fesm2022/ngwr-donut-chart-testing.mjs.map +1 -1
  121. package/fesm2022/ngwr-donut-chart.mjs +48 -6
  122. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  123. package/fesm2022/ngwr-drag-drop.mjs +6 -6
  124. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  125. package/fesm2022/ngwr-drawer-testing.mjs.map +1 -1
  126. package/fesm2022/ngwr-drawer.mjs +18 -18
  127. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  128. package/fesm2022/ngwr-dropdown-testing.mjs.map +1 -1
  129. package/fesm2022/ngwr-dropdown.mjs +174 -25
  130. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  131. package/fesm2022/ngwr-editor-testing.mjs +568 -0
  132. package/fesm2022/ngwr-editor-testing.mjs.map +1 -0
  133. package/fesm2022/ngwr-editor.mjs +2601 -0
  134. package/fesm2022/ngwr-editor.mjs.map +1 -0
  135. package/fesm2022/ngwr-empty.mjs +3 -3
  136. package/fesm2022/ngwr-empty.mjs.map +1 -1
  137. package/fesm2022/ngwr-event-calendar-testing.mjs.map +1 -1
  138. package/fesm2022/ngwr-event-calendar.mjs +14 -7
  139. package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
  140. package/fesm2022/ngwr-falling-text-testing.mjs.map +1 -1
  141. package/fesm2022/ngwr-falling-text.mjs +3 -3
  142. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  143. package/fesm2022/ngwr-file-upload-testing.mjs.map +1 -1
  144. package/fesm2022/ngwr-file-upload.mjs +3 -3
  145. package/fesm2022/ngwr-file-upload.mjs.map +1 -1
  146. package/fesm2022/ngwr-form-testing.mjs.map +1 -1
  147. package/fesm2022/ngwr-form.mjs +61 -10
  148. package/fesm2022/ngwr-form.mjs.map +1 -1
  149. package/fesm2022/ngwr-fuzzy-text-testing.mjs.map +1 -1
  150. package/fesm2022/ngwr-fuzzy-text.mjs +3 -3
  151. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  152. package/fesm2022/ngwr-gauge-testing.mjs.map +1 -1
  153. package/fesm2022/ngwr-gauge.mjs +35 -6
  154. package/fesm2022/ngwr-gauge.mjs.map +1 -1
  155. package/fesm2022/ngwr-glitch-text-testing.mjs.map +1 -1
  156. package/fesm2022/ngwr-glitch-text.mjs +3 -3
  157. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  158. package/fesm2022/ngwr-gradient-text-testing.mjs.map +1 -1
  159. package/fesm2022/ngwr-gradient-text.mjs +3 -3
  160. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  161. package/fesm2022/ngwr-graph-testing.mjs.map +1 -1
  162. package/fesm2022/ngwr-graph.mjs +6 -6
  163. package/fesm2022/ngwr-graph.mjs.map +1 -1
  164. package/fesm2022/ngwr-hotkey.mjs +6 -6
  165. package/fesm2022/ngwr-hotkey.mjs.map +1 -1
  166. package/fesm2022/ngwr-i18n-ar.mjs +31 -0
  167. package/fesm2022/ngwr-i18n-ar.mjs.map +1 -1
  168. package/fesm2022/ngwr-i18n-cs.mjs +31 -0
  169. package/fesm2022/ngwr-i18n-cs.mjs.map +1 -1
  170. package/fesm2022/ngwr-i18n-de.mjs +31 -0
  171. package/fesm2022/ngwr-i18n-de.mjs.map +1 -1
  172. package/fesm2022/ngwr-i18n-en.mjs +39 -0
  173. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  174. package/fesm2022/ngwr-i18n-es.mjs +31 -0
  175. package/fesm2022/ngwr-i18n-es.mjs.map +1 -1
  176. package/fesm2022/ngwr-i18n-fr.mjs +31 -0
  177. package/fesm2022/ngwr-i18n-fr.mjs.map +1 -1
  178. package/fesm2022/ngwr-i18n-he.mjs +31 -0
  179. package/fesm2022/ngwr-i18n-he.mjs.map +1 -1
  180. package/fesm2022/ngwr-i18n-hi.mjs +31 -0
  181. package/fesm2022/ngwr-i18n-hi.mjs.map +1 -1
  182. package/fesm2022/ngwr-i18n-id.mjs +31 -0
  183. package/fesm2022/ngwr-i18n-id.mjs.map +1 -1
  184. package/fesm2022/ngwr-i18n-it.mjs +31 -0
  185. package/fesm2022/ngwr-i18n-it.mjs.map +1 -1
  186. package/fesm2022/ngwr-i18n-ja.mjs +31 -0
  187. package/fesm2022/ngwr-i18n-ja.mjs.map +1 -1
  188. package/fesm2022/ngwr-i18n-ko.mjs +31 -0
  189. package/fesm2022/ngwr-i18n-ko.mjs.map +1 -1
  190. package/fesm2022/ngwr-i18n-nl.mjs +31 -0
  191. package/fesm2022/ngwr-i18n-nl.mjs.map +1 -1
  192. package/fesm2022/ngwr-i18n-pl.mjs +31 -0
  193. package/fesm2022/ngwr-i18n-pl.mjs.map +1 -1
  194. package/fesm2022/ngwr-i18n-pt.mjs +31 -0
  195. package/fesm2022/ngwr-i18n-pt.mjs.map +1 -1
  196. package/fesm2022/ngwr-i18n-ru.mjs +31 -0
  197. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  198. package/fesm2022/ngwr-i18n-sv.mjs +31 -0
  199. package/fesm2022/ngwr-i18n-sv.mjs.map +1 -1
  200. package/fesm2022/ngwr-i18n-tr.mjs +31 -0
  201. package/fesm2022/ngwr-i18n-tr.mjs.map +1 -1
  202. package/fesm2022/ngwr-i18n-uk.mjs +31 -0
  203. package/fesm2022/ngwr-i18n-uk.mjs.map +1 -1
  204. package/fesm2022/ngwr-i18n-vi.mjs +31 -0
  205. package/fesm2022/ngwr-i18n-vi.mjs.map +1 -1
  206. package/fesm2022/ngwr-i18n-zh-TW.mjs +31 -0
  207. package/fesm2022/ngwr-i18n-zh-TW.mjs.map +1 -1
  208. package/fesm2022/ngwr-i18n-zh.mjs +31 -0
  209. package/fesm2022/ngwr-i18n-zh.mjs.map +1 -1
  210. package/fesm2022/ngwr-i18n.mjs +9 -9
  211. package/fesm2022/ngwr-i18n.mjs.map +1 -1
  212. package/fesm2022/ngwr-icon-adapters-feather.mjs.map +1 -1
  213. package/fesm2022/ngwr-icon-adapters-lucide.mjs.map +1 -1
  214. package/fesm2022/ngwr-icon.mjs +6 -6
  215. package/fesm2022/ngwr-icon.mjs.map +1 -1
  216. package/fesm2022/ngwr-image-cropper-testing.mjs.map +1 -1
  217. package/fesm2022/ngwr-image-cropper.mjs +3 -3
  218. package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
  219. package/fesm2022/ngwr-input-number-testing.mjs.map +1 -1
  220. package/fesm2022/ngwr-input-number.mjs +15 -3
  221. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  222. package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -1
  223. package/fesm2022/ngwr-input-otp.mjs +3 -3
  224. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  225. package/fesm2022/ngwr-input-testing.mjs.map +1 -1
  226. package/fesm2022/ngwr-input.mjs +15 -15
  227. package/fesm2022/ngwr-input.mjs.map +1 -1
  228. package/fesm2022/ngwr-keyboard.mjs +3 -3
  229. package/fesm2022/ngwr-keyboard.mjs.map +1 -1
  230. package/fesm2022/ngwr-knob-testing.mjs.map +1 -1
  231. package/fesm2022/ngwr-knob.mjs +3 -3
  232. package/fesm2022/ngwr-knob.mjs.map +1 -1
  233. package/fesm2022/ngwr-layout.mjs +15 -15
  234. package/fesm2022/ngwr-layout.mjs.map +1 -1
  235. package/fesm2022/ngwr-lightbox-testing.mjs.map +1 -1
  236. package/fesm2022/ngwr-lightbox.mjs +3 -3
  237. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  238. package/fesm2022/ngwr-line-chart-testing.mjs.map +1 -1
  239. package/fesm2022/ngwr-line-chart.mjs +18 -7
  240. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  241. package/fesm2022/ngwr-list.mjs +6 -6
  242. package/fesm2022/ngwr-list.mjs.map +1 -1
  243. package/fesm2022/ngwr-loading-bar-router.mjs.map +1 -1
  244. package/fesm2022/ngwr-loading-bar.mjs +6 -6
  245. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  246. package/fesm2022/ngwr-markdown-testing.mjs.map +1 -1
  247. package/fesm2022/ngwr-markdown.mjs +798 -17
  248. package/fesm2022/ngwr-markdown.mjs.map +1 -1
  249. package/fesm2022/ngwr-marquee-testing.mjs.map +1 -1
  250. package/fesm2022/ngwr-marquee.mjs +3 -3
  251. package/fesm2022/ngwr-marquee.mjs.map +1 -1
  252. package/fesm2022/ngwr-media.mjs +3 -3
  253. package/fesm2022/ngwr-media.mjs.map +1 -1
  254. package/fesm2022/ngwr-mention-testing.mjs.map +1 -1
  255. package/fesm2022/ngwr-mention.mjs +6 -6
  256. package/fesm2022/ngwr-mention.mjs.map +1 -1
  257. package/fesm2022/ngwr-meta.mjs +6 -6
  258. package/fesm2022/ngwr-meta.mjs.map +1 -1
  259. package/fesm2022/ngwr-meter-group-testing.mjs +7 -3
  260. package/fesm2022/ngwr-meter-group-testing.mjs.map +1 -1
  261. package/fesm2022/ngwr-meter-group.mjs +26 -6
  262. package/fesm2022/ngwr-meter-group.mjs.map +1 -1
  263. package/fesm2022/ngwr-overlay.mjs +6 -6
  264. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  265. package/fesm2022/ngwr-page-header.mjs +13 -5
  266. package/fesm2022/ngwr-page-header.mjs.map +1 -1
  267. package/fesm2022/ngwr-pagination-testing.mjs.map +1 -1
  268. package/fesm2022/ngwr-pagination.mjs +3 -3
  269. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  270. package/fesm2022/ngwr-pipes.mjs +21 -21
  271. package/fesm2022/ngwr-pipes.mjs.map +1 -1
  272. package/fesm2022/ngwr-platform.mjs +9 -9
  273. package/fesm2022/ngwr-platform.mjs.map +1 -1
  274. package/fesm2022/ngwr-popconfirm-testing.mjs.map +1 -1
  275. package/fesm2022/ngwr-popconfirm.mjs +6 -6
  276. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  277. package/fesm2022/ngwr-popover-testing.mjs.map +1 -1
  278. package/fesm2022/ngwr-popover.mjs +578 -16
  279. package/fesm2022/ngwr-popover.mjs.map +1 -1
  280. package/fesm2022/ngwr-progress.mjs +3 -3
  281. package/fesm2022/ngwr-progress.mjs.map +1 -1
  282. package/fesm2022/ngwr-pull-to-refresh.mjs +3 -3
  283. package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -1
  284. package/fesm2022/ngwr-qr.mjs +3 -3
  285. package/fesm2022/ngwr-qr.mjs.map +1 -1
  286. package/fesm2022/ngwr-radio-testing.mjs.map +1 -1
  287. package/fesm2022/ngwr-radio.mjs +6 -6
  288. package/fesm2022/ngwr-radio.mjs.map +1 -1
  289. package/fesm2022/ngwr-rating-testing.mjs.map +1 -1
  290. package/fesm2022/ngwr-rating.mjs +3 -3
  291. package/fesm2022/ngwr-rating.mjs.map +1 -1
  292. package/fesm2022/ngwr-result.mjs +12 -12
  293. package/fesm2022/ngwr-result.mjs.map +1 -1
  294. package/fesm2022/ngwr-rotating-text-testing.mjs.map +1 -1
  295. package/fesm2022/ngwr-rotating-text.mjs +3 -3
  296. package/fesm2022/ngwr-rotating-text.mjs.map +1 -1
  297. package/fesm2022/ngwr-schema-form.mjs +3 -3
  298. package/fesm2022/ngwr-schema-form.mjs.map +1 -1
  299. package/fesm2022/ngwr-scroll.mjs +3 -3
  300. package/fesm2022/ngwr-scroll.mjs.map +1 -1
  301. package/fesm2022/ngwr-segmented-testing.mjs.map +1 -1
  302. package/fesm2022/ngwr-segmented.mjs +3 -3
  303. package/fesm2022/ngwr-segmented.mjs.map +1 -1
  304. package/fesm2022/ngwr-select-testing.mjs.map +1 -1
  305. package/fesm2022/ngwr-select.mjs +12 -12
  306. package/fesm2022/ngwr-select.mjs.map +1 -1
  307. package/fesm2022/ngwr-shiny-text-testing.mjs.map +1 -1
  308. package/fesm2022/ngwr-shiny-text.mjs +6 -6
  309. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  310. package/fesm2022/ngwr-sidebar.mjs +10 -3
  311. package/fesm2022/ngwr-sidebar.mjs.map +1 -1
  312. package/fesm2022/ngwr-skeleton.mjs +3 -3
  313. package/fesm2022/ngwr-skeleton.mjs.map +1 -1
  314. package/fesm2022/ngwr-slider-testing.mjs.map +1 -1
  315. package/fesm2022/ngwr-slider.mjs +3 -3
  316. package/fesm2022/ngwr-slider.mjs.map +1 -1
  317. package/fesm2022/ngwr-sparkline-testing.mjs.map +1 -1
  318. package/fesm2022/ngwr-sparkline.mjs +84 -10
  319. package/fesm2022/ngwr-sparkline.mjs.map +1 -1
  320. package/fesm2022/ngwr-speed-dial-testing.mjs.map +1 -1
  321. package/fesm2022/ngwr-speed-dial.mjs +3 -3
  322. package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
  323. package/fesm2022/ngwr-spinner.mjs +3 -3
  324. package/fesm2022/ngwr-spinner.mjs.map +1 -1
  325. package/fesm2022/ngwr-splash-cursor-testing.mjs.map +1 -1
  326. package/fesm2022/ngwr-splash-cursor.mjs +3 -3
  327. package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
  328. package/fesm2022/ngwr-split-text-testing.mjs.map +1 -1
  329. package/fesm2022/ngwr-split-text.mjs +3 -3
  330. package/fesm2022/ngwr-split-text.mjs.map +1 -1
  331. package/fesm2022/ngwr-splitter-testing.mjs.map +1 -1
  332. package/fesm2022/ngwr-splitter.mjs +3 -3
  333. package/fesm2022/ngwr-splitter.mjs.map +1 -1
  334. package/fesm2022/ngwr-spotlight-card-testing.mjs.map +1 -1
  335. package/fesm2022/ngwr-spotlight-card.mjs +6 -6
  336. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  337. package/fesm2022/ngwr-squircle.mjs +6 -6
  338. package/fesm2022/ngwr-squircle.mjs.map +1 -1
  339. package/fesm2022/ngwr-star-border-testing.mjs.map +1 -1
  340. package/fesm2022/ngwr-star-border.mjs +3 -3
  341. package/fesm2022/ngwr-star-border.mjs.map +1 -1
  342. package/fesm2022/ngwr-statistic.mjs +9 -9
  343. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  344. package/fesm2022/ngwr-stepper-testing.mjs.map +1 -1
  345. package/fesm2022/ngwr-stepper.mjs +6 -6
  346. package/fesm2022/ngwr-stepper.mjs.map +1 -1
  347. package/fesm2022/ngwr-storage.mjs +3 -3
  348. package/fesm2022/ngwr-storage.mjs.map +1 -1
  349. package/fesm2022/ngwr-switch-testing.mjs.map +1 -1
  350. package/fesm2022/ngwr-switch.mjs +3 -3
  351. package/fesm2022/ngwr-switch.mjs.map +1 -1
  352. package/fesm2022/ngwr-table-testing.mjs.map +1 -1
  353. package/fesm2022/ngwr-table.mjs +18 -18
  354. package/fesm2022/ngwr-table.mjs.map +1 -1
  355. package/fesm2022/ngwr-tabs-router.mjs +3 -3
  356. package/fesm2022/ngwr-tabs-router.mjs.map +1 -1
  357. package/fesm2022/ngwr-tabs-testing.mjs.map +1 -1
  358. package/fesm2022/ngwr-tabs.mjs +6 -6
  359. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  360. package/fesm2022/ngwr-textarea-testing.mjs.map +1 -1
  361. package/fesm2022/ngwr-textarea.mjs +3 -3
  362. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  363. package/fesm2022/ngwr-theme.mjs +3 -3
  364. package/fesm2022/ngwr-theme.mjs.map +1 -1
  365. package/fesm2022/ngwr-tilt-card-testing.mjs.map +1 -1
  366. package/fesm2022/ngwr-tilt-card.mjs +6 -6
  367. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  368. package/fesm2022/ngwr-timeline.mjs +6 -6
  369. package/fesm2022/ngwr-timeline.mjs.map +1 -1
  370. package/fesm2022/ngwr-toast-testing.mjs.map +1 -1
  371. package/fesm2022/ngwr-toast.mjs +9 -9
  372. package/fesm2022/ngwr-toast.mjs.map +1 -1
  373. package/fesm2022/ngwr-toolbar.mjs +10 -3
  374. package/fesm2022/ngwr-toolbar.mjs.map +1 -1
  375. package/fesm2022/ngwr-tour-testing.mjs.map +1 -1
  376. package/fesm2022/ngwr-tour.mjs +6 -6
  377. package/fesm2022/ngwr-tour.mjs.map +1 -1
  378. package/fesm2022/ngwr-transfer-testing.mjs.map +1 -1
  379. package/fesm2022/ngwr-transfer.mjs +3 -3
  380. package/fesm2022/ngwr-transfer.mjs.map +1 -1
  381. package/fesm2022/ngwr-tree-testing.mjs.map +1 -1
  382. package/fesm2022/ngwr-tree.mjs +3 -3
  383. package/fesm2022/ngwr-tree.mjs.map +1 -1
  384. package/fesm2022/ngwr-typewriter-testing.mjs.map +1 -1
  385. package/fesm2022/ngwr-typewriter.mjs +3 -3
  386. package/fesm2022/ngwr-typewriter.mjs.map +1 -1
  387. package/fesm2022/ngwr-typography.mjs +7 -3
  388. package/fesm2022/ngwr-typography.mjs.map +1 -1
  389. package/fesm2022/ngwr-utils.mjs.map +1 -1
  390. package/fesm2022/ngwr-validators.mjs.map +1 -1
  391. package/fesm2022/ngwr-version.mjs +1 -1
  392. package/fesm2022/ngwr-version.mjs.map +1 -1
  393. package/fesm2022/ngwr-virtual-scroll.mjs +3 -3
  394. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  395. package/fesm2022/ngwr-waves-testing.mjs.map +1 -1
  396. package/fesm2022/ngwr-waves.mjs +3 -3
  397. package/fesm2022/ngwr-waves.mjs.map +1 -1
  398. package/fesm2022/ngwr-window-testing.mjs.map +1 -1
  399. package/fesm2022/ngwr-window.mjs +12 -12
  400. package/fesm2022/ngwr-window.mjs.map +1 -1
  401. package/form/styles/_index.scss +16 -1
  402. package/gauge/styles/_index.scss +1 -0
  403. package/i18n/ar.json +32 -1
  404. package/i18n/cs.json +32 -1
  405. package/i18n/de.json +32 -1
  406. package/i18n/en.json +32 -1
  407. package/i18n/es.json +32 -1
  408. package/i18n/fr.json +32 -1
  409. package/i18n/he.json +32 -1
  410. package/i18n/hi.json +32 -1
  411. package/i18n/id.json +32 -1
  412. package/i18n/it.json +32 -1
  413. package/i18n/ja.json +32 -1
  414. package/i18n/ko.json +32 -1
  415. package/i18n/nl.json +32 -1
  416. package/i18n/pl.json +32 -1
  417. package/i18n/pt.json +32 -1
  418. package/i18n/ru.json +32 -1
  419. package/i18n/sv.json +32 -1
  420. package/i18n/tr.json +32 -1
  421. package/i18n/uk.json +32 -1
  422. package/i18n/vi.json +32 -1
  423. package/i18n/zh-TW.json +32 -1
  424. package/i18n/zh.json +32 -1
  425. package/input/styles/_index.scss +24 -1
  426. package/input-number/styles/_index.scss +69 -0
  427. package/input-otp/styles/_index.scss +5 -5
  428. package/line-chart/styles/_index.scss +30 -2
  429. package/llms-full.txt +14 -4
  430. package/llms.txt +188 -132
  431. package/mcp/providers.js +2 -2
  432. package/mcp/server.js +1 -1
  433. package/meter-group/styles/_index.scss +1 -0
  434. package/overlay/styles/_arrow.scss +30 -2
  435. package/package.json +43 -2
  436. package/page-header/styles/_index.scss +37 -1
  437. package/pagination/styles/_index.scss +9 -5
  438. package/popover/styles/_index.scss +73 -5
  439. package/progress/styles/_index.scss +4 -0
  440. package/radio/styles/_index.scss +4 -1
  441. package/schematics/use/symbol-map.json +1 -0
  442. package/select/styles/_index.scss +51 -12
  443. package/sidebar/styles/_index.scss +44 -2
  444. package/skeleton/styles/_index.scss +3 -0
  445. package/skills/ngwr/SKILL.md +5 -5
  446. package/skills/ngwr/references/catalog.md +2 -0
  447. package/skills/ngwr/references/setup.md +3 -3
  448. package/sparkline/styles/_index.scss +19 -0
  449. package/styles.scss +1 -0
  450. package/table/styles/_index.scss +7 -0
  451. package/textarea/styles/_index.scss +12 -3
  452. package/theme/styles/_colors.scss +39 -13
  453. package/theme/styles/_contrast.scss +9 -7
  454. package/toast/styles/_index.scss +4 -0
  455. package/toolbar/styles/_index.scss +35 -1
  456. package/tree/styles/_index.scss +46 -7
  457. package/types/ngwr-badge.d.ts +22 -7
  458. package/types/ngwr-bar-chart.d.ts +19 -1
  459. package/types/ngwr-calendar-heatmap.d.ts +29 -1
  460. package/types/ngwr-checkbox.d.ts +2 -0
  461. package/types/ngwr-config.d.ts +12 -0
  462. package/types/ngwr-date-picker.d.ts +308 -43
  463. package/types/ngwr-donut-chart.d.ts +24 -1
  464. package/types/ngwr-dropdown.d.ts +22 -2
  465. package/types/ngwr-editor-testing.d.ts +378 -0
  466. package/types/ngwr-editor.d.ts +449 -0
  467. package/types/ngwr-event-calendar.d.ts +8 -0
  468. package/types/ngwr-form.d.ts +35 -5
  469. package/types/ngwr-gauge.d.ts +20 -1
  470. package/types/ngwr-input-number.d.ts +7 -0
  471. package/types/ngwr-line-chart.d.ts +9 -1
  472. package/types/ngwr-markdown.d.ts +61 -2
  473. package/types/ngwr-meter-group-testing.d.ts +3 -2
  474. package/types/ngwr-meter-group.d.ts +14 -1
  475. package/types/ngwr-page-header.d.ts +10 -2
  476. package/types/ngwr-popover.d.ts +154 -3
  477. package/types/ngwr-sidebar.d.ts +7 -0
  478. package/types/ngwr-sparkline.d.ts +43 -1
  479. package/types/ngwr-toolbar.d.ts +7 -0
  480. package/types/ngwr-typography.d.ts +4 -0
  481. package/types/ngwr-version.d.ts +1 -1
  482. package/typography/styles/_index.scss +16 -0
@@ -386,10 +386,10 @@ class WrOutsideClick {
386
386
  this.cleanup = null;
387
387
  this.pressOrigin = null;
388
388
  }
389
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrOutsideClick, deps: [], target: i0.ɵɵFactoryTarget.Service });
390
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.6", ngImport: i0, type: WrOutsideClick });
389
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrOutsideClick, deps: [], target: i0.ɵɵFactoryTarget.Service });
390
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.7", ngImport: i0, type: WrOutsideClick });
391
391
  }
392
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrOutsideClick, decorators: [{
392
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrOutsideClick, decorators: [{
393
393
  type: Service
394
394
  }] });
395
395
 
@@ -420,10 +420,10 @@ class WrOverlayContainer extends OverlayContainer {
420
420
  super._createContainer();
421
421
  this._containerElement?.classList.add('wr-overlay-container');
422
422
  }
423
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrOverlayContainer, deps: [], target: i0.ɵɵFactoryTarget.Service });
424
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.6", ngImport: i0, type: WrOverlayContainer });
423
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrOverlayContainer, deps: [], target: i0.ɵɵFactoryTarget.Service });
424
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.7", ngImport: i0, type: WrOverlayContainer });
425
425
  }
426
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrOverlayContainer, decorators: [{
426
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrOverlayContainer, decorators: [{
427
427
  type: Service
428
428
  }] });
429
429
 
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-overlay.mjs","sources":["../../../projects/lib/overlay/wr-overlay-close.ts","../../../projects/lib/overlay/wr-follow-direction.ts","../../../projects/lib/overlay/wr-mirror-offsets.ts","../../../projects/lib/overlay/wr-outside-click.ts","../../../projects/lib/overlay/wr-overlay-container.ts","../../../projects/lib/overlay/tokens/wr-overlay.token.ts","../../../projects/lib/overlay/tokens/wr-overlay-container.token.ts","../../../projects/lib/overlay/tokens/wr-responsive-overlays.token.ts","../../../projects/lib/overlay/provide-wr-overlay.ts","../../../projects/lib/overlay/provide-wr-responsive-overlays.ts","../../../projects/lib/overlay/ngwr-overlay.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\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/** The same 24×24 stroked ✕ the rest of the library's chrome draws (alert, toast, lightbox). */\nconst CLOSE_ICON_ATTRS: readonly (readonly [string, string])[] = [\n ['class', 'wr-icon__svg'],\n ['viewBox', '0 0 24 24'],\n ['fill', 'none'],\n ['stroke', 'currentColor'],\n ['stroke-width', '2'],\n ['stroke-linecap', 'round'],\n ['stroke-linejoin', 'round'],\n ['aria-hidden', 'true'],\n];\nconst CLOSE_ICON_PATHS: readonly string[] = ['M18 6 6 18', 'm6 6 12 12'];\n\n/**\n * Builds the ✕ node by node.\n *\n * It was one `innerHTML = CLOSE_ICON`, and the string was a compile-time\n * constant, so it was never an injection risk — it was an AVAILABILITY one.\n * Under `require-trusted-types-for 'script'` an `innerHTML` write throws\n * `TrustedHTML assignment` whatever the string is, and the throw landed after\n * the overlay was on screen: a modal with no ✕, no backdrop subscription and no\n * Escape handler, over the whole application. `createElementNS` is not a\n * Trusted Types sink, so there is nothing left to police.\n */\nfunction createCloseIcon(doc: Document): SVGSVGElement {\n const svg = doc.createElementNS(SVG_NS, 'svg');\n // `setAttribute`, not `.className` — on an SVG element that property is an\n // `SVGAnimatedString` and assigning a string to it silently does nothing.\n for (const [name, value] of CLOSE_ICON_ATTRS) svg.setAttribute(name, value);\n for (const d of CLOSE_ICON_PATHS) {\n const path = doc.createElementNS(SVG_NS, 'path');\n path.setAttribute('d', d);\n svg.appendChild(path);\n }\n return svg;\n}\n\n/**\n * Appends a dismiss (✕) button to a service-opened overlay panel.\n *\n * `WrDialog` and `WrDrawerManager` build their panel around a component the\n * consumer supplies, so there is no template of their own to put a corner button\n * in — they call this instead. Component-driven overlays (`<wr-drawer>`) render\n * the same markup in their template.\n *\n * Uses `host.ownerDocument` rather than the global `document`, so it carries no\n * hidden browser-only assumption; callers still gate on the platform because\n * they have nothing to append to on the server.\n *\n * @param host Panel element the button is appended to (and positioned against).\n * @param className BEM class for the button, e.g. `wr-dialog__close`.\n * @param label Accessible name — already localized by the caller.\n * @param onClose Invoked on click.\n */\nexport function wrAppendOverlayClose(\n host: HTMLElement,\n className: string,\n label: string,\n onClose: () => void\n): HTMLButtonElement {\n const button = host.ownerDocument.createElement('button');\n button.type = 'button';\n button.className = className;\n button.setAttribute('aria-label', label);\n button.appendChild(createCloseIcon(host.ownerDocument));\n button.addEventListener('click', onClose);\n host.appendChild(button);\n return button;\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { Direction, Directionality } from '@angular/cdk/bidi';\nimport type { OverlayRef } from '@angular/cdk/overlay';\nimport { type Injector, effect, untracked } from '@angular/core';\n\nimport { Subscription } from 'rxjs';\n\nimport { noop } from 'ngwr/utils';\n\n/**\n * Keep an OPEN overlay on the application's reading direction.\n *\n * The CDK reads the direction ONCE, as a string, when the overlay is created\n * (`overlayConfig.direction ||= directionality.value`), writes it as the host's\n * `dir` on attach, and never looks at it again — `updatePosition()` does not\n * touch it and `setDirection()` is the only thing that does. So an application\n * that flips direction while a panel is open mirrors the page and leaves the\n * panel behind, still `ltr`, still resolving `start` to the left. This site's\n * own LTR/RTL switch is the demonstration: it lives inside a `wr-dropdown`, and\n * the `wr-segmented` it is built from reads `Directionality` live — so the thumb\n * slides to the other slot while the pane around it still renders `ltr`, and\n * parks under the wrong label.\n *\n * Call it once per `OverlayRef`, right after `overlay.create(...)`. The follower\n * ends itself when that overlay detaches or is disposed, so a reopen — which is\n * always a NEW ref in this library — needs a new call, and the returned teardown\n * is only for stopping early.\n *\n * `onDirectionChange` is for the sites whose position LIST is itself\n * direction-dependent (the four that pass their table through\n * {@link wrMirrorOffsets}): it runs with the new direction already on the ref\n * and before the overlay repositions, so the strategy is carrying the mirrored\n * offsets by the time the CDK re-resolves them.\n *\n * SSR-safe: it touches no browser global of its own, and the CDK's position\n * strategies no-op off the browser, so a flip on the server only rewrites the\n * attribute.\n *\n * @param overlayRef The overlay to keep in step, freshly created.\n * @param dir The `Directionality` the caller injected. `null` — an optional\n * inject with no provider, i.e. a bare `TestBed` — means there is nothing\n * ambient to follow and this does nothing at all.\n * @param injector Owns the `valueSignal` watch; the caller's own is right.\n * @param onDirectionChange Re-applies direction-dependent state, e.g.\n * `strategy.withPositions(wrMirrorOffsets(TABLE, direction === 'rtl'))`.\n * @returns Stops following. Idempotent, and unnecessary in the normal case.\n *\n * @example\n * ```ts\n * this.overlayRef = this.overlay.create({ positionStrategy, ... });\n * wrFollowDirection(this.overlayRef, this.dir, this.injector, direction =>\n * positionStrategy.withPositions(\n * wrMirrorOffsets(WR_POPCONFIRM_POSITIONS[this.position()], direction === 'rtl')\n * )\n * );\n * ```\n */\nexport function wrFollowDirection(\n overlayRef: OverlayRef,\n dir: Directionality | null,\n injector: Injector,\n onDirectionChange?: (direction: Direction) => void\n): () => void {\n if (!dir) return noop;\n\n const apply = (next: Direction): void => {\n // Comparing against the REF rather than a direction captured up here does\n // three jobs at once: the watch's mandatory first run is a no-op, a flip\n // that arrives down both channels is applied once, and a same-value write\n // never yanks a panel the user is reading.\n if (next === overlayRef.getDirection()) return;\n\n overlayRef.setDirection(next); // rewrites the host's `dir`; it does NOT reposition\n onDirectionChange?.(next); // the caller re-mirrors its position list here\n overlayRef.updatePosition(); // re-resolves start/end against the direction just set\n };\n\n // Two channels, because they are not the same thing. `valueSignal` is the\n // state — `Directionality.value` is a getter over it, so nothing can change\n // direction without writing it. `change` is an EventEmitter the root instance\n // never emits: it reads the document once at construction and only completes\n // the emitter on destroy, so it belongs to the `[dir]` directive (and to an\n // app, like this site's header, that emits it by hand as a courtesy). Keying\n // on `change` alone would be dead for an app that just writes the signal;\n // keying on the signal alone would ignore the `{ value, change }` test double\n // that a dozen of the library's RTL specs hand their component.\n //\n // `untracked` because of WHERE this is called from: half the call sites open\n // their overlay out of an `effect(() => { if (this.isOpen()) … })`, and\n // `effect()` refuses in dev mode to be created inside a reactive context.\n // Laundering only the CREATION is exactly right — the watch below still\n // depends on `valueSignal` and on nothing else.\n const watch = untracked(() =>\n effect(\n () => {\n // Read as a plain optional function rather than as a `Signal`, because\n // the case being guarded is a double that has no signal at all: falling\n // back to `value` registers no dependency, so the watch simply never\n // re-runs and `change` carries that case on its own.\n const read: (() => Direction) | undefined = dir.valueSignal;\n apply(read ? read() : dir.value);\n },\n { injector }\n )\n );\n\n // rxjs owns the teardown, and an `OverlayRef` is why. Open and close happen in\n // an event handler or an effect, never in an injection context, so the idiom\n // that suggests itself — `takeUntilDestroyed(destroyRef)` — would tie this to\n // the DIRECTIVE's lifetime: a menu opened fifty times would leave fifty\n // followers behind, each pinning a disposed ref. (`WrOutsideClick`'s JSDoc\n // records that same mistake, made at ten call sites.) `detachments()` is the\n // overlay's own lifetime and the one channel every dismissal goes through.\n // And it is not hygiene: `setDirection()` writes through the host element\n // `dispose()` nulls, so a watch that outlives its overlay THROWS on the next\n // flip.\n const teardown = new Subscription();\n const stop = (): void => teardown.unsubscribe();\n\n teardown.add(() => watch.destroy());\n teardown.add(dir.change.subscribe(apply));\n // Both handlers, for the reason `WrOutsideClick` gives: a live ref arrives\n // through `next`, one already disposed before this call has only `complete`\n // left to give.\n teardown.add(overlayRef.detachments().subscribe({ next: stop, complete: stop }));\n\n // `Subscription.unsubscribe()` is a no-op once closed, so the caller's copy of\n // this and the automatic one cannot fight, and calling it twice is free.\n return stop;\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { ConnectedPosition } from '@angular/cdk/overlay';\n\n/**\n * Mirror the horizontal offsets of a connected-position list for RTL.\n *\n * The CDK mirrors `originX` / `overlayX` under `dir=\"rtl\"` — a `start` anchor\n * resolves to the origin's right edge — but it does NOT mirror `offsetX`, which\n * it adds to the final PHYSICAL x (`_getOffset` returns `position.offsetX`\n * verbatim). So a position that meant \"sit to the inline-start of the trigger,\n * 8px clear of it\" keeps its `-8` under RTL, where the panel is now on the\n * right: the gap becomes an 8px OVERLAP, and the panel sits on top of the thing\n * it is describing.\n *\n * Nothing in the CDK will do this for us, and the amount is per position, so\n * every ngwr overlay that offsets along the inline axis passes its list through\n * here. `offsetY` is untouched: the block axis does not flip.\n *\n * @example\n * ```ts\n * const dir = inject(Directionality, { optional: true });\n *\n * strategy.withPositions(wrMirrorOffsets(WR_POPOVER_POSITIONS[position], dir?.value === 'rtl'));\n * ```\n */\nexport function wrMirrorOffsets(positions: readonly ConnectedPosition[], isRtl: boolean): ConnectedPosition[] {\n // Copied rather than mutated even when there is nothing to do: the position\n // tables are module-level constants shared by every instance, so handing back\n // the same objects invites a caller to write through them.\n if (!isRtl) return positions.map(position => ({ ...position }));\n\n return positions.map(position => ({\n ...position,\n ...(position.offsetX == null ? {} : { offsetX: -position.offsetX }),\n }));\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { OverlayRef } from '@angular/cdk/overlay';\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport { PLATFORM_ID, Service, inject } from '@angular/core';\n\nimport { Observable, type Subscriber } from 'rxjs';\n\n/** One live subscription to `WrOutsideClick.outsidePointerEvents()`. */\ninterface Watcher {\n readonly overlayRef: OverlayRef;\n readonly subscriber: Subscriber<MouseEvent>;\n}\n\n/**\n * Shadow-piercing `event.target` — `composedPath()[0]` is the real originator\n * when the click started inside a shadow root, where `target` is retargeted to\n * the host.\n */\nfunction eventTarget(event: Event): EventTarget | null {\n if (event.composedPath) {\n try {\n return event.composedPath()[0] ?? event.target;\n } catch {\n /* Detached / synthetic events can throw — fall through to `target`. */\n }\n }\n return event.target;\n}\n\n/** `parent.contains(child)`, but stepping out of shadow roots through their hosts. */\nfunction containsAcrossShadow(parent: Node, child: EventTarget | null): boolean {\n const hasShadowRoot = typeof ShadowRoot !== 'undefined';\n let current = child as Node | null;\n while (current) {\n if (current === parent) return true;\n current = hasShadowRoot && current instanceof ShadowRoot ? current.host : current.parentNode;\n }\n return false;\n}\n\n/**\n * Outside-click source for overlays — a drop-in replacement for\n * `OverlayRef.outsidePointerEvents()`.\n *\n * **Why this exists.** CDK's `OverlayOutsideClickDispatcher` binds its\n * listeners to `document.body`. When page content is shorter than the viewport,\n * a click in the empty space below it targets `<html>` — and `<html>` is\n * `body`'s *parent*, so the event bubbles straight to the document and `body`\n * never sees it. The overlay silently stays open. Listening on the document\n * itself catches both cases, and costs nothing else.\n *\n * Semantics are otherwise identical to the CDK's, deliberately:\n *\n * - Emits on `click` / `auxclick` / `contextmenu`, in the capture phase, and\n * tracks `pointerdown` so a `click` is judged by where the press *started*\n * (a drag that ends outside the pane doesn't count as an outside click).\n * - Walks watchers top-most first and stops at the first one that contains the\n * event, so clicking inside a stacked overlay can't close the ones beneath\n * it (a `wr-select` opened inside a `wr-popover`, say).\n * - Fires for the very click that opened the overlay, which is why every caller\n * also ignores events landing on its own trigger.\n *\n * Registration is per subscription: the document listeners go up with the first\n * watcher and come down with the last, so an app with no open overlay has none.\n * That sentence was aspirational until v11 — see {@link outsidePointerEvents}.\n */\n@Service()\nexport class WrOutsideClick {\n private readonly doc = inject(DOCUMENT);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n /** In attach order — last is top-most. */\n private readonly watchers: Watcher[] = [];\n private cleanup: (() => void) | null = null;\n private pressOrigin: EventTarget | null = null;\n\n /**\n * Emits every `click` / `auxclick` / `contextmenu` that lands outside the\n * given overlay's pane, for as long as the overlay is attached.\n *\n * **It completes when the overlay detaches, and that is load-bearing.** Every\n * one of the ten call sites subscribes inside its own `openOverlay()` and\n * pipes `takeUntilDestroyed(destroyRef)` — a DIRECTIVE lifetime, not an\n * overlay one — and none of them unsubscribes on close, because the natural\n * reading of that idiom is \"this ends with the component\". Without the\n * completion below the teardown never ran: one watcher accumulated per OPEN\n * for the life of the page, each pinning a disposed `OverlayRef` (and through\n * it a detached pane, its portal outlet and their injectors), the four\n * capture-phase document listeners could never come down because\n * `watchers.length` never reached zero, and every click on the page walked a\n * list that only grew. A `mode=\"tooltip\"` popover made it unbounded — one\n * permanent watcher per hover.\n *\n * Completing here rather than fixing ten call sites is deliberate: the next\n * component to open an overlay would have made the same reasonable mistake.\n * It is also what CDK's own `OverlayRef.outsidePointerEvents()` does.\n */\n outsidePointerEvents(overlayRef: OverlayRef): Observable<MouseEvent> {\n return new Observable<MouseEvent>(subscriber => {\n if (!this.isBrowser) return;\n\n const watcher: Watcher = { overlayRef, subscriber };\n this.watchers.push(watcher);\n if (this.watchers.length === 1) this.listen();\n\n // BOTH handlers, and the second one is not defensive padding. `dispose()`\n // emits a detachment and then completes the subject, so a live overlay\n // arrives through `next` — but a ref that was already disposed before\n // anyone subscribed has nothing left to emit and arrives through\n // `complete` alone. Listening for `next` only left exactly the watcher\n // this whole change exists to remove.\n const ended = (): void => subscriber.complete();\n const detached = overlayRef.detachments().subscribe({ next: ended, complete: ended });\n\n return () => {\n detached.unsubscribe();\n const index = this.watchers.indexOf(watcher);\n if (index > -1) this.watchers.splice(index, 1);\n if (!this.watchers.length) this.unlisten();\n };\n });\n }\n\n private readonly onPointerDown = (event: Event): void => {\n this.pressOrigin = eventTarget(event);\n };\n\n private readonly onClick = (event: Event): void => {\n const target = eventTarget(event);\n // `detail > 0` means the click really came from a pointer press. A click\n // activated by Enter or Space carries `detail: 0` and has no `pointerdown`\n // of its own — so trusting a leftover origin there judged it by a press\n // that belonged to something else entirely. A press inside the pane that\n // never produced a click (a drag released off-window, a node removed under\n // the finger, a cancelled touch) survives in `pressOrigin`, and the next\n // keyboard activation anywhere on the page then read as \"inside\": the panel\n // would not close, for keyboard users only.\n const fromPointer = event.type === 'click' && (event as MouseEvent).detail > 0;\n const origin = fromPointer && this.pressOrigin ? this.pressOrigin : target;\n this.pressOrigin = null;\n\n // Snapshot: a watcher that closes on this event unsubscribes synchronously,\n // mutating `watchers` while we're walking it.\n const watchers = this.watchers.slice();\n for (let i = watchers.length - 1; i > -1; i--) {\n const { overlayRef, subscriber } = watchers[i];\n if (!overlayRef.hasAttached()) continue;\n\n const pane = overlayRef.overlayElement;\n if (containsAcrossShadow(pane, target) || containsAcrossShadow(pane, origin)) break;\n\n subscriber.next(event as MouseEvent);\n }\n };\n\n private listen(): void {\n const options: AddEventListenerOptions = { capture: true };\n const doc = this.doc;\n\n doc.addEventListener('pointerdown', this.onPointerDown, options);\n doc.addEventListener('click', this.onClick, options);\n doc.addEventListener('auxclick', this.onClick, options);\n doc.addEventListener('contextmenu', this.onClick, options);\n\n this.cleanup = () => {\n doc.removeEventListener('pointerdown', this.onPointerDown, options);\n doc.removeEventListener('click', this.onClick, options);\n doc.removeEventListener('auxclick', this.onClick, options);\n doc.removeEventListener('contextmenu', this.onClick, options);\n };\n }\n\n private unlisten(): void {\n this.cleanup?.();\n this.cleanup = null;\n this.pressOrigin = null;\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { OverlayContainer } from '@angular/cdk/overlay';\nimport { Service } from '@angular/core';\n\n/**\n * Custom CDK `OverlayContainer` subclass that tags its DOM element with\n * `.wr-overlay-container` in addition to CDK's own `.cdk-overlay-container`.\n *\n * Why: CDK uses a single overlay container per app — every CDK consumer\n * (this lib, Angular Material, NG-ZORRO, etc.) puts its overlays in the\n * same root element. With this class applied you can scope NGWR-specific\n * overlay styles via the tag, e.g.:\n *\n * ```scss\n * .wr-overlay-container .cdk-overlay-pane { z-index: 1100; }\n * ```\n *\n * It does **not** isolate two libraries that both subclass OverlayContainer\n * — the last provider wins. It does give NGWR overlays a stable CSS hook.\n */\n@Service()\nexport class WrOverlayContainer extends OverlayContainer {\n protected override _createContainer(): void {\n super._createContainer();\n this._containerElement?.classList.add('wr-overlay-container');\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Overlay } from '@angular/cdk/overlay';\nimport { InjectionToken, inject } from '@angular/core';\n\n/**\n * Injection token for the CDK `Overlay` service NGWR components should\n * use to open panels.\n *\n * Defaults to CDK's root `Overlay` (shared with every other CDK consumer\n * in the app). Call `provideWrOverlay()` to bind it to an isolated\n * `Overlay` instance backed by a separate `OverlayContainer` — that way\n * NGWR overlays don't share the same DOM root with other libraries.\n *\n * @internal — directives/services inside the lib inject this instead of\n * CDK's `Overlay` directly.\n */\nexport const WR_OVERLAY = new InjectionToken<Overlay>('WR_OVERLAY', {\n providedIn: 'root',\n factory: () => inject(Overlay),\n});\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { OverlayContainer } from '@angular/cdk/overlay';\nimport { InjectionToken, inject } from '@angular/core';\n\n/**\n * Injection token for the overlay container NGWR components should use.\n *\n * Defaults to CDK's `OverlayContainer` — i.e. the same root element every\n * CDK consumer shares. Call `provideWrOverlay()` to replace it with an\n * isolated instance so NGWR overlays don't collide with other libraries.\n *\n * @internal\n */\nexport const WR_OVERLAY_CONTAINER = new InjectionToken<OverlayContainer>('WR_OVERLAY_CONTAINER', {\n providedIn: 'root',\n factory: () => inject(OverlayContainer),\n});\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\n/** Configuration for responsive (bottom-sheet) overlay presentation. */\ninterface WrResponsiveOverlaysConfig {\n /**\n * Viewport width (CSS px) at or below which overlays present as a\n * bottom-sheet instead of a floating panel. @default 640\n */\n readonly breakpoint: number;\n}\n\n/**\n * When set, overlay services (dialog, select, dropdown, …) present as a\n * slide-up bottom-sheet on viewports at or below `breakpoint`. `null`\n * (the default) keeps every overlay floating. Configure via\n * {@link provideWrResponsiveOverlays}; override per call with a\n * component's `responsive` option.\n *\n * @internal\n */\nconst WR_RESPONSIVE_OVERLAYS = new InjectionToken<WrResponsiveOverlaysConfig | null>('WR_RESPONSIVE_OVERLAYS', {\n factory: () => null,\n});\n\n/**\n * Decide whether an overlay should present as a bottom-sheet for the\n * current viewport.\n *\n * - `responsive === true` — sheet on small viewports regardless of config.\n * - `responsive === false` — never a sheet.\n * - `responsive === undefined` — follow the global config (sheet when\n * {@link provideWrResponsiveOverlays} is configured).\n *\n * SSR-safe: returns `false` when there's no `window`.\n *\n * @internal\n */\nfunction wrPresentAsSheet(responsive: boolean | undefined, config: WrResponsiveOverlaysConfig | null): boolean {\n const enabled = responsive ?? config !== null;\n if (!enabled || typeof window === 'undefined') return false;\n return window.innerWidth <= (config?.breakpoint ?? 640);\n}\n\nexport { WR_RESPONSIVE_OVERLAYS, wrPresentAsSheet };\nexport type { WrResponsiveOverlaysConfig };\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Overlay, OverlayContainer } from '@angular/cdk/overlay';\nimport {\n EnvironmentInjector,\n Injector,\n type EnvironmentProviders,\n inject,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n} from '@angular/core';\n\nimport { WrVisualViewport } from 'ngwr/platform';\n\nimport { WR_OVERLAY, WR_OVERLAY_CONTAINER } from './tokens';\nimport { WrOverlayContainer } from './wr-overlay-container';\n\n/**\n * Isolates NGWR overlays from other CDK consumers in the app.\n *\n * Without this call, NGWR overlays use CDK's root `Overlay` — they\n * render into the same `.cdk-overlay-container` element as Angular\n * Material, NG-ZORRO, etc. With it, NGWR gets its own `OverlayContainer`\n * (marked `.wr-overlay-container`) **and** its own `Overlay` service\n * instance — so styles, z-index, and lifecycle never collide.\n *\n * It does this by replacing two injection tokens:\n * - `WR_OVERLAY_CONTAINER` → custom `WrOverlayContainer` subclass\n * - `WR_OVERLAY` → a fresh `Overlay` instance built in a child injector\n * that resolves `OverlayContainer` to the custom subclass\n *\n * CDK's own root `Overlay` / `OverlayContainer` are left untouched, so\n * other libraries keep working with their original container.\n *\n * @example\n * ```ts\n * import { provideWrOverlay } from 'ngwr/overlay';\n *\n * bootstrapApplication(AppComponent, {\n * providers: [\n * provideWrOverlay(),\n * ],\n * });\n * ```\n */\nexport function provideWrOverlay(): EnvironmentProviders {\n return makeEnvironmentProviders([\n // Track the visual viewport app-wide so overlay sheets (and the\n // command-palette) can lift above the on-screen keyboard. No-op on the\n // server / in browsers without the API.\n provideEnvironmentInitializer(() => void inject(WrVisualViewport)),\n { provide: WR_OVERLAY_CONTAINER, useClass: WrOverlayContainer },\n {\n provide: WR_OVERLAY,\n useFactory: (): Overlay => {\n const parent = inject(EnvironmentInjector);\n const container = inject(WR_OVERLAY_CONTAINER);\n\n // Child injector resolves `OverlayContainer` to our subclass and\n // creates a fresh `Overlay` instance bound to it. CDK's own root\n // `Overlay` and `OverlayContainer` are untouched in the parent.\n const child = Injector.create({\n parent,\n providers: [\n { provide: OverlayContainer, useValue: container },\n { provide: Overlay, useClass: Overlay },\n ],\n });\n\n return child.get(Overlay);\n },\n },\n ]);\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\n\nimport { WR_RESPONSIVE_OVERLAYS, type WrResponsiveOverlaysConfig } from './tokens/wr-responsive-overlays.token';\n\n/**\n * Opt every NGWR overlay into responsive presentation — on viewports at or\n * below `breakpoint`, dialogs / selects / dropdowns and friends slide up as\n * a full-width bottom-sheet instead of a floating panel. Built on the same\n * overlay plumbing, so focus-trap, backdrop and scroll-blocking carry over.\n *\n * Individual components can still opt out (or in) per instance via their\n * `responsive` option.\n *\n * @example\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [provideWrOverlay(), provideWrResponsiveOverlays()],\n * });\n *\n * // Custom breakpoint:\n * provideWrResponsiveOverlays({ breakpoint: 768 });\n * ```\n */\nexport function provideWrResponsiveOverlays(config?: Partial<WrResponsiveOverlaysConfig>): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: WR_RESPONSIVE_OVERLAYS, useValue: { breakpoint: config?.breakpoint ?? 640 } },\n ]);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngwr-overlay.mjs","sources":["../../../projects/lib/overlay/wr-overlay-close.ts","../../../projects/lib/overlay/wr-follow-direction.ts","../../../projects/lib/overlay/wr-mirror-offsets.ts","../../../projects/lib/overlay/wr-outside-click.ts","../../../projects/lib/overlay/wr-overlay-container.ts","../../../projects/lib/overlay/tokens/wr-overlay.token.ts","../../../projects/lib/overlay/tokens/wr-overlay-container.token.ts","../../../projects/lib/overlay/tokens/wr-responsive-overlays.token.ts","../../../projects/lib/overlay/provide-wr-overlay.ts","../../../projects/lib/overlay/provide-wr-responsive-overlays.ts","../../../projects/lib/overlay/ngwr-overlay.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\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/** The same 24×24 stroked ✕ the rest of the library's chrome draws (alert, toast, lightbox). */\nconst CLOSE_ICON_ATTRS: readonly (readonly [string, string])[] = [\n ['class', 'wr-icon__svg'],\n ['viewBox', '0 0 24 24'],\n ['fill', 'none'],\n ['stroke', 'currentColor'],\n ['stroke-width', '2'],\n ['stroke-linecap', 'round'],\n ['stroke-linejoin', 'round'],\n ['aria-hidden', 'true'],\n];\nconst CLOSE_ICON_PATHS: readonly string[] = ['M18 6 6 18', 'm6 6 12 12'];\n\n/**\n * Builds the ✕ node by node.\n *\n * It was one `innerHTML = CLOSE_ICON`, and the string was a compile-time\n * constant, so it was never an injection risk — it was an AVAILABILITY one.\n * Under `require-trusted-types-for 'script'` an `innerHTML` write throws\n * `TrustedHTML assignment` whatever the string is, and the throw landed after\n * the overlay was on screen: a modal with no ✕, no backdrop subscription and no\n * Escape handler, over the whole application. `createElementNS` is not a\n * Trusted Types sink, so there is nothing left to police.\n */\nfunction createCloseIcon(doc: Document): SVGSVGElement {\n const svg = doc.createElementNS(SVG_NS, 'svg');\n // `setAttribute`, not `.className` — on an SVG element that property is an\n // `SVGAnimatedString` and assigning a string to it silently does nothing.\n for (const [name, value] of CLOSE_ICON_ATTRS) svg.setAttribute(name, value);\n for (const d of CLOSE_ICON_PATHS) {\n const path = doc.createElementNS(SVG_NS, 'path');\n path.setAttribute('d', d);\n svg.appendChild(path);\n }\n return svg;\n}\n\n/**\n * Appends a dismiss (✕) button to a service-opened overlay panel.\n *\n * `WrDialog` and `WrDrawerManager` build their panel around a component the\n * consumer supplies, so there is no template of their own to put a corner button\n * in — they call this instead. Component-driven overlays (`<wr-drawer>`) render\n * the same markup in their template.\n *\n * Uses `host.ownerDocument` rather than the global `document`, so it carries no\n * hidden browser-only assumption; callers still gate on the platform because\n * they have nothing to append to on the server.\n *\n * @param host Panel element the button is appended to (and positioned against).\n * @param className BEM class for the button, e.g. `wr-dialog__close`.\n * @param label Accessible name — already localized by the caller.\n * @param onClose Invoked on click.\n */\nexport function wrAppendOverlayClose(\n host: HTMLElement,\n className: string,\n label: string,\n onClose: () => void\n): HTMLButtonElement {\n const button = host.ownerDocument.createElement('button');\n button.type = 'button';\n button.className = className;\n button.setAttribute('aria-label', label);\n button.appendChild(createCloseIcon(host.ownerDocument));\n button.addEventListener('click', onClose);\n host.appendChild(button);\n return button;\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { Direction, Directionality } from '@angular/cdk/bidi';\nimport type { OverlayRef } from '@angular/cdk/overlay';\nimport { type Injector, effect, untracked } from '@angular/core';\n\nimport { Subscription } from 'rxjs';\n\nimport { noop } from 'ngwr/utils';\n\n/**\n * Keep an OPEN overlay on the application's reading direction.\n *\n * The CDK reads the direction ONCE, as a string, when the overlay is created\n * (`overlayConfig.direction ||= directionality.value`), writes it as the host's\n * `dir` on attach, and never looks at it again — `updatePosition()` does not\n * touch it and `setDirection()` is the only thing that does. So an application\n * that flips direction while a panel is open mirrors the page and leaves the\n * panel behind, still `ltr`, still resolving `start` to the left. This site's\n * own LTR/RTL switch is the demonstration: it lives inside a `wr-dropdown`, and\n * the `wr-segmented` it is built from reads `Directionality` live — so the thumb\n * slides to the other slot while the pane around it still renders `ltr`, and\n * parks under the wrong label.\n *\n * Call it once per `OverlayRef`, right after `overlay.create(...)`. The follower\n * ends itself when that overlay detaches or is disposed, so a reopen — which is\n * always a NEW ref in this library — needs a new call, and the returned teardown\n * is only for stopping early.\n *\n * `onDirectionChange` is for the sites whose position LIST is itself\n * direction-dependent (the four that pass their table through\n * {@link wrMirrorOffsets}): it runs with the new direction already on the ref\n * and before the overlay repositions, so the strategy is carrying the mirrored\n * offsets by the time the CDK re-resolves them.\n *\n * SSR-safe: it touches no browser global of its own, and the CDK's position\n * strategies no-op off the browser, so a flip on the server only rewrites the\n * attribute.\n *\n * @param overlayRef The overlay to keep in step, freshly created.\n * @param dir The `Directionality` the caller injected. `null` — an optional\n * inject with no provider, i.e. a bare `TestBed` — means there is nothing\n * ambient to follow and this does nothing at all.\n * @param injector Owns the `valueSignal` watch; the caller's own is right.\n * @param onDirectionChange Re-applies direction-dependent state, e.g.\n * `strategy.withPositions(wrMirrorOffsets(TABLE, direction === 'rtl'))`.\n * @returns Stops following. Idempotent, and unnecessary in the normal case.\n *\n * @example\n * ```ts\n * this.overlayRef = this.overlay.create({ positionStrategy, ... });\n * wrFollowDirection(this.overlayRef, this.dir, this.injector, direction =>\n * positionStrategy.withPositions(\n * wrMirrorOffsets(WR_POPCONFIRM_POSITIONS[this.position()], direction === 'rtl')\n * )\n * );\n * ```\n */\nexport function wrFollowDirection(\n overlayRef: OverlayRef,\n dir: Directionality | null,\n injector: Injector,\n onDirectionChange?: (direction: Direction) => void\n): () => void {\n if (!dir) return noop;\n\n const apply = (next: Direction): void => {\n // Comparing against the REF rather than a direction captured up here does\n // three jobs at once: the watch's mandatory first run is a no-op, a flip\n // that arrives down both channels is applied once, and a same-value write\n // never yanks a panel the user is reading.\n if (next === overlayRef.getDirection()) return;\n\n overlayRef.setDirection(next); // rewrites the host's `dir`; it does NOT reposition\n onDirectionChange?.(next); // the caller re-mirrors its position list here\n overlayRef.updatePosition(); // re-resolves start/end against the direction just set\n };\n\n // Two channels, because they are not the same thing. `valueSignal` is the\n // state — `Directionality.value` is a getter over it, so nothing can change\n // direction without writing it. `change` is an EventEmitter the root instance\n // never emits: it reads the document once at construction and only completes\n // the emitter on destroy, so it belongs to the `[dir]` directive (and to an\n // app, like this site's header, that emits it by hand as a courtesy). Keying\n // on `change` alone would be dead for an app that just writes the signal;\n // keying on the signal alone would ignore the `{ value, change }` test double\n // that a dozen of the library's RTL specs hand their component.\n //\n // `untracked` because of WHERE this is called from: half the call sites open\n // their overlay out of an `effect(() => { if (this.isOpen()) … })`, and\n // `effect()` refuses in dev mode to be created inside a reactive context.\n // Laundering only the CREATION is exactly right — the watch below still\n // depends on `valueSignal` and on nothing else.\n const watch = untracked(() =>\n effect(\n () => {\n // Read as a plain optional function rather than as a `Signal`, because\n // the case being guarded is a double that has no signal at all: falling\n // back to `value` registers no dependency, so the watch simply never\n // re-runs and `change` carries that case on its own.\n const read: (() => Direction) | undefined = dir.valueSignal;\n apply(read ? read() : dir.value);\n },\n { injector }\n )\n );\n\n // rxjs owns the teardown, and an `OverlayRef` is why. Open and close happen in\n // an event handler or an effect, never in an injection context, so the idiom\n // that suggests itself — `takeUntilDestroyed(destroyRef)` — would tie this to\n // the DIRECTIVE's lifetime: a menu opened fifty times would leave fifty\n // followers behind, each pinning a disposed ref. (`WrOutsideClick`'s JSDoc\n // records that same mistake, made at ten call sites.) `detachments()` is the\n // overlay's own lifetime and the one channel every dismissal goes through.\n // And it is not hygiene: `setDirection()` writes through the host element\n // `dispose()` nulls, so a watch that outlives its overlay THROWS on the next\n // flip.\n const teardown = new Subscription();\n const stop = (): void => teardown.unsubscribe();\n\n teardown.add(() => watch.destroy());\n teardown.add(dir.change.subscribe(apply));\n // Both handlers, for the reason `WrOutsideClick` gives: a live ref arrives\n // through `next`, one already disposed before this call has only `complete`\n // left to give.\n teardown.add(overlayRef.detachments().subscribe({ next: stop, complete: stop }));\n\n // `Subscription.unsubscribe()` is a no-op once closed, so the caller's copy of\n // this and the automatic one cannot fight, and calling it twice is free.\n return stop;\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { ConnectedPosition } from '@angular/cdk/overlay';\n\n/**\n * Mirror the horizontal offsets of a connected-position list for RTL.\n *\n * The CDK mirrors `originX` / `overlayX` under `dir=\"rtl\"` — a `start` anchor\n * resolves to the origin's right edge — but it does NOT mirror `offsetX`, which\n * it adds to the final PHYSICAL x (`_getOffset` returns `position.offsetX`\n * verbatim). So a position that meant \"sit to the inline-start of the trigger,\n * 8px clear of it\" keeps its `-8` under RTL, where the panel is now on the\n * right: the gap becomes an 8px OVERLAP, and the panel sits on top of the thing\n * it is describing.\n *\n * Nothing in the CDK will do this for us, and the amount is per position, so\n * every ngwr overlay that offsets along the inline axis passes its list through\n * here. `offsetY` is untouched: the block axis does not flip.\n *\n * @example\n * ```ts\n * const dir = inject(Directionality, { optional: true });\n *\n * strategy.withPositions(wrMirrorOffsets(WR_POPOVER_POSITIONS[position], dir?.value === 'rtl'));\n * ```\n */\nexport function wrMirrorOffsets(positions: readonly ConnectedPosition[], isRtl: boolean): ConnectedPosition[] {\n // Copied rather than mutated even when there is nothing to do: the position\n // tables are module-level constants shared by every instance, so handing back\n // the same objects invites a caller to write through them.\n if (!isRtl) return positions.map(position => ({ ...position }));\n\n return positions.map(position => ({\n ...position,\n ...(position.offsetX == null ? {} : { offsetX: -position.offsetX }),\n }));\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { OverlayRef } from '@angular/cdk/overlay';\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport { PLATFORM_ID, Service, inject } from '@angular/core';\n\nimport { Observable, type Subscriber } from 'rxjs';\n\n/** One live subscription to `WrOutsideClick.outsidePointerEvents()`. */\ninterface Watcher {\n readonly overlayRef: OverlayRef;\n readonly subscriber: Subscriber<MouseEvent>;\n}\n\n/**\n * Shadow-piercing `event.target` — `composedPath()[0]` is the real originator\n * when the click started inside a shadow root, where `target` is retargeted to\n * the host.\n */\nfunction eventTarget(event: Event): EventTarget | null {\n if (event.composedPath) {\n try {\n return event.composedPath()[0] ?? event.target;\n } catch {\n /* Detached / synthetic events can throw — fall through to `target`. */\n }\n }\n return event.target;\n}\n\n/** `parent.contains(child)`, but stepping out of shadow roots through their hosts. */\nfunction containsAcrossShadow(parent: Node, child: EventTarget | null): boolean {\n const hasShadowRoot = typeof ShadowRoot !== 'undefined';\n let current = child as Node | null;\n while (current) {\n if (current === parent) return true;\n current = hasShadowRoot && current instanceof ShadowRoot ? current.host : current.parentNode;\n }\n return false;\n}\n\n/**\n * Outside-click source for overlays — a drop-in replacement for\n * `OverlayRef.outsidePointerEvents()`.\n *\n * **Why this exists.** CDK's `OverlayOutsideClickDispatcher` binds its\n * listeners to `document.body`. When page content is shorter than the viewport,\n * a click in the empty space below it targets `<html>` — and `<html>` is\n * `body`'s *parent*, so the event bubbles straight to the document and `body`\n * never sees it. The overlay silently stays open. Listening on the document\n * itself catches both cases, and costs nothing else.\n *\n * Semantics are otherwise identical to the CDK's, deliberately:\n *\n * - Emits on `click` / `auxclick` / `contextmenu`, in the capture phase, and\n * tracks `pointerdown` so a `click` is judged by where the press *started*\n * (a drag that ends outside the pane doesn't count as an outside click).\n * - Walks watchers top-most first and stops at the first one that contains the\n * event, so clicking inside a stacked overlay can't close the ones beneath\n * it (a `wr-select` opened inside a `wr-popover`, say).\n * - Fires for the very click that opened the overlay, which is why every caller\n * also ignores events landing on its own trigger.\n *\n * Registration is per subscription: the document listeners go up with the first\n * watcher and come down with the last, so an app with no open overlay has none.\n * That sentence was aspirational until v11 — see {@link outsidePointerEvents}.\n */\n@Service()\nexport class WrOutsideClick {\n private readonly doc = inject(DOCUMENT);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n /** In attach order — last is top-most. */\n private readonly watchers: Watcher[] = [];\n private cleanup: (() => void) | null = null;\n private pressOrigin: EventTarget | null = null;\n\n /**\n * Emits every `click` / `auxclick` / `contextmenu` that lands outside the\n * given overlay's pane, for as long as the overlay is attached.\n *\n * **It completes when the overlay detaches, and that is load-bearing.** Every\n * one of the ten call sites subscribes inside its own `openOverlay()` and\n * pipes `takeUntilDestroyed(destroyRef)` — a DIRECTIVE lifetime, not an\n * overlay one — and none of them unsubscribes on close, because the natural\n * reading of that idiom is \"this ends with the component\". Without the\n * completion below the teardown never ran: one watcher accumulated per OPEN\n * for the life of the page, each pinning a disposed `OverlayRef` (and through\n * it a detached pane, its portal outlet and their injectors), the four\n * capture-phase document listeners could never come down because\n * `watchers.length` never reached zero, and every click on the page walked a\n * list that only grew. A `mode=\"tooltip\"` popover made it unbounded — one\n * permanent watcher per hover.\n *\n * Completing here rather than fixing ten call sites is deliberate: the next\n * component to open an overlay would have made the same reasonable mistake.\n * It is also what CDK's own `OverlayRef.outsidePointerEvents()` does.\n */\n outsidePointerEvents(overlayRef: OverlayRef): Observable<MouseEvent> {\n return new Observable<MouseEvent>(subscriber => {\n if (!this.isBrowser) return;\n\n const watcher: Watcher = { overlayRef, subscriber };\n this.watchers.push(watcher);\n if (this.watchers.length === 1) this.listen();\n\n // BOTH handlers, and the second one is not defensive padding. `dispose()`\n // emits a detachment and then completes the subject, so a live overlay\n // arrives through `next` — but a ref that was already disposed before\n // anyone subscribed has nothing left to emit and arrives through\n // `complete` alone. Listening for `next` only left exactly the watcher\n // this whole change exists to remove.\n const ended = (): void => subscriber.complete();\n const detached = overlayRef.detachments().subscribe({ next: ended, complete: ended });\n\n return () => {\n detached.unsubscribe();\n const index = this.watchers.indexOf(watcher);\n if (index > -1) this.watchers.splice(index, 1);\n if (!this.watchers.length) this.unlisten();\n };\n });\n }\n\n private readonly onPointerDown = (event: Event): void => {\n this.pressOrigin = eventTarget(event);\n };\n\n private readonly onClick = (event: Event): void => {\n const target = eventTarget(event);\n // `detail > 0` means the click really came from a pointer press. A click\n // activated by Enter or Space carries `detail: 0` and has no `pointerdown`\n // of its own — so trusting a leftover origin there judged it by a press\n // that belonged to something else entirely. A press inside the pane that\n // never produced a click (a drag released off-window, a node removed under\n // the finger, a cancelled touch) survives in `pressOrigin`, and the next\n // keyboard activation anywhere on the page then read as \"inside\": the panel\n // would not close, for keyboard users only.\n const fromPointer = event.type === 'click' && (event as MouseEvent).detail > 0;\n const origin = fromPointer && this.pressOrigin ? this.pressOrigin : target;\n this.pressOrigin = null;\n\n // Snapshot: a watcher that closes on this event unsubscribes synchronously,\n // mutating `watchers` while we're walking it.\n const watchers = this.watchers.slice();\n for (let i = watchers.length - 1; i > -1; i--) {\n const { overlayRef, subscriber } = watchers[i];\n if (!overlayRef.hasAttached()) continue;\n\n const pane = overlayRef.overlayElement;\n if (containsAcrossShadow(pane, target) || containsAcrossShadow(pane, origin)) break;\n\n subscriber.next(event as MouseEvent);\n }\n };\n\n private listen(): void {\n const options: AddEventListenerOptions = { capture: true };\n const doc = this.doc;\n\n doc.addEventListener('pointerdown', this.onPointerDown, options);\n doc.addEventListener('click', this.onClick, options);\n doc.addEventListener('auxclick', this.onClick, options);\n doc.addEventListener('contextmenu', this.onClick, options);\n\n this.cleanup = () => {\n doc.removeEventListener('pointerdown', this.onPointerDown, options);\n doc.removeEventListener('click', this.onClick, options);\n doc.removeEventListener('auxclick', this.onClick, options);\n doc.removeEventListener('contextmenu', this.onClick, options);\n };\n }\n\n private unlisten(): void {\n this.cleanup?.();\n this.cleanup = null;\n this.pressOrigin = null;\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { OverlayContainer } from '@angular/cdk/overlay';\nimport { Service } from '@angular/core';\n\n/**\n * Custom CDK `OverlayContainer` subclass that tags its DOM element with\n * `.wr-overlay-container` in addition to CDK's own `.cdk-overlay-container`.\n *\n * Why: CDK uses a single overlay container per app — every CDK consumer\n * (this lib, Angular Material, NG-ZORRO, etc.) puts its overlays in the\n * same root element. With this class applied you can scope NGWR-specific\n * overlay styles via the tag, e.g.:\n *\n * ```scss\n * .wr-overlay-container .cdk-overlay-pane { z-index: 1100; }\n * ```\n *\n * It does **not** isolate two libraries that both subclass OverlayContainer\n * — the last provider wins. It does give NGWR overlays a stable CSS hook.\n */\n@Service()\nexport class WrOverlayContainer extends OverlayContainer {\n protected override _createContainer(): void {\n super._createContainer();\n this._containerElement?.classList.add('wr-overlay-container');\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Overlay } from '@angular/cdk/overlay';\nimport { InjectionToken, inject } from '@angular/core';\n\n/**\n * Injection token for the CDK `Overlay` service NGWR components should\n * use to open panels.\n *\n * Defaults to CDK's root `Overlay` (shared with every other CDK consumer\n * in the app). Call `provideWrOverlay()` to bind it to an isolated\n * `Overlay` instance backed by a separate `OverlayContainer` — that way\n * NGWR overlays don't share the same DOM root with other libraries.\n *\n * @internal — directives/services inside the lib inject this instead of\n * CDK's `Overlay` directly.\n */\nexport const WR_OVERLAY = new InjectionToken<Overlay>('WR_OVERLAY', {\n providedIn: 'root',\n factory: () => inject(Overlay),\n});\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { OverlayContainer } from '@angular/cdk/overlay';\nimport { InjectionToken, inject } from '@angular/core';\n\n/**\n * Injection token for the overlay container NGWR components should use.\n *\n * Defaults to CDK's `OverlayContainer` — i.e. the same root element every\n * CDK consumer shares. Call `provideWrOverlay()` to replace it with an\n * isolated instance so NGWR overlays don't collide with other libraries.\n *\n * @internal\n */\nexport const WR_OVERLAY_CONTAINER = new InjectionToken<OverlayContainer>('WR_OVERLAY_CONTAINER', {\n providedIn: 'root',\n factory: () => inject(OverlayContainer),\n});\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\n/** Configuration for responsive (bottom-sheet) overlay presentation. */\ninterface WrResponsiveOverlaysConfig {\n /**\n * Viewport width (CSS px) at or below which overlays present as a\n * bottom-sheet instead of a floating panel. @default 640\n */\n readonly breakpoint: number;\n}\n\n/**\n * When set, overlay services (dialog, select, dropdown, …) present as a\n * slide-up bottom-sheet on viewports at or below `breakpoint`. `null`\n * (the default) keeps every overlay floating. Configure via\n * {@link provideWrResponsiveOverlays}; override per call with a\n * component's `responsive` option.\n *\n * @internal\n */\nconst WR_RESPONSIVE_OVERLAYS = new InjectionToken<WrResponsiveOverlaysConfig | null>('WR_RESPONSIVE_OVERLAYS', {\n factory: () => null,\n});\n\n/**\n * Decide whether an overlay should present as a bottom-sheet for the\n * current viewport.\n *\n * - `responsive === true` — sheet on small viewports regardless of config.\n * - `responsive === false` — never a sheet.\n * - `responsive === undefined` — follow the global config (sheet when\n * {@link provideWrResponsiveOverlays} is configured).\n *\n * SSR-safe: returns `false` when there's no `window`.\n *\n * @internal\n */\nfunction wrPresentAsSheet(responsive: boolean | undefined, config: WrResponsiveOverlaysConfig | null): boolean {\n const enabled = responsive ?? config !== null;\n if (!enabled || typeof window === 'undefined') return false;\n return window.innerWidth <= (config?.breakpoint ?? 640);\n}\n\nexport { WR_RESPONSIVE_OVERLAYS, wrPresentAsSheet };\nexport type { WrResponsiveOverlaysConfig };\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Overlay, OverlayContainer } from '@angular/cdk/overlay';\nimport {\n EnvironmentInjector,\n Injector,\n type EnvironmentProviders,\n inject,\n makeEnvironmentProviders,\n provideEnvironmentInitializer,\n} from '@angular/core';\n\nimport { WrVisualViewport } from 'ngwr/platform';\n\nimport { WR_OVERLAY, WR_OVERLAY_CONTAINER } from './tokens';\nimport { WrOverlayContainer } from './wr-overlay-container';\n\n/**\n * Isolates NGWR overlays from other CDK consumers in the app.\n *\n * Without this call, NGWR overlays use CDK's root `Overlay` — they\n * render into the same `.cdk-overlay-container` element as Angular\n * Material, NG-ZORRO, etc. With it, NGWR gets its own `OverlayContainer`\n * (marked `.wr-overlay-container`) **and** its own `Overlay` service\n * instance — so styles, z-index, and lifecycle never collide.\n *\n * It does this by replacing two injection tokens:\n * - `WR_OVERLAY_CONTAINER` → custom `WrOverlayContainer` subclass\n * - `WR_OVERLAY` → a fresh `Overlay` instance built in a child injector\n * that resolves `OverlayContainer` to the custom subclass\n *\n * CDK's own root `Overlay` / `OverlayContainer` are left untouched, so\n * other libraries keep working with their original container.\n *\n * @example\n * ```ts\n * import { provideWrOverlay } from 'ngwr/overlay';\n *\n * bootstrapApplication(AppComponent, {\n * providers: [\n * provideWrOverlay(),\n * ],\n * });\n * ```\n */\nexport function provideWrOverlay(): EnvironmentProviders {\n return makeEnvironmentProviders([\n // Track the visual viewport app-wide so overlay sheets (and the\n // command-palette) can lift above the on-screen keyboard. No-op on the\n // server / in browsers without the API.\n provideEnvironmentInitializer(() => void inject(WrVisualViewport)),\n { provide: WR_OVERLAY_CONTAINER, useClass: WrOverlayContainer },\n {\n provide: WR_OVERLAY,\n useFactory: (): Overlay => {\n const parent = inject(EnvironmentInjector);\n const container = inject(WR_OVERLAY_CONTAINER);\n\n // Child injector resolves `OverlayContainer` to our subclass and\n // creates a fresh `Overlay` instance bound to it. CDK's own root\n // `Overlay` and `OverlayContainer` are untouched in the parent.\n const child = Injector.create({\n parent,\n providers: [\n { provide: OverlayContainer, useValue: container },\n { provide: Overlay, useClass: Overlay },\n ],\n });\n\n return child.get(Overlay);\n },\n },\n ]);\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\n\nimport { WR_RESPONSIVE_OVERLAYS, type WrResponsiveOverlaysConfig } from './tokens/wr-responsive-overlays.token';\n\n/**\n * Opt every NGWR overlay into responsive presentation — on viewports at or\n * below `breakpoint`, dialogs / selects / dropdowns and friends slide up as\n * a full-width bottom-sheet instead of a floating panel. Built on the same\n * overlay plumbing, so focus-trap, backdrop and scroll-blocking carry over.\n *\n * Individual components can still opt out (or in) per instance via their\n * `responsive` option.\n *\n * @example\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [provideWrOverlay(), provideWrResponsiveOverlays()],\n * });\n *\n * // Custom breakpoint:\n * provideWrResponsiveOverlays({ breakpoint: 768 });\n * ```\n */\nexport function provideWrResponsiveOverlays(config?: Partial<WrResponsiveOverlaysConfig>): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: WR_RESPONSIVE_OVERLAYS, useValue: { breakpoint: config?.breakpoint ?? 640 } },\n ]);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -14,6 +14,14 @@ import { input, ViewEncapsulation, Component } from '@angular/core';
14
14
  * side), `[wrPageHeaderExtra]` (bottom row of tags / metadata). Title +
15
15
  * subtitle come from inputs.
16
16
  *
17
+ * A bare `<div>` wrapper in the actions slot, one with no `class` and no
18
+ * `style`, is laid out as a wrapping row with the actions region's own gap, so
19
+ * the buttons inside it are spaced exactly like buttons projected one by one.
20
+ * The gap follows `--wr-density-gap`. Give the wrapper a class or a style and
21
+ * its layout is yours: the header sets nothing on it. The extra row spaces its
22
+ * own children and leaves a wrapper alone, since that is where metadata prose
23
+ * goes, so project tags through an `<ng-container>` as below.
24
+ *
17
25
  * @example
18
26
  * ```html
19
27
  * <wr-page-header title="Settings" subtitle="Manage your workspace">
@@ -22,10 +30,10 @@ import { input, ViewEncapsulation, Component } from '@angular/core';
22
30
  * <button wr-btn>Invite</button>
23
31
  * <button wr-btn color="primary">Save</button>
24
32
  * </div>
25
- * <div wrPageHeaderExtra>
33
+ * <ng-container wrPageHeaderExtra>
26
34
  * <wr-tag>v2.4</wr-tag>
27
35
  * <wr-tag color="success">Stable</wr-tag>
28
- * </div>
36
+ * </ng-container>
29
37
  * </wr-page-header>
30
38
  * ```
31
39
  *
@@ -45,10 +53,10 @@ class WrPageHeader {
45
53
  * @default false
46
54
  */
47
55
  responsive = input(false, { ...(ngDevMode ? { debugName: "responsive" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
48
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrPageHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
49
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrPageHeader, isStandalone: true, selector: "wr-page-header", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.wr-page-header--responsive": "responsive()" }, classAttribute: "wr-page-header" }, ngImport: i0, template: "<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
56
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrPageHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
57
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: WrPageHeader, isStandalone: true, selector: "wr-page-header", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.wr-page-header--responsive": "responsive()" }, classAttribute: "wr-page-header" }, ngImport: i0, template: "<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
50
58
  }
51
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrPageHeader, decorators: [{
59
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrPageHeader, decorators: [{
52
60
  type: Component,
53
61
  args: [{ selector: 'wr-page-header', encapsulation: ViewEncapsulation.None, host: { class: 'wr-page-header', '[class.wr-page-header--responsive]': 'responsive()' }, template: "<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n" }]
54
62
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }] } });
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-page-header.mjs","sources":["../../../projects/lib/page-header/page-header.ts","../../../projects/lib/page-header/page-header.html","../../../projects/lib/page-header/ngwr-page-header.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 { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, input } from '@angular/core';\n\n/**\n * Top-of-page heading block. Three named slots via attribute selectors:\n * `[wrPageHeaderBreadcrumbs]` (top row), `[wrPageHeaderActions]` (right\n * side), `[wrPageHeaderExtra]` (bottom row of tags / metadata). Title +\n * subtitle come from inputs.\n *\n * @example\n * ```html\n * <wr-page-header title=\"Settings\" subtitle=\"Manage your workspace\">\n * <nav wrPageHeaderBreadcrumbs>…</nav>\n * <div wrPageHeaderActions>\n * <button wr-btn>Invite</button>\n * <button wr-btn color=\"primary\">Save</button>\n * </div>\n * <div wrPageHeaderExtra>\n * <wr-tag>v2.4</wr-tag>\n * <wr-tag color=\"success\">Stable</wr-tag>\n * </div>\n * </wr-page-header>\n * ```\n *\n * @see https://ngwr.dev/reference/components/page-header\n */\n@Component({\n selector: 'wr-page-header',\n templateUrl: './page-header.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-page-header', '[class.wr-page-header--responsive]': 'responsive()' },\n})\nexport class WrPageHeader {\n /** Primary title shown as an h1. */\n readonly title = input<string>('');\n\n /** Secondary line below the title. */\n readonly subtitle = input<string>('');\n\n /**\n * Stack the title and actions vertically when the header's own box is too\n * narrow to sit them side by side (a container query on its own width, not\n * the viewport — so it adapts inside a narrow column or split pane).\n * @default false\n */\n readonly responsive = input(false, { transform: coerceBooleanProperty });\n}\n","<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;AAAA;;;;;AAKG;AAKH;;;;;;;;;;;;;;;;;;;;;;AAsBG;MAOU,YAAY,CAAA;;IAEd,KAAK,GAAG,KAAK,CAAS,EAAE;8EAAC;;IAGzB,QAAQ,GAAG,KAAK,CAAS,EAAE;iFAAC;AAErC;;;;;AAKG;IACM,UAAU,GAAG,KAAK,CAAC,KAAK,kFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;uGAb7D,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAZ,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAY,skBCvCzB,0lBAqBA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FDkBa,YAAY,EAAA,UAAA,EAAA,CAAA;kBANxB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,gBAAgB,EAAA,aAAA,EAEX,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B,EAAE,KAAK,EAAE,gBAAgB,EAAE,oCAAoC,EAAE,cAAc,EAAE,EAAA,QAAA,EAAA,0lBAAA,EAAA;;;AErCzF;;AAEG;;;;"}
1
+ {"version":3,"file":"ngwr-page-header.mjs","sources":["../../../projects/lib/page-header/page-header.ts","../../../projects/lib/page-header/page-header.html","../../../projects/lib/page-header/ngwr-page-header.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 { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, input } from '@angular/core';\n\n/**\n * Top-of-page heading block. Three named slots via attribute selectors:\n * `[wrPageHeaderBreadcrumbs]` (top row), `[wrPageHeaderActions]` (right\n * side), `[wrPageHeaderExtra]` (bottom row of tags / metadata). Title +\n * subtitle come from inputs.\n *\n * A bare `<div>` wrapper in the actions slot, one with no `class` and no\n * `style`, is laid out as a wrapping row with the actions region's own gap, so\n * the buttons inside it are spaced exactly like buttons projected one by one.\n * The gap follows `--wr-density-gap`. Give the wrapper a class or a style and\n * its layout is yours: the header sets nothing on it. The extra row spaces its\n * own children and leaves a wrapper alone, since that is where metadata prose\n * goes, so project tags through an `<ng-container>` as below.\n *\n * @example\n * ```html\n * <wr-page-header title=\"Settings\" subtitle=\"Manage your workspace\">\n * <nav wrPageHeaderBreadcrumbs>…</nav>\n * <div wrPageHeaderActions>\n * <button wr-btn>Invite</button>\n * <button wr-btn color=\"primary\">Save</button>\n * </div>\n * <ng-container wrPageHeaderExtra>\n * <wr-tag>v2.4</wr-tag>\n * <wr-tag color=\"success\">Stable</wr-tag>\n * </ng-container>\n * </wr-page-header>\n * ```\n *\n * @see https://ngwr.dev/reference/components/page-header\n */\n@Component({\n selector: 'wr-page-header',\n templateUrl: './page-header.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-page-header', '[class.wr-page-header--responsive]': 'responsive()' },\n})\nexport class WrPageHeader {\n /** Primary title shown as an h1. */\n readonly title = input<string>('');\n\n /** Secondary line below the title. */\n readonly subtitle = input<string>('');\n\n /**\n * Stack the title and actions vertically when the header's own box is too\n * narrow to sit them side by side (a container query on its own width, not\n * the viewport — so it adapts inside a narrow column or split pane).\n * @default false\n */\n readonly responsive = input(false, { transform: coerceBooleanProperty });\n}\n","<div class=\"wr-page-header__breadcrumbs\">\n <ng-content select=\"[wrPageHeaderBreadcrumbs]\" />\n</div>\n\n<div class=\"wr-page-header__main\">\n <div class=\"wr-page-header__heading\">\n @if (title()) {\n <h1 class=\"wr-page-header__title\">{{ title() }}</h1>\n }\n @if (subtitle()) {\n <p class=\"wr-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n <div class=\"wr-page-header__actions\">\n <ng-content select=\"[wrPageHeaderActions]\" />\n </div>\n</div>\n\n<div class=\"wr-page-header__extra\">\n <ng-content select=\"[wrPageHeaderExtra]\" />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;AAAA;;;;;AAKG;AAKH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BG;MAOU,YAAY,CAAA;;IAEd,KAAK,GAAG,KAAK,CAAS,EAAE;8EAAC;;IAGzB,QAAQ,GAAG,KAAK,CAAS,EAAE;iFAAC;AAErC;;;;;AAKG;IACM,UAAU,GAAG,KAAK,CAAC,KAAK,kFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;uGAb7D,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAZ,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAY,skBC/CzB,0lBAqBA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FD0Ba,YAAY,EAAA,UAAA,EAAA,CAAA;kBANxB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,gBAAgB,EAAA,aAAA,EAEX,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B,EAAE,KAAK,EAAE,gBAAgB,EAAE,oCAAoC,EAAE,cAAc,EAAE,EAAA,QAAA,EAAA,0lBAAA,EAAA;;;AE7CzF;;AAEG;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-pagination-testing.mjs","sources":["../../../projects/lib/pagination/testing/wr-pagination-harness.ts","../../../projects/lib/pagination/testing/ngwr-pagination-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 } from '@angular/cdk/testing';\n\nimport { WrButtonHarness } from 'ngwr/button/testing';\nimport type { WrPaginationSize } from 'ngwr/pagination';\nimport { WrSelectHarness } from 'ngwr/select/testing';\n\nimport type { WrPaginationHarnessFilters } from './interfaces';\n\n/**\n * Test harness for `<wr-pagination>` — the numbered strip, its two step controls,\n * the total label and the page-size changer.\n *\n * The strip is not the page list: it is a WINDOW over it, at most seven pages wide,\n * with an `…` standing in for every page it skipped. So \"which pages can I click\"\n * and \"how many pages are there\" are different questions and this harness keeps\n * them apart —\n * {@link getPages} answers the first, {@link getTotalPages} the second, and\n * {@link getStrip} shows the gaps for what they are. A gap is a `<span>`, not a\n * control; counting the strip's children as pages is the mistake this API exists to\n * make impossible.\n *\n * **Which page is current has two answers, and this reads the ARIA one.** The\n * current cell is also PAINTED — the template binds\n * `[color]=\"isCurrent(page) ? 'primary' : null\"`, so `.wr-btn--primary` sits on it\n * too. But colour is a theming decision (`ngwr/config` names this very binding as\n * the reason it ships no app-wide `color` default), while `aria-current=\"page\"` is\n * the navigation contract: it is what a screen-reader user hears, what the\n * component's own spec pins, and the only one of the two that still means\n * \"you are here\" after a restyle. A harness that read the class would be reporting\n * on the paint.\n *\n * **No roving tab stop to disambiguate.** Every cell is a `<wr-btn>` ELEMENT with\n * its own tab stop (`tabindex=\"0\"`, dropped only while the control is off), so the\n * pager has no separate \"focused\" item that could drift from the current page —\n * unlike a tab strip or a radio group, there is one active state here and\n * {@link getCurrentPage} is it.\n *\n * Composed rather than re-queried: the cells and step controls are driven through\n * {@link WrButtonHarness}, which already knows how a `<wr-btn>` says it is off —\n * both the `disabled` attribute (written on every shape, though inert on a custom\n * element) and `aria-disabled`, in that order — and the size changer through\n * {@link WrSelectHarness}, whose panel is a portal in the overlay container and\n * nowhere inside the pager.\n *\n * jsdom notes: every method here is a class / attribute read or a no-arg click, so\n * none of it needs layout. Two things are therefore invisible in a unit test and\n * deliberately absent from this API — the responsive collapse, which is a container\n * query ({@link isResponsive} reports only that it is ALLOWED), and the compact\n * `‹ 3 / 10 ›` pager it swaps in, which is `aria-hidden` decoration duplicating\n * {@link getCurrentPage} and {@link getTotalPages} and which a real browser would\n * read as empty text while CSS keeps it hidden.\n *\n * @example\n * ```ts\n * const pager = await loader.getHarness(WrPaginationHarness);\n *\n * expect(await pager.getPages()).toEqual([1, 2, 3, 4, 5, 10]);\n * await pager.goToPage(3);\n * expect(await pager.getCurrentPage()).toBe(3);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrPaginationHarness extends ComponentHarness {\n static hostSelector = 'wr-pagination';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrPaginationHarnessFilters = {}): HarnessPredicate<WrPaginationHarness> {\n return new HarnessPredicate(WrPaginationHarness, options)\n .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))\n .addOption('page', options.page, async (harness, page) => {\n // The nullable read on purpose: the throwing getter would reject the whole\n // query over one pager that announces no current page, taking its\n // well-behaved neighbours down with it.\n return (await harness.currentPageOrNull()) === page;\n })\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n /** The numbered cells, in DOM order — ascending, and never a gap. */\n private readonly pageCells = this.locatorForAll(WrButtonHarness.with({ selector: '.wr-pagination__page' }));\n\n /**\n * The two controls bracketing the strip: previous, then next.\n *\n * Located by POSITION, not by their labels. `prevLabel` / `nextLabel` are inputs\n * and both fall back to the `pagination.prev` / `pagination.next` catalog entries,\n * so an English `aria-label` match works right up until someone ships a locale —\n * whereas the nav's shape (one step control, the strip, one step control) is\n * structural. `:not(.wr-pagination__page)` is what keeps the cells out of it.\n */\n private readonly stepControls = this.locatorForAll(\n WrButtonHarness.with({ selector: '.wr-pagination__nav > wr-btn:not(.wr-pagination__page)' })\n );\n\n /** Both kinds of strip slot, in DOM order — cells and the gaps between them. */\n private readonly stripSlots = this.locatorForAll('.wr-pagination__page, .wr-pagination__ellipsis');\n\n private readonly totalLabel = this.locatorForOptional('.wr-pagination__total');\n\n private readonly sizeChanger = this.locatorForOptional(WrSelectHarness.with({ selector: '.wr-pagination__size' }));\n\n /**\n * The accessible name of the `role=\"navigation\"` landmark.\n *\n * `''` only if the landmark lost its name, which is a bug rather than a state: a\n * page with two unnamed pagers gives a screen-reader user two identical\n * \"navigation\" landmarks.\n */\n async getLabel(): Promise<string> {\n return (await (await this.host()).getAttribute('aria-label')) ?? '';\n }\n\n /**\n * The size the pager RENDERS at, from its host modifier.\n *\n * The modifier is always emitted — `sm` included — so the fall-through below is\n * only ever reached for the default, and a size the strip is not wearing cannot\n * come back from here.\n *\n * The STRIP resolves nothing through `provideWrConfig()`, which is worth knowing\n * before an app-wide default is blamed for a cell size: the pager passes its own\n * `size` down to every `<wr-btn>` explicitly, so a configured `button.size` never\n * reaches a cell. The page-size changer is the exception and not covered by this\n * value — it is a bare `<wr-select>`, so `provideWrConfig({ select: … })` does\n * reach it.\n */\n async getSize(): Promise<WrPaginationSize> {\n const host = await this.host();\n if (await host.hasClass('wr-pagination--lg')) return 'lg';\n if (await host.hasClass('wr-pagination--md')) return 'md';\n return 'sm';\n }\n\n /**\n * Whether the pager is ALLOWED to collapse into its compact pager.\n *\n * Whether it HAS collapsed is a container query on the control's own box, and a\n * unit test has no layout for one to answer — assert this input in jsdom and the\n * reflow itself in a real browser.\n */\n async isResponsive(): Promise<boolean> {\n return (await this.host()).hasClass('wr-pagination--responsive');\n }\n\n /**\n * Whether the whole control refuses interaction.\n *\n * Read from the host modifier, because a `role=\"navigation\"` landmark has no ARIA\n * disabled state to prefer — the per-control answer lives on the buttons\n * themselves (`disabled` plus `aria-disabled` on each), which is what\n * {@link isPreviousDisabled} and {@link isNextDisabled} read.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.host()).hasClass('wr-pagination--disabled');\n }\n\n /**\n * The whole strip in DOM order: a `number` for every page cell, and the gap\n * marker's own text (`…`) for every ellipsis.\n *\n * The marker is read from the DOM rather than compared against a literal, so a\n * component that changes what it draws in a gap changes this too instead of\n * quietly reporting a page.\n */\n async getStrip(): Promise<(number | string)[]> {\n const slots = await this.stripSlots();\n return Promise.all(\n slots.map(async slot => {\n const text = (await slot.text()).trim();\n return (await slot.hasClass('wr-pagination__ellipsis')) ? text : Number(text);\n })\n );\n }\n\n /**\n * The pages that can be clicked right now, ascending. Gaps are not pages and are\n * not here — `[1, 8, 9, 10, 11, 12, 20]` for a twenty-page list sitting on 10.\n */\n async getPages(): Promise<number[]> {\n const cells = await this.pageCells();\n return Promise.all(cells.map(async cell => Number(await cell.getText())));\n }\n\n /**\n * How many pages there are — not how many are on the strip.\n *\n * Taken from the LAST cell, which the window always pins to the final page (the\n * first is pinned the same way), so this survives the gap that usually precedes\n * it. Deliberately not read from the compact `3 / 10` pager: that span is\n * `aria-hidden` and CSS-hidden outside responsive mode, so a browser-based\n * harness environment would read it as empty.\n */\n async getTotalPages(): Promise<number> {\n const pages = await this.getPages();\n const last = pages.at(-1);\n if (last === undefined) {\n throw new Error(\n 'WrPaginationHarness.getTotalPages(): the strip has no page cells at all. The pager offers page ' +\n '1 even for an empty list, so this is a rendering failure rather than an empty state.'\n );\n }\n return last;\n }\n\n /**\n * The page the pager announces as current, from `aria-current=\"page\"`.\n *\n * Throws when no cell claims it. The window always keeps the current page on the\n * strip, so getting here means `page` is not one of the pages at all. The\n * component clamps a host write into `1..totalPages`, which leaves one survivor:\n * a fractional page, which is in range and matches no cell — and which leaves\n * every cell looking equally inactive to an assistive tech user.\n */\n async getCurrentPage(): Promise<number> {\n const page = await this.currentPageOrNull();\n if (page === null) {\n throw new Error(\n 'WrPaginationHarness.getCurrentPage(): no cell carries `aria-current=\"page\"`. The visible window ' +\n `always includes the current page, so \\`page\\` is not a whole number — the component ` +\n `clamps it into 1..${await this.getTotalPages()} but does not round it.`\n );\n }\n return page;\n }\n\n /**\n * Click the cell for a page.\n *\n * Throws when that page is not on the strip — a seven-slot window over twenty\n * pages simply has no cell for page 15, and a silent no-op there reads as\n * \"navigation is broken\" three assertions later. Step with {@link next} /\n * {@link previous}, or move the host's own `page` model.\n *\n * A disabled pager is still clicked; the component's own guard is what refuses\n * the move, so assert the page rather than assume it. Clicking the CURRENT page\n * is a no-op by the same guard.\n */\n async goToPage(page: number): Promise<void> {\n for (const cell of await this.pageCells()) {\n if (Number(await cell.getText()) === page) {\n await cell.click();\n return;\n }\n }\n\n throw new Error(\n `WrPaginationHarness.goToPage(): page ${page} is not on the strip, which offers ` +\n `${(await this.getStrip()).join(' ')}. The window shows at most seven pages — step with next() / ` +\n 'previous(), or set the page on the host.'\n );\n }\n\n /**\n * Jump to page 1.\n *\n * There is no dedicated first / last control in this component; the window pins\n * the first and last page to the ends of the strip instead, so these two click\n * cells like any other page.\n */\n async goToFirst(): Promise<void> {\n return this.goToPage(1);\n }\n\n /** Jump to the last page — the trailing cell, not the last one before a gap. */\n async goToLast(): Promise<void> {\n return this.goToPage(await this.getTotalPages());\n }\n\n /**\n * Click the next-page control.\n *\n * Disabled on the last page, and a disabled `<wr-btn>` is still clicked here (see\n * {@link goToPage}) — {@link isNextDisabled} is the question, this is the action.\n */\n async next(): Promise<void> {\n return (await this.stepControl('next')).click();\n }\n\n /** Click the previous-page control. Disabled on the first page. */\n async previous(): Promise<void> {\n return (await this.stepControl('previous')).click();\n }\n\n /**\n * Whether the next-page control refuses the move — true on the last page, and\n * true for every control while the pager is disabled.\n *\n * Answered by {@link WrButtonHarness}, which reads the `disabled` attribute first\n * and `aria-disabled` second. A `<wr-btn>` element carries both: the attribute is\n * inert on anything but a real `<button>`, which is why the component adds the\n * ARIA state as well — so this is the accessible answer whichever branch supplies\n * it.\n */\n async isNextDisabled(): Promise<boolean> {\n return (await this.stepControl('next')).isDisabled();\n }\n\n /** Whether the previous-page control refuses the move — true on the first page. */\n async isPreviousDisabled(): Promise<boolean> {\n return (await this.stepControl('previous')).isDisabled();\n }\n\n /** Whether the pager shows its \"X–Y of Z\" label (the `showTotal` input). */\n async hasTotal(): Promise<boolean> {\n return (await this.totalLabel()) !== null;\n }\n\n /**\n * The total label exactly as rendered, e.g. `1–10 of 95`.\n *\n * The WHOLE string is one catalog entry (`pagination.range`) and the three\n * numbers in it are formatted per `LOCALE_ID`, so a spec asserting the literal\n * owns both the copy and the locale it asserts under. Note the range separator\n * is an en dash, not the ASCII hyphen this used to print.\n *\n * Throws when the label is not rendered, which is a `showTotal` that was never\n * set rather than a total of zero (a zero total still renders `0–0 of 0`).\n */\n async getTotalText(): Promise<string> {\n const label = await this.totalLabel();\n if (!label) {\n throw new Error(\n 'WrPaginationHarness.getTotalText(): this pager renders no total label — set `showTotal`. A ' +\n 'total of 0 still renders one.'\n );\n }\n return label.text();\n }\n\n /** Whether the pager renders its page-size changer (the `showSizeChanger` input). */\n async hasPageSizeChanger(): Promise<boolean> {\n return (await this.sizeChanger()) !== null;\n }\n\n /**\n * The page-size changer as a {@link WrSelectHarness} — for anything this harness\n * does not wrap: the offered labels, the open state, keyboard driving.\n *\n * Composed rather than re-queried on purpose: the changer is a real\n * `<wr-select>`, its options live in the overlay container rather than inside the\n * pager, and the select harness is the thing that already knows how to scope them\n * to their own trigger.\n *\n * Throws when there is no changer — an `undefined` here would turn into a\n * confusing failure inside a select call.\n */\n async getPageSizeSelect(): Promise<WrSelectHarness> {\n const select = await this.sizeChanger();\n if (!select) {\n throw new Error('WrPaginationHarness.getPageSizeSelect(): no page-size changer here — set `showSizeChanger`.');\n }\n return select;\n }\n\n /**\n * The page size currently in effect.\n *\n * The changer's trigger is the only place the size reaches the DOM, so this reads\n * it there and takes the digits: the label is localizable (`pagination.perPage`,\n * `{{size}} / page`) but interpolates the number in every language — unless a\n * catalog entry drops the placeholder, which is the second throw below.\n *\n * Throws when there is no changer at all: a pager without one says nothing on\n * screen about its page size, and the host's own model is where to assert it.\n */\n async getPageSize(): Promise<number> {\n const text = await (await this.getPageSizeSelect()).getValueText();\n const digits = /\\d+/.exec(text);\n if (!digits) {\n throw new Error(\n `WrPaginationHarness.getPageSize(): the changer reads \"${text}\", which names no number — a ` +\n 'catalog entry for `pagination.perPage` that drops `{{size}}` takes the size off the screen.'\n );\n }\n return Number(digits[0]);\n }\n\n /**\n * Pick a page size through the changer, the way a user does.\n *\n * Matched on the digits rather than the whole label, for the same reason\n * {@link getPageSize} reads them: `20 / page` and `20 / стр.` are the same option.\n * Throws when no option offers that size, naming what is on offer.\n *\n * Changing the size can move the page — the component pulls `page` back\n * when the new size leaves it past the end — so re-read {@link getCurrentPage}\n * afterwards rather than assuming it held.\n */\n async setPageSize(size: number): Promise<void> {\n const select = await this.getPageSizeSelect();\n if (await this.isDisabled()) {\n // Without this the call fails inside the select harness, whose message blames\n // a tag-mode panel and a `minChars` search that have nothing to do with it.\n throw new Error(\n 'WrPaginationHarness.setPageSize(): the pager is disabled, so its changer refuses to open — the ' +\n 'pager hands its own `disabled` straight to it.'\n );\n }\n\n await select.open();\n\n const labels = await select.getOptionLabels();\n const digits = new RegExp(`(^|\\\\D)${size}(\\\\D|$)`);\n const match = labels.find(label => digits.test(label));\n if (match === undefined) {\n throw new Error(\n `WrPaginationHarness.setPageSize(): no option offers ${size} — the changer offers ` +\n `${labels.join(', ')}. \\`pageSizeOptions\\` is what decides that list.`\n );\n }\n\n await select.selectOption({ text: match });\n }\n\n /** The current page, or `null` when no cell announces one. @see getCurrentPage */\n private async currentPageOrNull(): Promise<number | null> {\n const cell = await this.locatorForOptional(\n WrButtonHarness.with({ selector: '.wr-pagination__page[aria-current=\"page\"]' })\n )();\n return cell ? Number(await cell.getText()) : null;\n }\n\n private async stepControl(which: 'previous' | 'next'): Promise<WrButtonHarness> {\n const controls = await this.stepControls();\n if (controls.length !== 2) {\n throw new Error(\n `WrPaginationHarness: expected the nav to bracket the strip with a previous and a next control, ` +\n `found ${controls.length}. They are addressed by position, since their labels are localizable.`\n );\n }\n return which === 'previous' ? controls[0] : controls[1];\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngwr-pagination-testing.mjs","sources":["../../../projects/lib/pagination/testing/wr-pagination-harness.ts","../../../projects/lib/pagination/testing/ngwr-pagination-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 } from '@angular/cdk/testing';\n\nimport { WrButtonHarness } from 'ngwr/button/testing';\nimport type { WrPaginationSize } from 'ngwr/pagination';\nimport { WrSelectHarness } from 'ngwr/select/testing';\n\nimport type { WrPaginationHarnessFilters } from './interfaces';\n\n/**\n * Test harness for `<wr-pagination>` — the numbered strip, its two step controls,\n * the total label and the page-size changer.\n *\n * The strip is not the page list: it is a WINDOW over it, at most seven pages wide,\n * with an `…` standing in for every page it skipped. So \"which pages can I click\"\n * and \"how many pages are there\" are different questions and this harness keeps\n * them apart —\n * {@link getPages} answers the first, {@link getTotalPages} the second, and\n * {@link getStrip} shows the gaps for what they are. A gap is a `<span>`, not a\n * control; counting the strip's children as pages is the mistake this API exists to\n * make impossible.\n *\n * **Which page is current has two answers, and this reads the ARIA one.** The\n * current cell is also PAINTED — the template binds\n * `[color]=\"isCurrent(page) ? 'primary' : null\"`, so `.wr-btn--primary` sits on it\n * too. But colour is a theming decision (`ngwr/config` names this very binding as\n * the reason it ships no app-wide `color` default), while `aria-current=\"page\"` is\n * the navigation contract: it is what a screen-reader user hears, what the\n * component's own spec pins, and the only one of the two that still means\n * \"you are here\" after a restyle. A harness that read the class would be reporting\n * on the paint.\n *\n * **No roving tab stop to disambiguate.** Every cell is a `<wr-btn>` ELEMENT with\n * its own tab stop (`tabindex=\"0\"`, dropped only while the control is off), so the\n * pager has no separate \"focused\" item that could drift from the current page —\n * unlike a tab strip or a radio group, there is one active state here and\n * {@link getCurrentPage} is it.\n *\n * Composed rather than re-queried: the cells and step controls are driven through\n * {@link WrButtonHarness}, which already knows how a `<wr-btn>` says it is off —\n * both the `disabled` attribute (written on every shape, though inert on a custom\n * element) and `aria-disabled`, in that order — and the size changer through\n * {@link WrSelectHarness}, whose panel is a portal in the overlay container and\n * nowhere inside the pager.\n *\n * jsdom notes: every method here is a class / attribute read or a no-arg click, so\n * none of it needs layout. Two things are therefore invisible in a unit test and\n * deliberately absent from this API — the responsive collapse, which is a container\n * query ({@link isResponsive} reports only that it is ALLOWED), and the compact\n * `‹ 3 / 10 ›` pager it swaps in, which is `aria-hidden` decoration duplicating\n * {@link getCurrentPage} and {@link getTotalPages} and which a real browser would\n * read as empty text while CSS keeps it hidden.\n *\n * @example\n * ```ts\n * const pager = await loader.getHarness(WrPaginationHarness);\n *\n * expect(await pager.getPages()).toEqual([1, 2, 3, 4, 5, 10]);\n * await pager.goToPage(3);\n * expect(await pager.getCurrentPage()).toBe(3);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrPaginationHarness extends ComponentHarness {\n static hostSelector = 'wr-pagination';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrPaginationHarnessFilters = {}): HarnessPredicate<WrPaginationHarness> {\n return new HarnessPredicate(WrPaginationHarness, options)\n .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))\n .addOption('page', options.page, async (harness, page) => {\n // The nullable read on purpose: the throwing getter would reject the whole\n // query over one pager that announces no current page, taking its\n // well-behaved neighbours down with it.\n return (await harness.currentPageOrNull()) === page;\n })\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n /** The numbered cells, in DOM order — ascending, and never a gap. */\n private readonly pageCells = this.locatorForAll(WrButtonHarness.with({ selector: '.wr-pagination__page' }));\n\n /**\n * The two controls bracketing the strip: previous, then next.\n *\n * Located by POSITION, not by their labels. `prevLabel` / `nextLabel` are inputs\n * and both fall back to the `pagination.prev` / `pagination.next` catalog entries,\n * so an English `aria-label` match works right up until someone ships a locale —\n * whereas the nav's shape (one step control, the strip, one step control) is\n * structural. `:not(.wr-pagination__page)` is what keeps the cells out of it.\n */\n private readonly stepControls = this.locatorForAll(\n WrButtonHarness.with({ selector: '.wr-pagination__nav > wr-btn:not(.wr-pagination__page)' })\n );\n\n /** Both kinds of strip slot, in DOM order — cells and the gaps between them. */\n private readonly stripSlots = this.locatorForAll('.wr-pagination__page, .wr-pagination__ellipsis');\n\n private readonly totalLabel = this.locatorForOptional('.wr-pagination__total');\n\n private readonly sizeChanger = this.locatorForOptional(WrSelectHarness.with({ selector: '.wr-pagination__size' }));\n\n /**\n * The accessible name of the `role=\"navigation\"` landmark.\n *\n * `''` only if the landmark lost its name, which is a bug rather than a state: a\n * page with two unnamed pagers gives a screen-reader user two identical\n * \"navigation\" landmarks.\n */\n async getLabel(): Promise<string> {\n return (await (await this.host()).getAttribute('aria-label')) ?? '';\n }\n\n /**\n * The size the pager RENDERS at, from its host modifier.\n *\n * The modifier is always emitted — `sm` included — so the fall-through below is\n * only ever reached for the default, and a size the strip is not wearing cannot\n * come back from here.\n *\n * The STRIP resolves nothing through `provideWrConfig()`, which is worth knowing\n * before an app-wide default is blamed for a cell size: the pager passes its own\n * `size` down to every `<wr-btn>` explicitly, so a configured `button.size` never\n * reaches a cell. The page-size changer is the exception and not covered by this\n * value — it is a bare `<wr-select>`, so `provideWrConfig({ select: … })` does\n * reach it.\n */\n async getSize(): Promise<WrPaginationSize> {\n const host = await this.host();\n if (await host.hasClass('wr-pagination--lg')) return 'lg';\n if (await host.hasClass('wr-pagination--md')) return 'md';\n return 'sm';\n }\n\n /**\n * Whether the pager is ALLOWED to collapse into its compact pager.\n *\n * Whether it HAS collapsed is a container query on the control's own box, and a\n * unit test has no layout for one to answer — assert this input in jsdom and the\n * reflow itself in a real browser.\n */\n async isResponsive(): Promise<boolean> {\n return (await this.host()).hasClass('wr-pagination--responsive');\n }\n\n /**\n * Whether the whole control refuses interaction.\n *\n * Read from the host modifier, because a `role=\"navigation\"` landmark has no ARIA\n * disabled state to prefer — the per-control answer lives on the buttons\n * themselves (`disabled` plus `aria-disabled` on each), which is what\n * {@link isPreviousDisabled} and {@link isNextDisabled} read.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.host()).hasClass('wr-pagination--disabled');\n }\n\n /**\n * The whole strip in DOM order: a `number` for every page cell, and the gap\n * marker's own text (`…`) for every ellipsis.\n *\n * The marker is read from the DOM rather than compared against a literal, so a\n * component that changes what it draws in a gap changes this too instead of\n * quietly reporting a page.\n */\n async getStrip(): Promise<(number | string)[]> {\n const slots = await this.stripSlots();\n return Promise.all(\n slots.map(async slot => {\n const text = (await slot.text()).trim();\n return (await slot.hasClass('wr-pagination__ellipsis')) ? text : Number(text);\n })\n );\n }\n\n /**\n * The pages that can be clicked right now, ascending. Gaps are not pages and are\n * not here — `[1, 8, 9, 10, 11, 12, 20]` for a twenty-page list sitting on 10.\n */\n async getPages(): Promise<number[]> {\n const cells = await this.pageCells();\n return Promise.all(cells.map(async cell => Number(await cell.getText())));\n }\n\n /**\n * How many pages there are — not how many are on the strip.\n *\n * Taken from the LAST cell, which the window always pins to the final page (the\n * first is pinned the same way), so this survives the gap that usually precedes\n * it. Deliberately not read from the compact `3 / 10` pager: that span is\n * `aria-hidden` and CSS-hidden outside responsive mode, so a browser-based\n * harness environment would read it as empty.\n */\n async getTotalPages(): Promise<number> {\n const pages = await this.getPages();\n const last = pages.at(-1);\n if (last === undefined) {\n throw new Error(\n 'WrPaginationHarness.getTotalPages(): the strip has no page cells at all. The pager offers page ' +\n '1 even for an empty list, so this is a rendering failure rather than an empty state.'\n );\n }\n return last;\n }\n\n /**\n * The page the pager announces as current, from `aria-current=\"page\"`.\n *\n * Throws when no cell claims it. The window always keeps the current page on the\n * strip, so getting here means `page` is not one of the pages at all. The\n * component clamps a host write into `1..totalPages`, which leaves one survivor:\n * a fractional page, which is in range and matches no cell — and which leaves\n * every cell looking equally inactive to an assistive tech user.\n */\n async getCurrentPage(): Promise<number> {\n const page = await this.currentPageOrNull();\n if (page === null) {\n throw new Error(\n 'WrPaginationHarness.getCurrentPage(): no cell carries `aria-current=\"page\"`. The visible window ' +\n `always includes the current page, so \\`page\\` is not a whole number — the component ` +\n `clamps it into 1..${await this.getTotalPages()} but does not round it.`\n );\n }\n return page;\n }\n\n /**\n * Click the cell for a page.\n *\n * Throws when that page is not on the strip — a seven-slot window over twenty\n * pages simply has no cell for page 15, and a silent no-op there reads as\n * \"navigation is broken\" three assertions later. Step with {@link next} /\n * {@link previous}, or move the host's own `page` model.\n *\n * A disabled pager is still clicked; the component's own guard is what refuses\n * the move, so assert the page rather than assume it. Clicking the CURRENT page\n * is a no-op by the same guard.\n */\n async goToPage(page: number): Promise<void> {\n for (const cell of await this.pageCells()) {\n if (Number(await cell.getText()) === page) {\n await cell.click();\n return;\n }\n }\n\n throw new Error(\n `WrPaginationHarness.goToPage(): page ${page} is not on the strip, which offers ` +\n `${(await this.getStrip()).join(' ')}. The window shows at most seven pages — step with next() / ` +\n 'previous(), or set the page on the host.'\n );\n }\n\n /**\n * Jump to page 1.\n *\n * There is no dedicated first / last control in this component; the window pins\n * the first and last page to the ends of the strip instead, so these two click\n * cells like any other page.\n */\n async goToFirst(): Promise<void> {\n return this.goToPage(1);\n }\n\n /** Jump to the last page — the trailing cell, not the last one before a gap. */\n async goToLast(): Promise<void> {\n return this.goToPage(await this.getTotalPages());\n }\n\n /**\n * Click the next-page control.\n *\n * Disabled on the last page, and a disabled `<wr-btn>` is still clicked here (see\n * {@link goToPage}) — {@link isNextDisabled} is the question, this is the action.\n */\n async next(): Promise<void> {\n return (await this.stepControl('next')).click();\n }\n\n /** Click the previous-page control. Disabled on the first page. */\n async previous(): Promise<void> {\n return (await this.stepControl('previous')).click();\n }\n\n /**\n * Whether the next-page control refuses the move — true on the last page, and\n * true for every control while the pager is disabled.\n *\n * Answered by {@link WrButtonHarness}, which reads the `disabled` attribute first\n * and `aria-disabled` second. A `<wr-btn>` element carries both: the attribute is\n * inert on anything but a real `<button>`, which is why the component adds the\n * ARIA state as well — so this is the accessible answer whichever branch supplies\n * it.\n */\n async isNextDisabled(): Promise<boolean> {\n return (await this.stepControl('next')).isDisabled();\n }\n\n /** Whether the previous-page control refuses the move — true on the first page. */\n async isPreviousDisabled(): Promise<boolean> {\n return (await this.stepControl('previous')).isDisabled();\n }\n\n /** Whether the pager shows its \"X–Y of Z\" label (the `showTotal` input). */\n async hasTotal(): Promise<boolean> {\n return (await this.totalLabel()) !== null;\n }\n\n /**\n * The total label exactly as rendered, e.g. `1–10 of 95`.\n *\n * The WHOLE string is one catalog entry (`pagination.range`) and the three\n * numbers in it are formatted per `LOCALE_ID`, so a spec asserting the literal\n * owns both the copy and the locale it asserts under. Note the range separator\n * is an en dash, not the ASCII hyphen this used to print.\n *\n * Throws when the label is not rendered, which is a `showTotal` that was never\n * set rather than a total of zero (a zero total still renders `0–0 of 0`).\n */\n async getTotalText(): Promise<string> {\n const label = await this.totalLabel();\n if (!label) {\n throw new Error(\n 'WrPaginationHarness.getTotalText(): this pager renders no total label — set `showTotal`. A ' +\n 'total of 0 still renders one.'\n );\n }\n return label.text();\n }\n\n /** Whether the pager renders its page-size changer (the `showSizeChanger` input). */\n async hasPageSizeChanger(): Promise<boolean> {\n return (await this.sizeChanger()) !== null;\n }\n\n /**\n * The page-size changer as a {@link WrSelectHarness} — for anything this harness\n * does not wrap: the offered labels, the open state, keyboard driving.\n *\n * Composed rather than re-queried on purpose: the changer is a real\n * `<wr-select>`, its options live in the overlay container rather than inside the\n * pager, and the select harness is the thing that already knows how to scope them\n * to their own trigger.\n *\n * Throws when there is no changer — an `undefined` here would turn into a\n * confusing failure inside a select call.\n */\n async getPageSizeSelect(): Promise<WrSelectHarness> {\n const select = await this.sizeChanger();\n if (!select) {\n throw new Error('WrPaginationHarness.getPageSizeSelect(): no page-size changer here — set `showSizeChanger`.');\n }\n return select;\n }\n\n /**\n * The page size currently in effect.\n *\n * The changer's trigger is the only place the size reaches the DOM, so this reads\n * it there and takes the digits: the label is localizable (`pagination.perPage`,\n * `{{size}} / page`) but interpolates the number in every language — unless a\n * catalog entry drops the placeholder, which is the second throw below.\n *\n * Throws when there is no changer at all: a pager without one says nothing on\n * screen about its page size, and the host's own model is where to assert it.\n */\n async getPageSize(): Promise<number> {\n const text = await (await this.getPageSizeSelect()).getValueText();\n const digits = /\\d+/.exec(text);\n if (!digits) {\n throw new Error(\n `WrPaginationHarness.getPageSize(): the changer reads \"${text}\", which names no number — a ` +\n 'catalog entry for `pagination.perPage` that drops `{{size}}` takes the size off the screen.'\n );\n }\n return Number(digits[0]);\n }\n\n /**\n * Pick a page size through the changer, the way a user does.\n *\n * Matched on the digits rather than the whole label, for the same reason\n * {@link getPageSize} reads them: `20 / page` and `20 / стр.` are the same option.\n * Throws when no option offers that size, naming what is on offer.\n *\n * Changing the size can move the page — the component pulls `page` back\n * when the new size leaves it past the end — so re-read {@link getCurrentPage}\n * afterwards rather than assuming it held.\n */\n async setPageSize(size: number): Promise<void> {\n const select = await this.getPageSizeSelect();\n if (await this.isDisabled()) {\n // Without this the call fails inside the select harness, whose message blames\n // a tag-mode panel and a `minChars` search that have nothing to do with it.\n throw new Error(\n 'WrPaginationHarness.setPageSize(): the pager is disabled, so its changer refuses to open — the ' +\n 'pager hands its own `disabled` straight to it.'\n );\n }\n\n await select.open();\n\n const labels = await select.getOptionLabels();\n const digits = new RegExp(`(^|\\\\D)${size}(\\\\D|$)`);\n const match = labels.find(label => digits.test(label));\n if (match === undefined) {\n throw new Error(\n `WrPaginationHarness.setPageSize(): no option offers ${size} — the changer offers ` +\n `${labels.join(', ')}. \\`pageSizeOptions\\` is what decides that list.`\n );\n }\n\n await select.selectOption({ text: match });\n }\n\n /** The current page, or `null` when no cell announces one. @see getCurrentPage */\n private async currentPageOrNull(): Promise<number | null> {\n const cell = await this.locatorForOptional(\n WrButtonHarness.with({ selector: '.wr-pagination__page[aria-current=\"page\"]' })\n )();\n return cell ? Number(await cell.getText()) : null;\n }\n\n private async stepControl(which: 'previous' | 'next'): Promise<WrButtonHarness> {\n const controls = await this.stepControls();\n if (controls.length !== 2) {\n throw new Error(\n `WrPaginationHarness: expected the nav to bracket the strip with a previous and a next control, ` +\n `found ${controls.length}. They are addressed by position, since their labels are localizable.`\n );\n }\n return which === 'previous' ? controls[0] : controls[1];\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -321,10 +321,10 @@ class WrPagination {
321
321
  // something the guard covers.
322
322
  this.pageSize.set(next);
323
323
  }
324
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrPagination, deps: [], target: i0.ɵɵFactoryTarget.Component });
325
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrPagination, isStandalone: true, selector: "wr-pagination", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, showSizeChanger: { classPropertyName: "showSizeChanger", publicName: "showSizeChanger", isSignal: true, isRequired: false, transformFunction: null }, showTotal: { classPropertyName: "showTotal", publicName: "showTotal", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, prevLabel: { classPropertyName: "prevLabel", publicName: "prevLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, itemsPerPageLabel: { classPropertyName: "itemsPerPageLabel", publicName: "itemsPerPageLabel", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { page: "pageChange", pageSize: "pageSizeChange" }, host: { attributes: { "role": "navigation" }, properties: { "class": "classes()", "attr.aria-label": "navLabel()" } }, ngImport: i0, template: "<div class=\"wr-pagination__inner\">\n @if (showTotal()) {\n <span class=\"wr-pagination__total\">{{ rangeLabel() }}</span>\n }\n\n <div class=\"wr-pagination__nav\">\n <!--\n `wr-pagination__nav-btn` exists so the stylesheet can mirror the arrow\n glyph under `dir=\"rtl\"`. A class rather than `:first-child` /\n `:last-child` on the row: those two positions do hold today \u2014 which is why\n the `--square` end caps use them \u2014 but only while the prev button, the\n compact label and the next button all stay unconditional and in this\n order. A mirror keyed to position would follow a reorder, or land on a\n page cell, without a word.\n\n The two `[disabled]` bindings compare against the RANGE (`<= 1`,\n `>= totalPages()`) rather than for equality with its ends. While `total`\n is 0 the guard effect stops enforcing the upper bound, so the page can\n legitimately sit past `totalPages()` \u2014 and `=== totalPages()` reported\n next as enabled there while `goTo` refused the step. Prev is still\n enabled in that state, correctly: `prevPage()` walks it back into range.\n -->\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || page() <= 1\"\n (click)=\"goTo(prevPage())\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n </wr-btn>\n\n @for (page of pages(); track $index) {\n @if (page === ellipsis) {\n <span class=\"wr-pagination__ellipsis\">{{ ellipsis }}</span>\n } @else {\n <wr-btn\n class=\"wr-pagination__page\"\n [size]=\"size()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"goToPage({ page })\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <!-- Compact pager \u2014 shown only in responsive mode on a narrow box (CSS). -->\n <span class=\"wr-pagination__current\" aria-hidden=\"true\">{{ compactLabel() }}</span>\n\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedNext()\"\n [disabled]=\"disabled() || page() >= totalPages()\"\n (click)=\"goTo(page() + 1)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n </wr-btn>\n </div>\n\n @if (showSizeChanger()) {\n <!--\n `ariaLabel`, not `[attr.aria-label]`: `<wr-select>`'s host carries no role,\n so an attribute there names nothing and never reaches the `role=\"combobox\"`\n button inside \u2014 the size changer announced itself as the catalog's generic\n \"Select\".\n -->\n <wr-select\n class=\"wr-pagination__size\"\n [ariaLabel]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [value]=\"pageSize()\"\n (valueChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ perPage({ size: option }) }}</wr-option>\n }\n </wr-select>\n }\n</div>\n", dependencies: [{ kind: "component", type: WrButton, selector: "wr-btn, button[wr-btn], a[wr-btn]", inputs: ["color", "size", "shape", "icon", "iconPosition", "disabled", "outlined", "block", "loading", "disabledWhenLoading"] }, { kind: "component", type: WrSelect, selector: "wr-select", inputs: ["placeholder", "clearLabel", "ariaLabel", "disabled", "readonly", "rounded", "size", "responsive", "mode", "searchable", "searchQuery", "options", "displayWith", "loader", "serverSearch", "debounceMs", "minChars", "freeText", "virtualScroll", "rowHeight", "viewportHeight", "overscan", "noResultsText", "loadingText", "loading", "separators", "allowDuplicates", "validate", "clearable", "maxItems", "maxTagCount", "value"], outputs: ["searchQueryChange", "searchChange", "valueChange", "touch"] }, { kind: "component", type: WrOption, selector: "wr-option", inputs: ["value", "disabled", "label"] }], encapsulation: i0.ViewEncapsulation.None });
324
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrPagination, deps: [], target: i0.ɵɵFactoryTarget.Component });
325
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: WrPagination, isStandalone: true, selector: "wr-pagination", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, showSizeChanger: { classPropertyName: "showSizeChanger", publicName: "showSizeChanger", isSignal: true, isRequired: false, transformFunction: null }, showTotal: { classPropertyName: "showTotal", publicName: "showTotal", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, prevLabel: { classPropertyName: "prevLabel", publicName: "prevLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, itemsPerPageLabel: { classPropertyName: "itemsPerPageLabel", publicName: "itemsPerPageLabel", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { page: "pageChange", pageSize: "pageSizeChange" }, host: { attributes: { "role": "navigation" }, properties: { "class": "classes()", "attr.aria-label": "navLabel()" } }, ngImport: i0, template: "<div class=\"wr-pagination__inner\">\n @if (showTotal()) {\n <span class=\"wr-pagination__total\">{{ rangeLabel() }}</span>\n }\n\n <div class=\"wr-pagination__nav\">\n <!--\n `wr-pagination__nav-btn` exists so the stylesheet can mirror the arrow\n glyph under `dir=\"rtl\"`. A class rather than `:first-child` /\n `:last-child` on the row: those two positions do hold today \u2014 which is why\n the `--square` end caps use them \u2014 but only while the prev button, the\n compact label and the next button all stay unconditional and in this\n order. A mirror keyed to position would follow a reorder, or land on a\n page cell, without a word.\n\n The two `[disabled]` bindings compare against the RANGE (`<= 1`,\n `>= totalPages()`) rather than for equality with its ends. While `total`\n is 0 the guard effect stops enforcing the upper bound, so the page can\n legitimately sit past `totalPages()` \u2014 and `=== totalPages()` reported\n next as enabled there while `goTo` refused the step. Prev is still\n enabled in that state, correctly: `prevPage()` walks it back into range.\n -->\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || page() <= 1\"\n (click)=\"goTo(prevPage())\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n </wr-btn>\n\n @for (page of pages(); track $index) {\n @if (page === ellipsis) {\n <span class=\"wr-pagination__ellipsis\">{{ ellipsis }}</span>\n } @else {\n <wr-btn\n class=\"wr-pagination__page\"\n [size]=\"size()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"goToPage({ page })\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <!-- Compact pager \u2014 shown only in responsive mode on a narrow box (CSS). -->\n <span class=\"wr-pagination__current\" aria-hidden=\"true\">{{ compactLabel() }}</span>\n\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedNext()\"\n [disabled]=\"disabled() || page() >= totalPages()\"\n (click)=\"goTo(page() + 1)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n </wr-btn>\n </div>\n\n @if (showSizeChanger()) {\n <!--\n `ariaLabel`, not `[attr.aria-label]`: `<wr-select>`'s host carries no role,\n so an attribute there names nothing and never reaches the `role=\"combobox\"`\n button inside \u2014 the size changer announced itself as the catalog's generic\n \"Select\".\n -->\n <wr-select\n class=\"wr-pagination__size\"\n [ariaLabel]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [value]=\"pageSize()\"\n (valueChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ perPage({ size: option }) }}</wr-option>\n }\n </wr-select>\n }\n</div>\n", dependencies: [{ kind: "component", type: WrButton, selector: "wr-btn, button[wr-btn], a[wr-btn]", inputs: ["color", "size", "shape", "icon", "iconPosition", "disabled", "outlined", "block", "loading", "disabledWhenLoading"] }, { kind: "component", type: WrSelect, selector: "wr-select", inputs: ["placeholder", "clearLabel", "ariaLabel", "disabled", "readonly", "rounded", "size", "responsive", "mode", "searchable", "searchQuery", "options", "displayWith", "loader", "serverSearch", "debounceMs", "minChars", "freeText", "virtualScroll", "rowHeight", "viewportHeight", "overscan", "noResultsText", "loadingText", "loading", "separators", "allowDuplicates", "validate", "clearable", "maxItems", "maxTagCount", "value"], outputs: ["searchQueryChange", "searchChange", "valueChange", "touch"] }, { kind: "component", type: WrOption, selector: "wr-option", inputs: ["value", "disabled", "label"] }], encapsulation: i0.ViewEncapsulation.None });
326
326
  }
327
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrPagination, decorators: [{
327
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrPagination, decorators: [{
328
328
  type: Component,
329
329
  args: [{ selector: 'wr-pagination', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()', role: 'navigation', '[attr.aria-label]': 'navLabel()' }, imports: [WrButton, WrSelect, WrOption], template: "<div class=\"wr-pagination__inner\">\n @if (showTotal()) {\n <span class=\"wr-pagination__total\">{{ rangeLabel() }}</span>\n }\n\n <div class=\"wr-pagination__nav\">\n <!--\n `wr-pagination__nav-btn` exists so the stylesheet can mirror the arrow\n glyph under `dir=\"rtl\"`. A class rather than `:first-child` /\n `:last-child` on the row: those two positions do hold today \u2014 which is why\n the `--square` end caps use them \u2014 but only while the prev button, the\n compact label and the next button all stay unconditional and in this\n order. A mirror keyed to position would follow a reorder, or land on a\n page cell, without a word.\n\n The two `[disabled]` bindings compare against the RANGE (`<= 1`,\n `>= totalPages()`) rather than for equality with its ends. While `total`\n is 0 the guard effect stops enforcing the upper bound, so the page can\n legitimately sit past `totalPages()` \u2014 and `=== totalPages()` reported\n next as enabled there while `goTo` refused the step. Prev is still\n enabled in that state, correctly: `prevPage()` walks it back into range.\n -->\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedPrev()\"\n [disabled]=\"disabled() || page() <= 1\"\n (click)=\"goTo(prevPage())\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n </wr-btn>\n\n @for (page of pages(); track $index) {\n @if (page === ellipsis) {\n <span class=\"wr-pagination__ellipsis\">{{ ellipsis }}</span>\n } @else {\n <wr-btn\n class=\"wr-pagination__page\"\n [size]=\"size()\"\n [outlined]=\"!isCurrent(page)\"\n [color]=\"isCurrent(page) ? 'primary' : null\"\n [attr.aria-current]=\"isCurrent(page) ? 'page' : null\"\n [attr.aria-label]=\"goToPage({ page })\"\n [disabled]=\"disabled()\"\n (click)=\"goTo(page)\"\n >\n {{ page }}\n </wr-btn>\n }\n }\n\n <!-- Compact pager \u2014 shown only in responsive mode on a narrow box (CSS). -->\n <span class=\"wr-pagination__current\" aria-hidden=\"true\">{{ compactLabel() }}</span>\n\n <wr-btn\n class=\"wr-pagination__nav-btn\"\n [size]=\"size()\"\n outlined\n [attr.aria-label]=\"resolvedNext()\"\n [disabled]=\"disabled() || page() >= totalPages()\"\n (click)=\"goTo(page() + 1)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n </wr-btn>\n </div>\n\n @if (showSizeChanger()) {\n <!--\n `ariaLabel`, not `[attr.aria-label]`: `<wr-select>`'s host carries no role,\n so an attribute there names nothing and never reaches the `role=\"combobox\"`\n button inside \u2014 the size changer announced itself as the catalog's generic\n \"Select\".\n -->\n <wr-select\n class=\"wr-pagination__size\"\n [ariaLabel]=\"resolvedItemsPerPage()\"\n [disabled]=\"disabled()\"\n [value]=\"pageSize()\"\n (valueChange)=\"onSizeChange($event)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <wr-option [value]=\"option\">{{ perPage({ size: option }) }}</wr-option>\n }\n </wr-select>\n }\n</div>\n" }]
330
330
  }], ctorParameters: () => [], propDecorators: { page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }, { type: i0.Output, args: ["pageChange"] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }, { type: i0.Output, args: ["pageSizeChange"] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], showSizeChanger: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSizeChanger", required: false }] }], showTotal: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTotal", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], prevLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "prevLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], itemsPerPageLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemsPerPageLabel", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });