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
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-mention.mjs","sources":["../../../projects/lib/mention/caret.ts","../../../projects/lib/mention/mention-panel.ts","../../../projects/lib/mention/mention-panel.html","../../../projects/lib/mention/mention.ts","../../../projects/lib/mention/ngwr-mention.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\n/**\n * CSS properties whose values must be copied onto the mirror to match layout.\n *\n * `as const satisfies` keeps each name checked against `CSSStyleDeclaration`\n * while narrowing the element type to these string-valued literals — the wider\n * `keyof CSSStyleDeclaration` also spans its methods (`setProperty`, `item`, …),\n * which makes the indexed read below look like an unbound method.\n */\nconst MIRROR_PROPS = [\n 'boxSizing',\n // Without this the mirror inherits `<body>`'s direction, and the two disagree\n // whenever the field carries its own `dir` — measured at 230px of error for a\n // 320px RTL field inside an LTR page, which put the panel outside the field\n // entirely. `textAlign` below is the same story from the other side: an RTL\n // field's computed value is the logical `start`, which only resolves to the\n // right edge once the mirror knows the direction.\n 'direction',\n 'width',\n 'height',\n 'overflowX',\n 'overflowY',\n 'borderTopWidth',\n 'borderRightWidth',\n 'borderBottomWidth',\n 'borderLeftWidth',\n 'paddingTop',\n 'paddingRight',\n 'paddingBottom',\n 'paddingLeft',\n 'fontStyle',\n 'fontVariant',\n 'fontWeight',\n 'fontStretch',\n 'fontSize',\n 'fontSizeAdjust',\n 'lineHeight',\n 'fontFamily',\n 'textAlign',\n 'textTransform',\n 'textIndent',\n 'textDecoration',\n 'letterSpacing',\n 'wordSpacing',\n 'tabSize',\n 'whiteSpace',\n 'wordWrap',\n] as const satisfies readonly (keyof CSSStyleDeclaration)[];\n\n/** A caret has no size, and an environment with no layout has no rects at all. */\nconst NO_RECT = { top: 0, left: 0 } as const;\n\n/**\n * Where the browser would draw the caret this collapsed `range` marks.\n *\n * `getClientRects()` before `getBoundingClientRect()`: a collapsed range at a\n * bidi boundary has TWO candidate positions and reports both, and the bounding\n * box of the pair spans the whole run between them. The first rect is the one\n * the caret is actually painted at.\n *\n * Both are optional-called because jsdom implements NEITHER on `Range` — it lays\n * nothing out, so every element rect in it is already 0×0 and a zero here keeps\n * the function answering what the rest of that environment answers rather than\n * throwing halfway through an unrelated spec.\n */\nfunction caretRectOf(range: Range): { readonly top: number; readonly left: number } {\n const rects = range.getClientRects?.();\n if (rects && rects.length > 0) return rects[0];\n return range.getBoundingClientRect?.() ?? NO_RECT;\n}\n\n/**\n * Compute the viewport coordinates of a textarea / input caret at a given\n * `position`. Uses the \"mirror div\" technique — a hidden div with the same\n * styling holds the field's text, and a COLLAPSED RANGE at `position` reports\n * where the caret would be.\n *\n * Returns viewport-relative `{ top, left }` — pass straight to a CDK\n * Overlay anchored at that point.\n *\n * **A range, not a probe span, and the difference only shows in RTL.** The\n * classic version of this technique puts the text before the caret in the div,\n * the text after it in a `<span>`, and reads the span's LEFT edge. That reads\n * the caret's side of the boundary only while the text runs left to right. Under\n * the Unicode BiDi algorithm the span can be laid out to the LEFT of the run it\n * follows, so the edge that faces the caret is its right one — and which edge\n * that is depends on the bidi level of the text at the caret, not on the field's\n * direction, so there is no side to pick. A collapsed range asks the browser\n * where it would draw the caret and gets the reordering for free. Measured\n * against a `contenteditable` twin of the field, in Chromium: the range agrees\n * to within a pixel for Latin, Arabic and mixed text in both directions, where\n * the span was out by up to 300px in RTL (see the spec next door).\n *\n * The `<input>` branch keeps the field's WIDTH for the same reason. It used to\n * force `width: auto` so a long single line could not wrap; but an RTL field\n * right-aligns its text inside its own box, so a shrink-to-fit mirror throws\n * away the only measurement that decides where the text starts. `overflow:\n * hidden` is what keeps the overflow from painting, and `input.scrollLeft`\n * already accounts for a field scrolled past its box.\n */\nexport function getCaretCoordinates(\n input: HTMLTextAreaElement | HTMLInputElement,\n position: number\n): { top: number; left: number; lineHeight: number } {\n const doc = input.ownerDocument;\n const style = getComputedStyle(input);\n const mirror = doc.createElement('div');\n\n for (const prop of MIRROR_PROPS) {\n mirror.style[prop] = style[prop];\n }\n mirror.style.position = 'absolute';\n mirror.style.visibility = 'hidden';\n mirror.style.top = '0';\n mirror.style.left = '0';\n mirror.style.whiteSpace = 'pre-wrap';\n mirror.style.wordWrap = 'break-word';\n\n // <input> is single-line — force whitespace behaviour so coords are sane.\n if (input.tagName === 'INPUT') {\n mirror.style.whiteSpace = 'pre';\n mirror.style.height = 'auto';\n mirror.style.overflow = 'hidden';\n }\n\n // One text node, so the range can address any offset in it. An empty field\n // still needs a line box to measure, hence the fallback character.\n const text = doc.createTextNode(input.value || '.');\n mirror.appendChild(text);\n\n doc.body.appendChild(mirror);\n const range = doc.createRange();\n range.setStart(text, Math.min(position, text.length));\n range.collapse(true);\n const caretRect = caretRectOf(range);\n const mirrorRect = mirror.getBoundingClientRect();\n const lineHeight = parseFloat(style.lineHeight) || parseFloat(style.fontSize) * 1.2;\n doc.body.removeChild(mirror);\n\n const inputRect = input.getBoundingClientRect();\n return {\n top: inputRect.top + (caretRect.top - mirrorRect.top) - input.scrollTop,\n left: inputRect.left + (caretRect.left - mirrorRect.left) - input.scrollLeft,\n lineHeight,\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 { Component, ViewEncapsulation, input, output } from '@angular/core';\n\nimport type { WrMentionItem } from './interfaces';\n\n/**\n * The id of the option at `index`, given the listbox's own id.\n *\n * Lives here, and is used from both sides, because this format is a contract\n * between two files: the panel stamps it onto each `<li>`, and the directive\n * names one of them in `aria-activedescendant`. Written out twice, the two would\n * drift and the reference would silently dangle — and a dangling\n * `aria-activedescendant` is not an error the browser reports, it just stops\n * announcing options.\n *\n * @internal\n */\nexport function wrMentionOptionId(listboxId: string, index: number): string {\n return `${listboxId}-opt-${index}`;\n}\n\n/**\n * Overlay panel rendered by {@link WrMention}. Not intended for\n * direct use — the directive instantiates it via a ComponentPortal.\n *\n * @internal — the same tag its twin `WrPopconfirmPanel` already carried. It says\n * the intent; it does not by itself keep the class out of the generated API\n * tables, because `WrTableFilter` and `WrTableSort` are tagged AND documented —\n * see `EXPORTED_BUT_INTERNAL` in `scripts/lib/extract-api.ts`.\n */\n@Component({\n selector: 'wr-mention-panel',\n templateUrl: './mention-panel.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-mention-panel' },\n})\nexport class WrMentionPanel {\n readonly items = input<readonly WrMentionItem[]>([]);\n readonly activeIndex = input(0);\n readonly displayWith = input<(item: WrMentionItem) => string>(item => item.label);\n\n /**\n * Id of the `<ul role=\"listbox\">`, minted by the directive and pointed at by\n * its `aria-controls`. Owned there rather than here because the panel is\n * disposed and rebuilt whenever the caret leaves a mention, while the\n * attribute on the host has to stay put.\n *\n * Plain `input('')`, never `input.required` — a ComponentPortal-created\n * component throws on the first change detection if a required input is unset.\n */\n readonly listboxId = input('');\n\n /** Accessible name for the listbox. ARIA requires one; the directive supplies it from the catalog. */\n readonly listLabel = input('');\n\n protected optionId(index: number): string {\n return wrMentionOptionId(this.listboxId(), index);\n }\n\n /** Emitted when the user picks an item (click). */\n readonly picked = output<WrMentionItem>();\n\n /** Emitted on mouseenter — used by the directive to track hover. */\n readonly hovered = output<number>();\n\n protected onPick(item: WrMentionItem, event: MouseEvent): void {\n // mousedown semantics — keep focus on the input.\n event.preventDefault();\n this.picked.emit(item);\n }\n}\n","<!--\n No empty branch: `activate()` calls `close()` and returns before `open()` when\n nothing matches, so the panel is never rendered with zero items. The \"No\n matches\" `<div>` that used to live here was unreachable — and a hard-coded\n English string besides. The zero-match case is announced through the\n directive's live region instead.\n-->\n<ul class=\"wr-mention-panel__list\" role=\"listbox\" [attr.id]=\"listboxId()\" [attr.aria-label]=\"listLabel()\">\n @for (item of items(); track $index) {\n <li\n class=\"wr-mention-panel__option\"\n role=\"option\"\n [attr.id]=\"optionId($index)\"\n [class.wr-mention-panel__option--active]=\"$index === activeIndex()\"\n [attr.aria-selected]=\"$index === activeIndex()\"\n (mouseenter)=\"hovered.emit($index)\"\n (mousedown)=\"onPick(item, $event)\"\n >\n {{ displayWith()(item) }}\n </li>\n }\n</ul>\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directionality } from '@angular/cdk/bidi';\nimport { coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n type ConnectedPosition,\n type FlexibleConnectedPositionStrategyOrigin,\n type OverlayRef,\n ScrollStrategyOptions,\n} from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n type ComponentRef,\n DestroyRef,\n Directive,\n ElementRef,\n Injector,\n PLATFORM_ID,\n computed,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { readI18nText, useI18nFormatter } from 'ngwr/i18n';\nimport { WR_OVERLAY, wrFollowDirection } from 'ngwr/overlay';\nimport { isComposing } from 'ngwr/utils';\n\nimport { getCaretCoordinates } from './caret';\nimport type { WrMentionCommit, WrMentionItem } from './interfaces';\nimport { WrMentionPanel, wrMentionOptionId } from './mention-panel';\n\ninterface ActiveState {\n trigger: string;\n query: string;\n startIndex: number;\n}\n\n/**\n * Deterministic under prerender, unlike `randomId()` — `aria-controls` is a\n * static host binding, so it renders on the server too, and a random value would\n * differ between that render and the hydrated client.\n */\nlet mentionUid = 0;\n\n/** Gap between the caret's line and the panel, on whichever side it opens. */\nconst CARET_GAP = 4;\n\n/**\n * Below the caret's line first, above it when there is no room — the two sides\n * a caret-anchored list can take. There is no horizontal pair: a panel that\n * jumped to the other side of the caret would read as a different widget, so a\n * caret near the inline end is handled by `withPush` sliding the panel back\n * onto the screen instead. `overlayX: 'start'` is the logical corner, so RTL\n * hangs the panel from the caret's other side without a second table.\n */\nconst CARET_POSITIONS: ConnectedPosition[] = [\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' },\n];\n\n/**\n * `@`-style mention picker for `<textarea>` and `<input>`. Listens for\n * trigger characters (default `'@'`); when typed at a word boundary, an\n * overlay panel opens at the caret and shows filtered options. Pick with\n * Enter / Tab / click — the trigger + query is replaced with the inserted\n * value plus a trailing space.\n *\n * @example\n * ```html\n * <textarea\n * wrMention\n * [wrMentionItems]=\"users\"\n * [displayWith]=\"userLabel\"\n * (wrMentionSelected)=\"onMention($event)\"\n * ></textarea>\n * ```\n *\n * @see https://ngwr.dev/reference/components/mention\n */\n@Directive({\n selector: '[wrMention]',\n host: {\n '(input)': 'onInput()',\n '(click)': 'onClick()',\n '(keyup)': 'onCaretMove($event)',\n '(keydown)': 'onKeydown($event)',\n '(blur)': 'onBlur()',\n\n // The IME pair. `isComposing` on a `keydown` answers \"did the input method\n // take this key\", which is a different question from \"is a conversion open\n // right now\" — on the committing keystroke the two disagree by design — and\n // detection runs from `input` and `keyup`, where there is no such flag to\n // read. So the state is tracked here and the detector consults it.\n '(compositionstart)': 'onCompositionStart()',\n '(compositionend)': 'onCompositionEnd()',\n\n // The host keeps its implicit `role=\"textbox\"`. It is NOT a combobox: this\n // field holds prose and the mention is one fragment inside it, not the\n // field's value. `role=\"combobox\"` is also flatly disallowed on `<textarea>`\n // by ARIA in HTML (axe: `aria-allowed-role`), and it would drop\n // `aria-multiline`, which combobox does not support — so a screen reader\n // would stop reporting the field as multi-line for the whole editing\n // session, not just while the popup is open.\n //\n // Static, because `aria-autocomplete` describes a permanent capability of\n // the field; ARIA says authors SHOULD NOT toggle it to signal that\n // suggestions are currently showing. Being static is also what makes the\n // feature discoverable — it is announced on focus, before the user types a\n // trigger char.\n 'aria-autocomplete': 'list',\n // Required alongside `aria-autocomplete=\"list\"`, and must name the popup's\n // role. Measured clean on a textbox with axe-core 4.13.\n 'aria-haspopup': 'listbox',\n // Also static, and deliberately left pointing at an id that only exists\n // while the panel is open: gating it would mean gating `aria-autocomplete`\n // too. An unresolved `aria-controls` is a manual-review note in axe, never a\n // violation — unlike `aria-activedescendant`, which is an author error.\n //\n // This is the attribute that legalises the whole design: for a textbox\n // controlling a popup, `aria-activedescendant` is allowed to name an element\n // owned by the *controlled* element, which is how the reference reaches into\n // the CDK overlay's separate DOM subtree at all.\n '[attr.aria-controls]': 'listboxId',\n '[attr.aria-activedescendant]': 'activeOptionId()',\n\n // No `aria-expanded`. It is not a supported state of `role=\"textbox\"` —\n // axe rates it a *critical* `aria-allowed-attr` violation — so the\n // \"a list appeared\" signal cannot be an ARIA state here. That is what the\n // live region below is for; it is load-bearing, not decoration.\n },\n})\nexport class WrMention<T extends WrMentionItem = WrMentionItem> {\n /** Items to filter against the typed query. */\n readonly wrMentionItems = input<readonly T[]>([]);\n\n /** Trigger characters that open the panel. @default ['@'] */\n readonly triggers = input<readonly string[]>(['@']);\n\n /** Maps an item to its display label. @default `item.label` */\n readonly displayWith = input<(item: T) => string>((item: T) => item.label);\n\n /**\n * Returns the text to insert into the textarea on commit. Receives the\n * picked item and the trigger char. @default `${trigger}${displayWith(item)}`\n */\n readonly valueWith = input<((item: T, trigger: string) => string) | null>(null);\n\n /** Custom filter. @default case-insensitive `includes` over `displayWith(item)`. */\n readonly filterWith = input<((query: string, item: T) => boolean) | null>(null);\n\n /** Maximum number of items shown in the panel. @default 8 */\n readonly maxResults = input(8, { transform: (v: unknown): number => Math.max(1, coerceNumberProperty(v, 8)) });\n\n /** Emits the selected item, trigger, and query whenever the user commits. */\n readonly wrMentionSelected = output<WrMentionCommit<T>>();\n\n private readonly host = inject<ElementRef<HTMLTextAreaElement | HTMLInputElement>>(ElementRef);\n private readonly overlay = inject(WR_OVERLAY);\n /**\n * Optional inject: `Directionality` is root-provided, so this is never null in\n * an app — but a bare `TestBed` that provides nothing should still get a\n * directive that works, and defaulting to LTR is the honest fallback.\n */\n private readonly dir = inject(Directionality, { optional: true });\n private readonly scrollStrategies = inject(ScrollStrategyOptions);\n private readonly destroyRef = inject(DestroyRef);\n private readonly injector = inject(Injector);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n private overlayRef: OverlayRef | null = null;\n private panelRef: ComponentRef<WrMentionPanel> | null = null;\n /**\n * Where the caret sits INSIDE the field — its offset from the field's\n * top-left corner, plus the height of the line it is on. Mutated in place by\n * `open()`, never replaced: `caretAnchor()` closes over this object.\n */\n private readonly caretOffset = { dx: 0, dy: 0, lineHeight: 0 };\n private state: ActiveState | null = null;\n private readonly activeIndex = signal(0);\n private readonly filteredItems = signal<readonly T[]>([]);\n private readonly isOpen = signal(false);\n\n /** @internal — read by the `aria-controls` host binding. */\n protected readonly listboxId = `wr-mention-listbox-${++mentionUid}`;\n\n private readonly listLabel = readI18nText('mention.listbox', 'Mentions');\n private readonly availableText = useI18nFormatter('mention.available', 'Matches available: {{count}}');\n private readonly insertedText = useI18nFormatter('mention.inserted', 'Inserted: {{label}}');\n\n /**\n * `aria-activedescendant`, or `null`.\n *\n * Gated hard on `isOpen()`, which is only set once the panel's options are\n * actually in the DOM. An id that resolves to nothing is an author error, and\n * the failure mode is silent: the browser does not complain, it simply stops\n * firing the event that makes a screen reader speak the option. Same\n * discipline `tree.ts` uses for its virtualized rows.\n */\n protected readonly activeOptionId = computed<string | null>(() => {\n if (!this.isOpen()) return null;\n const index = this.activeIndex();\n return index >= 0 && index < this.filteredItems().length ? wrMentionOptionId(this.listboxId, index) : null;\n });\n\n /**\n * Polite live region, parked on `<body>`.\n *\n * Not inside the panel: `close()` disposes the overlay on every keystroke that\n * leaves a mention, so a region living there would be recreated constantly —\n * and a live region has to be in the DOM *before* its text changes to be\n * announced at all. It also could not announce the two cases that matter most,\n * since in both the panel is already gone: \"nothing matched\" and \"inserted X\".\n *\n * Not a sibling of the host either — that would land inside the consumer's\n * markup and start matching their `+`, `~` and `:nth-child()` selectors.\n */\n private liveRegion: HTMLElement | null = null;\n\n constructor() {\n if (this.isBrowser) {\n const doc = this.host.nativeElement.ownerDocument;\n const region = doc.createElement('div');\n region.className = 'wr-mention__status';\n region.setAttribute('role', 'status');\n doc.body.appendChild(region);\n this.liveRegion = region;\n }\n\n this.destroyRef.onDestroy(() => {\n this.close();\n this.liveRegion?.remove();\n this.liveRegion = null;\n });\n }\n\n private announce(message: string): void {\n if (this.liveRegion) this.liveRegion.textContent = message;\n }\n\n // Host listeners\n\n /**\n * True between `compositionstart` and `compositionend`.\n *\n * Detection must not run on the half-built text an IME leaves in the field:\n * `@やま` is a reading on its way to `@山田`, and matching the reading opens a\n * panel that then eats the Enter meant to accept the conversion. So the field\n * is read once, on `compositionend`, when the text is real.\n */\n private composing = false;\n\n /** @internal */\n protected onCompositionStart(): void {\n this.composing = true;\n // A panel opened before the conversion started would take the arrows and the\n // Enter that now belong to the candidate window.\n this.close();\n }\n\n /** @internal */\n protected onCompositionEnd(): void {\n this.composing = false;\n // The committed text is only in the field now, so this is the first honest\n // read of it.\n this.detect();\n }\n\n /** @internal */\n protected onInput(): void {\n if (this.composing) return;\n this.detect();\n }\n\n /** @internal */\n protected onClick(): void {\n this.detect();\n }\n\n /** @internal */\n protected onCaretMove(event: KeyboardEvent): void {\n if (this.composing || isComposing(event)) return;\n // Every key `onKeydown` already consumed, Escape included: its keyup would\n // re-detect at a caret that is still sitting inside the mention and reopen the\n // panel Escape had just dismissed. A synthetic keydown-only Escape hides that\n // — the real gesture is a pair, and the second half undid the first.\n if (\n event.key === 'ArrowUp' ||\n event.key === 'ArrowDown' ||\n event.key === 'Enter' ||\n event.key === 'Tab' ||\n event.key === 'Escape'\n ) {\n return;\n }\n this.detect();\n }\n\n /** @internal */\n protected onKeydown(event: KeyboardEvent): void {\n // The key is the input method's while a conversion is open — Enter accepts a\n // candidate, Escape cancels the reading, the arrows walk the candidate list.\n // `this.composing` is deliberately not consulted: on Safari's committing\n // keystroke it has already gone false, and `isComposing` covers that case\n // through the 229 sentinel.\n if (isComposing(event)) return;\n if (!this.state) return;\n const list = this.filteredItems();\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n if (list.length > 0) this.setActive((this.activeIndex() + 1) % list.length);\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (list.length > 0) this.setActive((this.activeIndex() - 1 + list.length) % list.length);\n break;\n case 'Enter':\n case 'Tab': {\n const item = list[this.activeIndex()];\n if (item) {\n event.preventDefault();\n this.commit(item);\n }\n break;\n }\n case 'Escape':\n event.preventDefault();\n // The panel is the innermost thing Escape can dismiss, so it keeps the\n // key: without this, the same press also closed the dialog / drawer /\n // window the field sits in.\n //\n // `preventDefault()` alone buys nothing — every host overlay matches on\n // `event.key` and none of them looks at `defaultPrevented` — and letting\n // CDK's `OverlayKeyboardDispatcher` sort it out does not work either.\n // The dispatcher walks the stack newest-first and stops at the first\n // overlay with a `keydownEvents()` subscriber; this panel has none (it\n // is driven from the field's own handler, which runs at the target\n // before the body-phase dispatcher), so Escape falls straight through to\n // the overlay underneath.\n event.stopPropagation();\n this.close();\n break;\n default:\n break;\n }\n }\n\n /** @internal */\n protected onBlur(): void {\n // Defer so option mousedown lands first.\n setTimeout(() => this.close(), 120);\n }\n\n // Detection\n\n private detect(): void {\n const el = this.host.nativeElement;\n const caret = el.selectionStart ?? 0;\n const text = el.value.substring(0, caret);\n const triggers = this.triggers();\n\n // Walk back from the caret looking for a trigger char with whitespace\n // (or start-of-string) immediately before it. Stop on whitespace.\n let i = caret;\n while (i > 0) {\n const ch = text[i - 1];\n if (triggers.includes(ch)) {\n const before = i - 2 >= 0 ? text[i - 2] : '';\n if (i - 2 < 0 || /\\s/.test(before)) {\n const query = text.substring(i);\n this.activate(ch, query, i - 1);\n return;\n }\n break;\n }\n if (/\\s/.test(ch)) break;\n i--;\n }\n this.close();\n }\n\n private activate(trigger: string, query: string, startIndex: number): void {\n this.state = { trigger, query, startIndex };\n const previousCount = this.filteredItems().length;\n const filtered = this.filter(query).slice(0, this.maxResults());\n this.filteredItems.set(filtered);\n if (filtered.length === 0) {\n // Announce *after* closing: `close()` clears the region, so announcing\n // first would wipe the message before a screen reader reached it.\n this.close();\n this.announce(this.availableText({ count: 0 }));\n return;\n }\n this.setActive(Math.min(this.activeIndex(), filtered.length - 1));\n this.open();\n // Only when the size actually changes. Re-announcing the same count on every\n // keystroke would talk over the per-option speech from activedescendant.\n if (filtered.length !== previousCount) this.announce(this.availableText({ count: filtered.length }));\n }\n\n private filter(query: string): readonly T[] {\n const items = this.wrMentionItems();\n const custom = this.filterWith();\n const display = this.displayWith();\n if (!query) return items;\n if (custom) return items.filter(item => custom(query, item));\n const q = query.toLowerCase();\n return items.filter(item => display(item).toLowerCase().includes(q));\n }\n\n private setActive(i: number): void {\n this.activeIndex.set(i);\n this.panelRef?.setInput('activeIndex', i);\n }\n\n // Overlay\n\n /**\n * The overlay's anchor: the caret's line box, grown by the gap the panel\n * keeps from the text, as a zero-WIDTH virtual origin in viewport\n * coordinates. Inflating the rect rather than passing `offsetY` is what keeps\n * `withPush` honest — CDK applies a position offset as a `transform` AFTER it\n * has clamped, so a pushed panel would land the offset off the screen edge.\n *\n * Live getters, not a snapshot, and that is the whole of the scroll fix.\n * `getCaretCoordinates` answers in viewport coordinates, which a\n * `GlobalPositionStrategy` froze at the instant of the keystroke: the panel\n * then stayed pinned to the screen while the page scrolled out from under it\n * (150px of scroll, 150px of drift, ending up over unrelated content). CDK\n * re-reads a virtual origin on every `apply()`, so pinning it to the FIELD's\n * live rect is what turns `reposition()` into a real re-anchor.\n *\n * Only the caret's offset inside the field is captured up front. Measuring it\n * runs the mirror-div pass in `caret.ts` — a full layout read, far too\n * expensive to repeat per scroll event — and it cannot change without a\n * keystroke, which re-enters `open()` anyway.\n */\n private caretAnchor(): FlexibleConnectedPositionStrategyOrigin {\n const field = this.host.nativeElement;\n const offset = this.caretOffset;\n return {\n width: 0,\n get x(): number {\n return field.getBoundingClientRect().left + offset.dx;\n },\n get y(): number {\n return field.getBoundingClientRect().top + offset.dy - CARET_GAP;\n },\n get height(): number {\n return offset.lineHeight + CARET_GAP * 2;\n },\n };\n }\n\n private open(): void {\n const el = this.host.nativeElement;\n const caret = el.selectionStart ?? 0;\n const { top, left, lineHeight } = getCaretCoordinates(el, caret);\n const field = el.getBoundingClientRect();\n this.caretOffset.dx = left - field.left;\n this.caretOffset.dy = top - field.top;\n this.caretOffset.lineHeight = lineHeight;\n\n if (!this.overlayRef) {\n this.overlayRef = this.overlay.create({\n // Flexible, not global: a global strategy has no anchor and no fallback\n // positions, so the panel was always drawn downward from the caret no\n // matter how little room was left below it — half the list ended up\n // under the fold, unreachable by pointer AND invisible to a sighted\n // keyboard user walking it with `aria-activedescendant` (WCAG 2.4.11).\n positionStrategy: this.overlay\n .position()\n .flexibleConnectedTo(this.caretAnchor())\n // The panel sizes itself (`max-height` on the list); the flip above\n // and `withPush` are the whole answer to a cramped viewport.\n .withFlexibleDimensions(false)\n .withPush(true)\n .withPositions(CARET_POSITIONS),\n scrollStrategy: this.scrollStrategies.reposition(),\n panelClass: 'wr-mention-overlay',\n });\n\n // Once per mention SESSION, which is the same thing as once per ref here:\n // the block this sits in is the only place one is created, and `close()`\n // is the only place one is disposed. No callback — `CARET_POSITIONS`\n // carries no `offsetX` to mirror, by the design noted at the table, so\n // `setDirection` plus the reposition the helper already does is the whole\n // of it: the panel hangs off the caret's other side and the list inside\n // reads the way the page now does.\n wrFollowDirection(this.overlayRef, this.dir, this.injector);\n\n const portal = new ComponentPortal(WrMentionPanel);\n const ref = this.overlayRef.attach(portal);\n this.panelRef = ref;\n ref.setInput('displayWith', this.displayWith());\n ref.setInput('listboxId', this.listboxId);\n // Read once here rather than bound: the panel is created per open, and by\n // then the catalog has long landed.\n ref.setInput('listLabel', this.listLabel());\n ref.instance.picked.subscribe(item => this.commit(item as T));\n ref.instance.hovered.subscribe(i => this.setActive(i));\n }\n // No `else` re-building the strategy: the anchor reads `caretOffset` and the\n // field's live rect, both of which the lines above have already refreshed.\n\n this.panelRef?.setInput('items', this.filteredItems());\n this.panelRef?.setInput('activeIndex', this.activeIndex());\n\n // Render the panel's own view NOW, before `aria-activedescendant` is allowed\n // to name one of its options. `attach()` inserts the host element but leaves\n // it empty — the panel is a separate root view, so on the first open the\n // `<li>` being referenced does not exist anywhere in the document yet.\n // Waiting for the next tick would leave a window where the reference dangles\n // and the announcement is lost with no error anywhere.\n this.panelRef?.changeDetectorRef.detectChanges();\n // Place it only now, with the options rendered: which side of the caret the\n // panel takes is decided by measuring it, and `attach()` defers CDK's own\n // first placement into `afterNextRender` — a frame in which the panel would\n // be painted, full size and fully opaque, at the overlay container's\n // top-left corner.\n this.overlayRef.updatePosition();\n this.isOpen.set(true);\n }\n\n private close(): void {\n if (this.overlayRef) {\n this.overlayRef.dispose();\n this.overlayRef = null;\n this.panelRef = null;\n }\n this.isOpen.set(false);\n this.state = null;\n this.activeIndex.set(0);\n this.filteredItems.set([]);\n this.announce('');\n }\n\n private commit(item: T): void {\n // Snapshot the state up front. `dispatchEvent` below re-enters this directive\n // synchronously: the listener runs `detect()`, and because assigning\n // `el.value` has already parked the caret at the end of the text — past the\n // space this method appends — `detect()` finds no trigger and calls\n // `close()`, which nulls `this.state`. Reading `this.state` after that line\n // threw, so `wrMentionSelected` never fired for anyone.\n const state = this.state;\n if (!state) return;\n\n const el = this.host.nativeElement;\n const value = el.value;\n const caret = el.selectionStart ?? value.length;\n const valueFn = this.valueWith();\n const label = this.displayWith()(item);\n const inserted = valueFn ? valueFn(item, state.trigger) : `${state.trigger}${label}`;\n const replacement = `${inserted} `;\n const before = value.substring(0, state.startIndex);\n const after = value.substring(caret);\n const next = before + replacement + after;\n\n el.value = next;\n el.dispatchEvent(new Event('input', { bubbles: true }));\n const nextCaret = (before + replacement).length;\n el.setSelectionRange(nextCaret, nextCaret);\n this.wrMentionSelected.emit({ item, trigger: state.trigger, query: state.query });\n\n // Announce after `close()`, never before — it clears the live region.\n // Committing is otherwise silent: the panel simply vanishes.\n this.close();\n this.announce(this.insertedText({ label }));\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-mention.mjs","sources":["../../../projects/lib/mention/caret.ts","../../../projects/lib/mention/mention-panel.ts","../../../projects/lib/mention/mention-panel.html","../../../projects/lib/mention/mention.ts","../../../projects/lib/mention/ngwr-mention.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\n/**\n * CSS properties whose values must be copied onto the mirror to match layout.\n *\n * `as const satisfies` keeps each name checked against `CSSStyleDeclaration`\n * while narrowing the element type to these string-valued literals — the wider\n * `keyof CSSStyleDeclaration` also spans its methods (`setProperty`, `item`, …),\n * which makes the indexed read below look like an unbound method.\n */\nconst MIRROR_PROPS = [\n 'boxSizing',\n // Without this the mirror inherits `<body>`'s direction, and the two disagree\n // whenever the field carries its own `dir` — measured at 230px of error for a\n // 320px RTL field inside an LTR page, which put the panel outside the field\n // entirely. `textAlign` below is the same story from the other side: an RTL\n // field's computed value is the logical `start`, which only resolves to the\n // right edge once the mirror knows the direction.\n 'direction',\n 'width',\n 'height',\n 'overflowX',\n 'overflowY',\n 'borderTopWidth',\n 'borderRightWidth',\n 'borderBottomWidth',\n 'borderLeftWidth',\n 'paddingTop',\n 'paddingRight',\n 'paddingBottom',\n 'paddingLeft',\n 'fontStyle',\n 'fontVariant',\n 'fontWeight',\n 'fontStretch',\n 'fontSize',\n 'fontSizeAdjust',\n 'lineHeight',\n 'fontFamily',\n 'textAlign',\n 'textTransform',\n 'textIndent',\n 'textDecoration',\n 'letterSpacing',\n 'wordSpacing',\n 'tabSize',\n 'whiteSpace',\n 'wordWrap',\n] as const satisfies readonly (keyof CSSStyleDeclaration)[];\n\n/** A caret has no size, and an environment with no layout has no rects at all. */\nconst NO_RECT = { top: 0, left: 0 } as const;\n\n/**\n * Where the browser would draw the caret this collapsed `range` marks.\n *\n * `getClientRects()` before `getBoundingClientRect()`: a collapsed range at a\n * bidi boundary has TWO candidate positions and reports both, and the bounding\n * box of the pair spans the whole run between them. The first rect is the one\n * the caret is actually painted at.\n *\n * Both are optional-called because jsdom implements NEITHER on `Range` — it lays\n * nothing out, so every element rect in it is already 0×0 and a zero here keeps\n * the function answering what the rest of that environment answers rather than\n * throwing halfway through an unrelated spec.\n */\nfunction caretRectOf(range: Range): { readonly top: number; readonly left: number } {\n const rects = range.getClientRects?.();\n if (rects && rects.length > 0) return rects[0];\n return range.getBoundingClientRect?.() ?? NO_RECT;\n}\n\n/**\n * Compute the viewport coordinates of a textarea / input caret at a given\n * `position`. Uses the \"mirror div\" technique — a hidden div with the same\n * styling holds the field's text, and a COLLAPSED RANGE at `position` reports\n * where the caret would be.\n *\n * Returns viewport-relative `{ top, left }` — pass straight to a CDK\n * Overlay anchored at that point.\n *\n * **A range, not a probe span, and the difference only shows in RTL.** The\n * classic version of this technique puts the text before the caret in the div,\n * the text after it in a `<span>`, and reads the span's LEFT edge. That reads\n * the caret's side of the boundary only while the text runs left to right. Under\n * the Unicode BiDi algorithm the span can be laid out to the LEFT of the run it\n * follows, so the edge that faces the caret is its right one — and which edge\n * that is depends on the bidi level of the text at the caret, not on the field's\n * direction, so there is no side to pick. A collapsed range asks the browser\n * where it would draw the caret and gets the reordering for free. Measured\n * against a `contenteditable` twin of the field, in Chromium: the range agrees\n * to within a pixel for Latin, Arabic and mixed text in both directions, where\n * the span was out by up to 300px in RTL (see the spec next door).\n *\n * The `<input>` branch keeps the field's WIDTH for the same reason. It used to\n * force `width: auto` so a long single line could not wrap; but an RTL field\n * right-aligns its text inside its own box, so a shrink-to-fit mirror throws\n * away the only measurement that decides where the text starts. `overflow:\n * hidden` is what keeps the overflow from painting, and `input.scrollLeft`\n * already accounts for a field scrolled past its box.\n */\nexport function getCaretCoordinates(\n input: HTMLTextAreaElement | HTMLInputElement,\n position: number\n): { top: number; left: number; lineHeight: number } {\n const doc = input.ownerDocument;\n const style = getComputedStyle(input);\n const mirror = doc.createElement('div');\n\n for (const prop of MIRROR_PROPS) {\n mirror.style[prop] = style[prop];\n }\n mirror.style.position = 'absolute';\n mirror.style.visibility = 'hidden';\n mirror.style.top = '0';\n mirror.style.left = '0';\n mirror.style.whiteSpace = 'pre-wrap';\n mirror.style.wordWrap = 'break-word';\n\n // <input> is single-line — force whitespace behaviour so coords are sane.\n if (input.tagName === 'INPUT') {\n mirror.style.whiteSpace = 'pre';\n mirror.style.height = 'auto';\n mirror.style.overflow = 'hidden';\n }\n\n // One text node, so the range can address any offset in it. An empty field\n // still needs a line box to measure, hence the fallback character.\n const text = doc.createTextNode(input.value || '.');\n mirror.appendChild(text);\n\n doc.body.appendChild(mirror);\n const range = doc.createRange();\n range.setStart(text, Math.min(position, text.length));\n range.collapse(true);\n const caretRect = caretRectOf(range);\n const mirrorRect = mirror.getBoundingClientRect();\n const lineHeight = parseFloat(style.lineHeight) || parseFloat(style.fontSize) * 1.2;\n doc.body.removeChild(mirror);\n\n const inputRect = input.getBoundingClientRect();\n return {\n top: inputRect.top + (caretRect.top - mirrorRect.top) - input.scrollTop,\n left: inputRect.left + (caretRect.left - mirrorRect.left) - input.scrollLeft,\n lineHeight,\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 { Component, ViewEncapsulation, input, output } from '@angular/core';\n\nimport type { WrMentionItem } from './interfaces';\n\n/**\n * The id of the option at `index`, given the listbox's own id.\n *\n * Lives here, and is used from both sides, because this format is a contract\n * between two files: the panel stamps it onto each `<li>`, and the directive\n * names one of them in `aria-activedescendant`. Written out twice, the two would\n * drift and the reference would silently dangle — and a dangling\n * `aria-activedescendant` is not an error the browser reports, it just stops\n * announcing options.\n *\n * @internal\n */\nexport function wrMentionOptionId(listboxId: string, index: number): string {\n return `${listboxId}-opt-${index}`;\n}\n\n/**\n * Overlay panel rendered by {@link WrMention}. Not intended for\n * direct use — the directive instantiates it via a ComponentPortal.\n *\n * @internal — the same tag its twin `WrPopconfirmPanel` already carried. It says\n * the intent; it does not by itself keep the class out of the generated API\n * tables, because `WrTableFilter` and `WrTableSort` are tagged AND documented —\n * see `EXPORTED_BUT_INTERNAL` in `scripts/lib/extract-api.ts`.\n */\n@Component({\n selector: 'wr-mention-panel',\n templateUrl: './mention-panel.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-mention-panel' },\n})\nexport class WrMentionPanel {\n readonly items = input<readonly WrMentionItem[]>([]);\n readonly activeIndex = input(0);\n readonly displayWith = input<(item: WrMentionItem) => string>(item => item.label);\n\n /**\n * Id of the `<ul role=\"listbox\">`, minted by the directive and pointed at by\n * its `aria-controls`. Owned there rather than here because the panel is\n * disposed and rebuilt whenever the caret leaves a mention, while the\n * attribute on the host has to stay put.\n *\n * Plain `input('')`, never `input.required` — a ComponentPortal-created\n * component throws on the first change detection if a required input is unset.\n */\n readonly listboxId = input('');\n\n /** Accessible name for the listbox. ARIA requires one; the directive supplies it from the catalog. */\n readonly listLabel = input('');\n\n protected optionId(index: number): string {\n return wrMentionOptionId(this.listboxId(), index);\n }\n\n /** Emitted when the user picks an item (click). */\n readonly picked = output<WrMentionItem>();\n\n /** Emitted on mouseenter — used by the directive to track hover. */\n readonly hovered = output<number>();\n\n protected onPick(item: WrMentionItem, event: MouseEvent): void {\n // mousedown semantics — keep focus on the input.\n event.preventDefault();\n this.picked.emit(item);\n }\n}\n","<!--\n No empty branch: `activate()` calls `close()` and returns before `open()` when\n nothing matches, so the panel is never rendered with zero items. The \"No\n matches\" `<div>` that used to live here was unreachable — and a hard-coded\n English string besides. The zero-match case is announced through the\n directive's live region instead.\n-->\n<ul class=\"wr-mention-panel__list\" role=\"listbox\" [attr.id]=\"listboxId()\" [attr.aria-label]=\"listLabel()\">\n @for (item of items(); track $index) {\n <li\n class=\"wr-mention-panel__option\"\n role=\"option\"\n [attr.id]=\"optionId($index)\"\n [class.wr-mention-panel__option--active]=\"$index === activeIndex()\"\n [attr.aria-selected]=\"$index === activeIndex()\"\n (mouseenter)=\"hovered.emit($index)\"\n (mousedown)=\"onPick(item, $event)\"\n >\n {{ displayWith()(item) }}\n </li>\n }\n</ul>\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directionality } from '@angular/cdk/bidi';\nimport { coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n type ConnectedPosition,\n type FlexibleConnectedPositionStrategyOrigin,\n type OverlayRef,\n ScrollStrategyOptions,\n} from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n type ComponentRef,\n DestroyRef,\n Directive,\n ElementRef,\n Injector,\n PLATFORM_ID,\n computed,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { readI18nText, useI18nFormatter } from 'ngwr/i18n';\nimport { WR_OVERLAY, wrFollowDirection } from 'ngwr/overlay';\nimport { isComposing } from 'ngwr/utils';\n\nimport { getCaretCoordinates } from './caret';\nimport type { WrMentionCommit, WrMentionItem } from './interfaces';\nimport { WrMentionPanel, wrMentionOptionId } from './mention-panel';\n\ninterface ActiveState {\n trigger: string;\n query: string;\n startIndex: number;\n}\n\n/**\n * Deterministic under prerender, unlike `randomId()` — `aria-controls` is a\n * static host binding, so it renders on the server too, and a random value would\n * differ between that render and the hydrated client.\n */\nlet mentionUid = 0;\n\n/** Gap between the caret's line and the panel, on whichever side it opens. */\nconst CARET_GAP = 4;\n\n/**\n * Below the caret's line first, above it when there is no room — the two sides\n * a caret-anchored list can take. There is no horizontal pair: a panel that\n * jumped to the other side of the caret would read as a different widget, so a\n * caret near the inline end is handled by `withPush` sliding the panel back\n * onto the screen instead. `overlayX: 'start'` is the logical corner, so RTL\n * hangs the panel from the caret's other side without a second table.\n */\nconst CARET_POSITIONS: ConnectedPosition[] = [\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' },\n];\n\n/**\n * `@`-style mention picker for `<textarea>` and `<input>`. Listens for\n * trigger characters (default `'@'`); when typed at a word boundary, an\n * overlay panel opens at the caret and shows filtered options. Pick with\n * Enter / Tab / click — the trigger + query is replaced with the inserted\n * value plus a trailing space.\n *\n * @example\n * ```html\n * <textarea\n * wrMention\n * [wrMentionItems]=\"users\"\n * [displayWith]=\"userLabel\"\n * (wrMentionSelected)=\"onMention($event)\"\n * ></textarea>\n * ```\n *\n * @see https://ngwr.dev/reference/components/mention\n */\n@Directive({\n selector: '[wrMention]',\n host: {\n '(input)': 'onInput()',\n '(click)': 'onClick()',\n '(keyup)': 'onCaretMove($event)',\n '(keydown)': 'onKeydown($event)',\n '(blur)': 'onBlur()',\n\n // The IME pair. `isComposing` on a `keydown` answers \"did the input method\n // take this key\", which is a different question from \"is a conversion open\n // right now\" — on the committing keystroke the two disagree by design — and\n // detection runs from `input` and `keyup`, where there is no such flag to\n // read. So the state is tracked here and the detector consults it.\n '(compositionstart)': 'onCompositionStart()',\n '(compositionend)': 'onCompositionEnd()',\n\n // The host keeps its implicit `role=\"textbox\"`. It is NOT a combobox: this\n // field holds prose and the mention is one fragment inside it, not the\n // field's value. `role=\"combobox\"` is also flatly disallowed on `<textarea>`\n // by ARIA in HTML (axe: `aria-allowed-role`), and it would drop\n // `aria-multiline`, which combobox does not support — so a screen reader\n // would stop reporting the field as multi-line for the whole editing\n // session, not just while the popup is open.\n //\n // Static, because `aria-autocomplete` describes a permanent capability of\n // the field; ARIA says authors SHOULD NOT toggle it to signal that\n // suggestions are currently showing. Being static is also what makes the\n // feature discoverable — it is announced on focus, before the user types a\n // trigger char.\n 'aria-autocomplete': 'list',\n // Required alongside `aria-autocomplete=\"list\"`, and must name the popup's\n // role. Measured clean on a textbox with axe-core 4.13.\n 'aria-haspopup': 'listbox',\n // Also static, and deliberately left pointing at an id that only exists\n // while the panel is open: gating it would mean gating `aria-autocomplete`\n // too. An unresolved `aria-controls` is a manual-review note in axe, never a\n // violation — unlike `aria-activedescendant`, which is an author error.\n //\n // This is the attribute that legalises the whole design: for a textbox\n // controlling a popup, `aria-activedescendant` is allowed to name an element\n // owned by the *controlled* element, which is how the reference reaches into\n // the CDK overlay's separate DOM subtree at all.\n '[attr.aria-controls]': 'listboxId',\n '[attr.aria-activedescendant]': 'activeOptionId()',\n\n // No `aria-expanded`. It is not a supported state of `role=\"textbox\"` —\n // axe rates it a *critical* `aria-allowed-attr` violation — so the\n // \"a list appeared\" signal cannot be an ARIA state here. That is what the\n // live region below is for; it is load-bearing, not decoration.\n },\n})\nexport class WrMention<T extends WrMentionItem = WrMentionItem> {\n /** Items to filter against the typed query. */\n readonly wrMentionItems = input<readonly T[]>([]);\n\n /** Trigger characters that open the panel. @default ['@'] */\n readonly triggers = input<readonly string[]>(['@']);\n\n /** Maps an item to its display label. @default `item.label` */\n readonly displayWith = input<(item: T) => string>((item: T) => item.label);\n\n /**\n * Returns the text to insert into the textarea on commit. Receives the\n * picked item and the trigger char. @default `${trigger}${displayWith(item)}`\n */\n readonly valueWith = input<((item: T, trigger: string) => string) | null>(null);\n\n /** Custom filter. @default case-insensitive `includes` over `displayWith(item)`. */\n readonly filterWith = input<((query: string, item: T) => boolean) | null>(null);\n\n /** Maximum number of items shown in the panel. @default 8 */\n readonly maxResults = input(8, { transform: (v: unknown): number => Math.max(1, coerceNumberProperty(v, 8)) });\n\n /** Emits the selected item, trigger, and query whenever the user commits. */\n readonly wrMentionSelected = output<WrMentionCommit<T>>();\n\n private readonly host = inject<ElementRef<HTMLTextAreaElement | HTMLInputElement>>(ElementRef);\n private readonly overlay = inject(WR_OVERLAY);\n /**\n * Optional inject: `Directionality` is root-provided, so this is never null in\n * an app — but a bare `TestBed` that provides nothing should still get a\n * directive that works, and defaulting to LTR is the honest fallback.\n */\n private readonly dir = inject(Directionality, { optional: true });\n private readonly scrollStrategies = inject(ScrollStrategyOptions);\n private readonly destroyRef = inject(DestroyRef);\n private readonly injector = inject(Injector);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n private overlayRef: OverlayRef | null = null;\n private panelRef: ComponentRef<WrMentionPanel> | null = null;\n /**\n * Where the caret sits INSIDE the field — its offset from the field's\n * top-left corner, plus the height of the line it is on. Mutated in place by\n * `open()`, never replaced: `caretAnchor()` closes over this object.\n */\n private readonly caretOffset = { dx: 0, dy: 0, lineHeight: 0 };\n private state: ActiveState | null = null;\n private readonly activeIndex = signal(0);\n private readonly filteredItems = signal<readonly T[]>([]);\n private readonly isOpen = signal(false);\n\n /** @internal — read by the `aria-controls` host binding. */\n protected readonly listboxId = `wr-mention-listbox-${++mentionUid}`;\n\n private readonly listLabel = readI18nText('mention.listbox', 'Mentions');\n private readonly availableText = useI18nFormatter('mention.available', 'Matches available: {{count}}');\n private readonly insertedText = useI18nFormatter('mention.inserted', 'Inserted: {{label}}');\n\n /**\n * `aria-activedescendant`, or `null`.\n *\n * Gated hard on `isOpen()`, which is only set once the panel's options are\n * actually in the DOM. An id that resolves to nothing is an author error, and\n * the failure mode is silent: the browser does not complain, it simply stops\n * firing the event that makes a screen reader speak the option. Same\n * discipline `tree.ts` uses for its virtualized rows.\n */\n protected readonly activeOptionId = computed<string | null>(() => {\n if (!this.isOpen()) return null;\n const index = this.activeIndex();\n return index >= 0 && index < this.filteredItems().length ? wrMentionOptionId(this.listboxId, index) : null;\n });\n\n /**\n * Polite live region, parked on `<body>`.\n *\n * Not inside the panel: `close()` disposes the overlay on every keystroke that\n * leaves a mention, so a region living there would be recreated constantly —\n * and a live region has to be in the DOM *before* its text changes to be\n * announced at all. It also could not announce the two cases that matter most,\n * since in both the panel is already gone: \"nothing matched\" and \"inserted X\".\n *\n * Not a sibling of the host either — that would land inside the consumer's\n * markup and start matching their `+`, `~` and `:nth-child()` selectors.\n */\n private liveRegion: HTMLElement | null = null;\n\n constructor() {\n if (this.isBrowser) {\n const doc = this.host.nativeElement.ownerDocument;\n const region = doc.createElement('div');\n region.className = 'wr-mention__status';\n region.setAttribute('role', 'status');\n doc.body.appendChild(region);\n this.liveRegion = region;\n }\n\n this.destroyRef.onDestroy(() => {\n this.close();\n this.liveRegion?.remove();\n this.liveRegion = null;\n });\n }\n\n private announce(message: string): void {\n if (this.liveRegion) this.liveRegion.textContent = message;\n }\n\n // Host listeners\n\n /**\n * True between `compositionstart` and `compositionend`.\n *\n * Detection must not run on the half-built text an IME leaves in the field:\n * `@やま` is a reading on its way to `@山田`, and matching the reading opens a\n * panel that then eats the Enter meant to accept the conversion. So the field\n * is read once, on `compositionend`, when the text is real.\n */\n private composing = false;\n\n /** @internal */\n protected onCompositionStart(): void {\n this.composing = true;\n // A panel opened before the conversion started would take the arrows and the\n // Enter that now belong to the candidate window.\n this.close();\n }\n\n /** @internal */\n protected onCompositionEnd(): void {\n this.composing = false;\n // The committed text is only in the field now, so this is the first honest\n // read of it.\n this.detect();\n }\n\n /** @internal */\n protected onInput(): void {\n if (this.composing) return;\n this.detect();\n }\n\n /** @internal */\n protected onClick(): void {\n this.detect();\n }\n\n /** @internal */\n protected onCaretMove(event: KeyboardEvent): void {\n if (this.composing || isComposing(event)) return;\n // Every key `onKeydown` already consumed, Escape included: its keyup would\n // re-detect at a caret that is still sitting inside the mention and reopen the\n // panel Escape had just dismissed. A synthetic keydown-only Escape hides that\n // — the real gesture is a pair, and the second half undid the first.\n if (\n event.key === 'ArrowUp' ||\n event.key === 'ArrowDown' ||\n event.key === 'Enter' ||\n event.key === 'Tab' ||\n event.key === 'Escape'\n ) {\n return;\n }\n this.detect();\n }\n\n /** @internal */\n protected onKeydown(event: KeyboardEvent): void {\n // The key is the input method's while a conversion is open — Enter accepts a\n // candidate, Escape cancels the reading, the arrows walk the candidate list.\n // `this.composing` is deliberately not consulted: on Safari's committing\n // keystroke it has already gone false, and `isComposing` covers that case\n // through the 229 sentinel.\n if (isComposing(event)) return;\n if (!this.state) return;\n const list = this.filteredItems();\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n if (list.length > 0) this.setActive((this.activeIndex() + 1) % list.length);\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (list.length > 0) this.setActive((this.activeIndex() - 1 + list.length) % list.length);\n break;\n case 'Enter':\n case 'Tab': {\n const item = list[this.activeIndex()];\n if (item) {\n event.preventDefault();\n this.commit(item);\n }\n break;\n }\n case 'Escape':\n event.preventDefault();\n // The panel is the innermost thing Escape can dismiss, so it keeps the\n // key: without this, the same press also closed the dialog / drawer /\n // window the field sits in.\n //\n // `preventDefault()` alone buys nothing — every host overlay matches on\n // `event.key` and none of them looks at `defaultPrevented` — and letting\n // CDK's `OverlayKeyboardDispatcher` sort it out does not work either.\n // The dispatcher walks the stack newest-first and stops at the first\n // overlay with a `keydownEvents()` subscriber; this panel has none (it\n // is driven from the field's own handler, which runs at the target\n // before the body-phase dispatcher), so Escape falls straight through to\n // the overlay underneath.\n event.stopPropagation();\n this.close();\n break;\n default:\n break;\n }\n }\n\n /** @internal */\n protected onBlur(): void {\n // Defer so option mousedown lands first.\n setTimeout(() => this.close(), 120);\n }\n\n // Detection\n\n private detect(): void {\n const el = this.host.nativeElement;\n const caret = el.selectionStart ?? 0;\n const text = el.value.substring(0, caret);\n const triggers = this.triggers();\n\n // Walk back from the caret looking for a trigger char with whitespace\n // (or start-of-string) immediately before it. Stop on whitespace.\n let i = caret;\n while (i > 0) {\n const ch = text[i - 1];\n if (triggers.includes(ch)) {\n const before = i - 2 >= 0 ? text[i - 2] : '';\n if (i - 2 < 0 || /\\s/.test(before)) {\n const query = text.substring(i);\n this.activate(ch, query, i - 1);\n return;\n }\n break;\n }\n if (/\\s/.test(ch)) break;\n i--;\n }\n this.close();\n }\n\n private activate(trigger: string, query: string, startIndex: number): void {\n this.state = { trigger, query, startIndex };\n const previousCount = this.filteredItems().length;\n const filtered = this.filter(query).slice(0, this.maxResults());\n this.filteredItems.set(filtered);\n if (filtered.length === 0) {\n // Announce *after* closing: `close()` clears the region, so announcing\n // first would wipe the message before a screen reader reached it.\n this.close();\n this.announce(this.availableText({ count: 0 }));\n return;\n }\n this.setActive(Math.min(this.activeIndex(), filtered.length - 1));\n this.open();\n // Only when the size actually changes. Re-announcing the same count on every\n // keystroke would talk over the per-option speech from activedescendant.\n if (filtered.length !== previousCount) this.announce(this.availableText({ count: filtered.length }));\n }\n\n private filter(query: string): readonly T[] {\n const items = this.wrMentionItems();\n const custom = this.filterWith();\n const display = this.displayWith();\n if (!query) return items;\n if (custom) return items.filter(item => custom(query, item));\n const q = query.toLowerCase();\n return items.filter(item => display(item).toLowerCase().includes(q));\n }\n\n private setActive(i: number): void {\n this.activeIndex.set(i);\n this.panelRef?.setInput('activeIndex', i);\n }\n\n // Overlay\n\n /**\n * The overlay's anchor: the caret's line box, grown by the gap the panel\n * keeps from the text, as a zero-WIDTH virtual origin in viewport\n * coordinates. Inflating the rect rather than passing `offsetY` is what keeps\n * `withPush` honest — CDK applies a position offset as a `transform` AFTER it\n * has clamped, so a pushed panel would land the offset off the screen edge.\n *\n * Live getters, not a snapshot, and that is the whole of the scroll fix.\n * `getCaretCoordinates` answers in viewport coordinates, which a\n * `GlobalPositionStrategy` froze at the instant of the keystroke: the panel\n * then stayed pinned to the screen while the page scrolled out from under it\n * (150px of scroll, 150px of drift, ending up over unrelated content). CDK\n * re-reads a virtual origin on every `apply()`, so pinning it to the FIELD's\n * live rect is what turns `reposition()` into a real re-anchor.\n *\n * Only the caret's offset inside the field is captured up front. Measuring it\n * runs the mirror-div pass in `caret.ts` — a full layout read, far too\n * expensive to repeat per scroll event — and it cannot change without a\n * keystroke, which re-enters `open()` anyway.\n */\n private caretAnchor(): FlexibleConnectedPositionStrategyOrigin {\n const field = this.host.nativeElement;\n const offset = this.caretOffset;\n return {\n width: 0,\n get x(): number {\n return field.getBoundingClientRect().left + offset.dx;\n },\n get y(): number {\n return field.getBoundingClientRect().top + offset.dy - CARET_GAP;\n },\n get height(): number {\n return offset.lineHeight + CARET_GAP * 2;\n },\n };\n }\n\n private open(): void {\n const el = this.host.nativeElement;\n const caret = el.selectionStart ?? 0;\n const { top, left, lineHeight } = getCaretCoordinates(el, caret);\n const field = el.getBoundingClientRect();\n this.caretOffset.dx = left - field.left;\n this.caretOffset.dy = top - field.top;\n this.caretOffset.lineHeight = lineHeight;\n\n if (!this.overlayRef) {\n this.overlayRef = this.overlay.create({\n // Flexible, not global: a global strategy has no anchor and no fallback\n // positions, so the panel was always drawn downward from the caret no\n // matter how little room was left below it — half the list ended up\n // under the fold, unreachable by pointer AND invisible to a sighted\n // keyboard user walking it with `aria-activedescendant` (WCAG 2.4.11).\n positionStrategy: this.overlay\n .position()\n .flexibleConnectedTo(this.caretAnchor())\n // The panel sizes itself (`max-height` on the list); the flip above\n // and `withPush` are the whole answer to a cramped viewport.\n .withFlexibleDimensions(false)\n .withPush(true)\n .withPositions(CARET_POSITIONS),\n scrollStrategy: this.scrollStrategies.reposition(),\n panelClass: 'wr-mention-overlay',\n });\n\n // Once per mention SESSION, which is the same thing as once per ref here:\n // the block this sits in is the only place one is created, and `close()`\n // is the only place one is disposed. No callback — `CARET_POSITIONS`\n // carries no `offsetX` to mirror, by the design noted at the table, so\n // `setDirection` plus the reposition the helper already does is the whole\n // of it: the panel hangs off the caret's other side and the list inside\n // reads the way the page now does.\n wrFollowDirection(this.overlayRef, this.dir, this.injector);\n\n const portal = new ComponentPortal(WrMentionPanel);\n const ref = this.overlayRef.attach(portal);\n this.panelRef = ref;\n ref.setInput('displayWith', this.displayWith());\n ref.setInput('listboxId', this.listboxId);\n // Read once here rather than bound: the panel is created per open, and by\n // then the catalog has long landed.\n ref.setInput('listLabel', this.listLabel());\n ref.instance.picked.subscribe(item => this.commit(item as T));\n ref.instance.hovered.subscribe(i => this.setActive(i));\n }\n // No `else` re-building the strategy: the anchor reads `caretOffset` and the\n // field's live rect, both of which the lines above have already refreshed.\n\n this.panelRef?.setInput('items', this.filteredItems());\n this.panelRef?.setInput('activeIndex', this.activeIndex());\n\n // Render the panel's own view NOW, before `aria-activedescendant` is allowed\n // to name one of its options. `attach()` inserts the host element but leaves\n // it empty — the panel is a separate root view, so on the first open the\n // `<li>` being referenced does not exist anywhere in the document yet.\n // Waiting for the next tick would leave a window where the reference dangles\n // and the announcement is lost with no error anywhere.\n this.panelRef?.changeDetectorRef.detectChanges();\n // Place it only now, with the options rendered: which side of the caret the\n // panel takes is decided by measuring it, and `attach()` defers CDK's own\n // first placement into `afterNextRender` — a frame in which the panel would\n // be painted, full size and fully opaque, at the overlay container's\n // top-left corner.\n this.overlayRef.updatePosition();\n this.isOpen.set(true);\n }\n\n private close(): void {\n if (this.overlayRef) {\n this.overlayRef.dispose();\n this.overlayRef = null;\n this.panelRef = null;\n }\n this.isOpen.set(false);\n this.state = null;\n this.activeIndex.set(0);\n this.filteredItems.set([]);\n this.announce('');\n }\n\n private commit(item: T): void {\n // Snapshot the state up front. `dispatchEvent` below re-enters this directive\n // synchronously: the listener runs `detect()`, and because assigning\n // `el.value` has already parked the caret at the end of the text — past the\n // space this method appends — `detect()` finds no trigger and calls\n // `close()`, which nulls `this.state`. Reading `this.state` after that line\n // threw, so `wrMentionSelected` never fired for anyone.\n const state = this.state;\n if (!state) return;\n\n const el = this.host.nativeElement;\n const value = el.value;\n const caret = el.selectionStart ?? value.length;\n const valueFn = this.valueWith();\n const label = this.displayWith()(item);\n const inserted = valueFn ? valueFn(item, state.trigger) : `${state.trigger}${label}`;\n const replacement = `${inserted} `;\n const before = value.substring(0, state.startIndex);\n const after = value.substring(caret);\n const next = before + replacement + after;\n\n el.value = next;\n el.dispatchEvent(new Event('input', { bubbles: true }));\n const nextCaret = (before + replacement).length;\n el.setSelectionRange(nextCaret, nextCaret);\n this.wrMentionSelected.emit({ item, trigger: state.trigger, query: state.query });\n\n // Announce after `close()`, never before — it clears the live region.\n // Committing is otherwise silent: the panel simply vanishes.\n this.close();\n this.announce(this.insertedText({ label }));\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -247,10 +247,10 @@ class WrMeta {
247
247
  link.remove();
248
248
  }
249
249
  }
250
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrMeta, deps: [], target: i0.ɵɵFactoryTarget.Service });
251
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.6", ngImport: i0, type: WrMeta });
250
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrMeta, deps: [], target: i0.ɵɵFactoryTarget.Service });
251
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.7", ngImport: i0, type: WrMeta });
252
252
  }
253
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrMeta, decorators: [{
253
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrMeta, decorators: [{
254
254
  type: Service
255
255
  }], ctorParameters: () => [] });
256
256
 
@@ -292,10 +292,10 @@ class WrMetaBinding {
292
292
  });
293
293
  inject(DestroyRef).onDestroy(() => this.handle?.pop());
294
294
  }
295
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrMetaBinding, deps: [], target: i0.ɵɵFactoryTarget.Directive });
296
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.6", type: WrMetaBinding, isStandalone: true, selector: "[wrMeta]", inputs: { wrMeta: { classPropertyName: "wrMeta", publicName: "wrMeta", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
295
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrMetaBinding, deps: [], target: i0.ɵɵFactoryTarget.Directive });
296
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: WrMetaBinding, isStandalone: true, selector: "[wrMeta]", inputs: { wrMeta: { classPropertyName: "wrMeta", publicName: "wrMeta", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
297
297
  }
298
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrMetaBinding, decorators: [{
298
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrMetaBinding, decorators: [{
299
299
  type: Directive,
300
300
  args: [{ selector: '[wrMeta]' }]
301
301
  }], ctorParameters: () => [], propDecorators: { wrMeta: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrMeta", required: true }] }] } });
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-meta.mjs","sources":["../../../projects/lib/meta/tokens.ts","../../../projects/lib/meta/wr-meta.ts","../../../projects/lib/meta/wr-meta-binding.ts","../../../projects/lib/meta/provide-wr-meta.ts","../../../projects/lib/meta/ngwr-meta.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 { InjectionToken } from '@angular/core';\n\nimport type { WrMetaConfig } from './interfaces';\n\n/** App-wide defaults registered via {@link provideWrMeta}. */\nexport const WR_META_DEFAULTS = new InjectionToken<WrMetaConfig>('WR_META_DEFAULTS', {\n factory: (): WrMetaConfig => ({}),\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 { DOCUMENT } from '@angular/common';\nimport { Injector, Service, computed, effect, inject, signal, untracked } from '@angular/core';\nimport { Meta, Title } from '@angular/platform-browser';\n\nimport type { WrMetaConfig, WrMetaHandle } from './interfaces';\nimport { WR_META_DEFAULTS } from './tokens';\n\n/** Deep-merge two `WrMetaConfig` layers — later wins for scalars + nested groups. */\nfunction merge(base: WrMetaConfig, top: WrMetaConfig): WrMetaConfig {\n return {\n ...base,\n ...top,\n og: { ...base.og, ...top.og },\n twitter: { ...base.twitter, ...top.twitter },\n };\n}\n\n/**\n * Centralised `<head>` metadata manager — title, description, keywords,\n * canonical, Open Graph and Twitter Card tags.\n *\n * Stack-based: `push(config)` adds a layer (returned handle pops it),\n * `set(config)` replaces the current top, `reset()` clears all overrides.\n * Layers merge via shallow merge for scalars and a one-level deep merge\n * for `og` / `twitter` groups.\n *\n * The title and the canonical link are diffed against the last applied\n * snapshot and only rewritten when they actually change; the `<meta>` tags\n * are re-resolved by selector on every apply, so an existing tag is updated\n * in place rather than duplicated.\n *\n * @example\n * ```ts\n * const meta = inject(WrMeta);\n * meta.set({ title: 'Pricing', description: 'Plans for every team.' });\n *\n * // From a route component — auto-pop on destroy via the directive:\n * <div [wrMeta]=\"{ title: 'Pricing' }\">\n * ```\n *\n * @see https://ngwr.dev/reference/services/meta\n */\n@Service()\nexport class WrMeta {\n private readonly title = inject(Title);\n private readonly meta = inject(Meta);\n private readonly doc = inject(DOCUMENT);\n private readonly defaults = inject(WR_META_DEFAULTS);\n private readonly injector = inject(Injector);\n\n /** Stack of meta layers. Bottom = defaults, top = currently applied. */\n private readonly stack = signal<readonly WrMetaConfig[]>([this.defaults]);\n\n /** Resolved (merged) metadata at the top of the stack. */\n readonly resolved = computed(() => this.stack().reduce((acc, layer) => merge(acc, layer), {} as WrMetaConfig));\n\n /** Last applied snapshot — used to diff against the next resolution. */\n private applied: WrMetaConfig = {};\n\n constructor() {\n // Apply defaults immediately on construction.\n this.apply();\n }\n\n /** Snapshot of the resolved metadata currently in the DOM. */\n current(): Readonly<WrMetaConfig> {\n return this.applied;\n }\n\n /** Replace the top layer (or create one if only defaults are present). */\n set(config: WrMetaConfig): void {\n this.stack.update(stack => {\n if (stack.length <= 1) return [...stack, config];\n return [...stack.slice(0, -1), config];\n });\n this.apply();\n }\n\n /** Push a new layer. Returns a handle whose `.pop()` removes it. */\n push(config: WrMetaConfig): WrMetaHandle {\n // Copied so the layer has an identity of its own: the handle finds it by\n // reference, and pushing one shared config object twice would otherwise\n // give two layers the same identity — the first handle to pop would take\n // the second one's layer with it.\n const target: WrMetaConfig = { ...config };\n this.stack.update(stack => [...stack, target]);\n this.apply();\n return {\n pop: () => {\n this.stack.update(stack => {\n const idx = stack.lastIndexOf(target);\n if (idx <= 0) return stack;\n return [...stack.slice(0, idx), ...stack.slice(idx + 1)];\n });\n this.apply();\n },\n };\n }\n\n /**\n * Reactive layer. Runs `factory` inside an effect and re-applies the\n * resolved metadata whenever any signal it reads changes — so a title\n * (or any field) built from {@link WrI18n}'s `t()` updates live on\n * locale switch, with no manual re-`set()`.\n *\n * Returns a handle whose `.pop()` removes the layer and stops the effect.\n * Safe to call outside an injection context.\n *\n * @example Locale-aware title\n * ```ts\n * const meta = inject(WrMeta);\n * const i18n = inject(WrI18n);\n *\n * // `i18n.t(...)` tracks the active locale, so the title re-renders\n * // every time `i18n.use(...)` switches languages.\n * meta.bind(() => ({\n * title: i18n.t('home.title'),\n * description: i18n.t('home.description'),\n * }));\n * ```\n */\n bind(factory: () => WrMetaConfig): WrMetaHandle {\n let current: WrMetaConfig | null = null;\n\n const ref = effect(\n () => {\n // Copied for the same reason as in `push`: the layer is located by\n // reference, so it must not share one with anybody else's.\n const next: WrMetaConfig = { ...factory() };\n // Recompute is reactive; the stack write + DOM apply are not, so\n // the effect only re-runs on `factory`'s own dependencies.\n untracked(() => {\n this.stack.update(stack => {\n if (current === null) return [...stack, next];\n const idx = stack.lastIndexOf(current);\n return idx < 0 ? [...stack, next] : [...stack.slice(0, idx), next, ...stack.slice(idx + 1)];\n });\n current = next;\n this.apply();\n });\n },\n { injector: this.injector }\n );\n\n return {\n pop: () => {\n ref.destroy();\n if (current === null) return;\n const target = current;\n current = null;\n this.stack.update(stack => {\n const idx = stack.lastIndexOf(target);\n if (idx <= 0) return stack;\n return [...stack.slice(0, idx), ...stack.slice(idx + 1)];\n });\n this.apply();\n },\n };\n }\n\n /** Pop the most recently pushed layer (defaults remain). */\n pop(): void {\n this.stack.update(stack => (stack.length <= 1 ? stack : stack.slice(0, -1)));\n this.apply();\n }\n\n /** Clear all overrides, restore the defaults registered via `provideWrMeta`. */\n reset(): void {\n this.stack.set([this.defaults]);\n this.apply();\n }\n\n // Internals\n\n private apply(): void {\n const next = this.resolved();\n this.diffTitle(next);\n this.diffMeta(next);\n this.diffLink(next);\n this.applied = next;\n }\n\n private diffTitle(next: WrMetaConfig): void {\n if (next.title === this.applied.title && next.titleTemplate === this.applied.titleTemplate) return;\n if (next.title) {\n // `{{ title }}` reads like Angular; `%s` stays for printf fans.\n const formatted = next.titleTemplate\n ? next.titleTemplate.replace(/\\{\\{\\s*title\\s*\\}\\}/g, next.title).replace('%s', next.title)\n : next.title;\n this.title.setTitle(formatted);\n } else if (this.applied.title) {\n this.title.setTitle('');\n }\n }\n\n private diffMeta(next: WrMetaConfig): void {\n this.updateName('description', next.description);\n this.updateName('keywords', next.keywords?.join(', '));\n this.updateName('theme-color', next.themeColor);\n\n // Open Graph.\n this.updateProp('og:title', next.og?.title ?? next.title);\n this.updateProp('og:description', next.og?.description ?? next.description);\n this.updateProp('og:image', next.og?.image);\n this.updateProp('og:url', next.og?.url ?? next.canonical);\n this.updateProp('og:type', next.og?.type);\n this.updateProp('og:site_name', next.og?.siteName);\n\n // Twitter.\n this.updateName('twitter:card', next.twitter?.card);\n this.updateName('twitter:title', next.twitter?.title ?? next.title);\n this.updateName('twitter:description', next.twitter?.description ?? next.description);\n this.updateName('twitter:image', next.twitter?.image ?? next.og?.image);\n this.updateName('twitter:creator', next.twitter?.creator);\n }\n\n private updateName(name: string, content: string | undefined): void {\n if (content) {\n this.meta.updateTag({ name, content }, `name='${name}'`);\n } else {\n this.meta.removeTag(`name='${name}'`);\n }\n }\n\n private updateProp(property: string, content: string | undefined): void {\n if (content) {\n this.meta.updateTag({ property, content }, `property='${property}'`);\n } else {\n this.meta.removeTag(`property='${property}'`);\n }\n }\n\n private diffLink(next: WrMetaConfig): void {\n if (next.canonical === this.applied.canonical) return;\n const head = this.doc.head;\n let link = head.querySelector<HTMLLinkElement>(\"link[rel='canonical']\");\n if (next.canonical) {\n if (!link) {\n link = this.doc.createElement('link');\n link.setAttribute('rel', 'canonical');\n head.appendChild(link);\n }\n link.setAttribute('href', next.canonical);\n } else if (link) {\n link.remove();\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 { DestroyRef, Directive, effect, inject, input, untracked } from '@angular/core';\n\nimport type { WrMetaConfig, WrMetaHandle } from './interfaces';\nimport { WrMeta } from './wr-meta';\n\n/**\n * Declarative wrapper around {@link WrMeta}.\n *\n * - Pushes the bound config on init.\n * - Re-pushes (replacing) when the config reference changes.\n * - Pops the layer on destroy — perfect for route-level meta overrides.\n *\n * @example\n * ```html\n * <div [wrMeta]=\"{ title: 'Pricing', description: 'Plans for every team.' }\">\n * ```\n */\n@Directive({ selector: '[wrMeta]' })\nexport class WrMetaBinding {\n readonly wrMeta = input.required<WrMetaConfig>();\n\n private readonly metaService = inject(WrMeta);\n private handle: WrMetaHandle | null = null;\n\n constructor() {\n effect(() => {\n const next = this.wrMeta();\n // Only the INPUT is read reactively. `push` / `pop` write the service's\n // layer stack and then re-apply, and applying reads that same stack through\n // `resolved()` — so without this the effect depends on a signal it writes\n // and re-runs forever. `WrMeta.bind()` guards the identical pair the same\n // way; this directive was missing it.\n untracked(() => {\n this.handle?.pop();\n this.handle = this.metaService.push(next);\n });\n });\n inject(DestroyRef).onDestroy(() => this.handle?.pop());\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 type { WrMetaConfig } from './interfaces';\nimport { WR_META_DEFAULTS } from './tokens';\n\n/**\n * Register app-wide defaults for {@link WrMeta}. Use to set a\n * consistent baseline `title` / `titleTemplate` / `og` / `twitter` for every\n * route — individual routes / components can override via\n * `metaService.push(...)` or the `[wrMeta]` directive.\n *\n * @example\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [\n * provideWrMeta({\n * titleTemplate: '{{ title }} · NGWR',\n * description: 'Angular UI components library',\n * og: { siteName: 'NGWR', type: 'website' },\n * twitter: { card: 'summary_large_image', creator: '@thekhegay' },\n * }),\n * ],\n * });\n * ```\n */\nexport function provideWrMeta(defaults: WrMetaConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: WR_META_DEFAULTS, useValue: defaults }]);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;AAAA;;;;;AAKG;AAMH;MACa,gBAAgB,GAAG,IAAI,cAAc,CAAe,kBAAkB,EAAE;AACnF,IAAA,OAAO,EAAE,OAAqB,EAAE,CAAC;AAClC,CAAA;;ACdD;;;;;AAKG;AASH;AACA,SAAS,KAAK,CAAC,IAAkB,EAAE,GAAiB,EAAA;IAClD,OAAO;AACL,QAAA,GAAG,IAAI;AACP,QAAA,GAAG,GAAG;QACN,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,GAAG,CAAC,EAAE,EAAE;QAC7B,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE;KAC7C;AACH;AAEA;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;MAEU,MAAM,CAAA;AACA,IAAA,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;AACrB,IAAA,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;AACnB,IAAA,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;AACtB,IAAA,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACnC,IAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;;AAG3B,IAAA,KAAK,GAAG,MAAM,CAA0B,CAAC,IAAI,CAAC,QAAQ,CAAC;8EAAC;;AAGhE,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,KAAK,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAkB,CAAC;iFAAC;;IAGtG,OAAO,GAAiB,EAAE;AAElC,IAAA,WAAA,GAAA;;QAEE,IAAI,CAAC,KAAK,EAAE;IACd;;IAGA,OAAO,GAAA;QACL,OAAO,IAAI,CAAC,OAAO;IACrB;;AAGA,IAAA,GAAG,CAAC,MAAoB,EAAA;AACtB,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAG;AACxB,YAAA,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;AAAE,gBAAA,OAAO,CAAC,GAAG,KAAK,EAAE,MAAM,CAAC;AAChD,YAAA,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;AACxC,QAAA,CAAC,CAAC;QACF,IAAI,CAAC,KAAK,EAAE;IACd;;AAGA,IAAA,IAAI,CAAC,MAAoB,EAAA;;;;;AAKvB,QAAA,MAAM,MAAM,GAAiB,EAAE,GAAG,MAAM,EAAE;AAC1C,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK,EAAE;QACZ,OAAO;YACL,GAAG,EAAE,MAAK;AACR,gBAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAG;oBACxB,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;oBACrC,IAAI,GAAG,IAAI,CAAC;AAAE,wBAAA,OAAO,KAAK;oBAC1B,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AAC1D,gBAAA,CAAC,CAAC;gBACF,IAAI,CAAC,KAAK,EAAE;YACd,CAAC;SACF;IACH;AAEA;;;;;;;;;;;;;;;;;;;;;AAqBG;AACH,IAAA,IAAI,CAAC,OAA2B,EAAA;QAC9B,IAAI,OAAO,GAAwB,IAAI;AAEvC,QAAA,MAAM,GAAG,GAAG,MAAM,CAChB,MAAK;;;AAGH,YAAA,MAAM,IAAI,GAAiB,EAAE,GAAG,OAAO,EAAE,EAAE;;;YAG3C,SAAS,CAAC,MAAK;AACb,gBAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAG;oBACxB,IAAI,OAAO,KAAK,IAAI;AAAE,wBAAA,OAAO,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC;oBAC7C,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC;AACtC,oBAAA,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AAC7F,gBAAA,CAAC,CAAC;gBACF,OAAO,GAAG,IAAI;gBACd,IAAI,CAAC,KAAK,EAAE;AACd,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,2EACC,QAAQ,EAAE,IAAI,CAAC,QAAQ,GAC1B;QAED,OAAO;YACL,GAAG,EAAE,MAAK;gBACR,GAAG,CAAC,OAAO,EAAE;gBACb,IAAI,OAAO,KAAK,IAAI;oBAAE;gBACtB,MAAM,MAAM,GAAG,OAAO;gBACtB,OAAO,GAAG,IAAI;AACd,gBAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAG;oBACxB,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;oBACrC,IAAI,GAAG,IAAI,CAAC;AAAE,wBAAA,OAAO,KAAK;oBAC1B,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AAC1D,gBAAA,CAAC,CAAC;gBACF,IAAI,CAAC,KAAK,EAAE;YACd,CAAC;SACF;IACH;;IAGA,GAAG,GAAA;AACD,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5E,IAAI,CAAC,KAAK,EAAE;IACd;;IAGA,KAAK,GAAA;QACH,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,EAAE;IACd;;IAIQ,KAAK,GAAA;AACX,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE;AAC5B,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AACpB,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AACnB,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AACnB,QAAA,IAAI,CAAC,OAAO,GAAG,IAAI;IACrB;AAEQ,IAAA,SAAS,CAAC,IAAkB,EAAA;AAClC,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC,OAAO,CAAC,aAAa;YAAE;AAC5F,QAAA,IAAI,IAAI,CAAC,KAAK,EAAE;;AAEd,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC;kBACnB,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,sBAAsB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK;AACzF,kBAAE,IAAI,CAAC,KAAK;AACd,YAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;QAChC;AAAO,aAAA,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;AAC7B,YAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB;IACF;AAEQ,IAAA,QAAQ,CAAC,IAAkB,EAAA;QACjC,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,IAAI,CAAC,WAAW,CAAC;AAChD,QAAA,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,IAAI,CAAC,UAAU,CAAC;;AAG/C,QAAA,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;AACzD,QAAA,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,IAAI,CAAC,EAAE,EAAE,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC;QAC3E,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC;AAC3C,QAAA,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC;QACzD,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC;QACzC,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC;;QAGlD,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC;AACnD,QAAA,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;AACnE,QAAA,IAAI,CAAC,UAAU,CAAC,qBAAqB,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC;AACrF,QAAA,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC;QACvE,IAAI,CAAC,UAAU,CAAC,iBAAiB,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;IAC3D;IAEQ,UAAU,CAAC,IAAY,EAAE,OAA2B,EAAA;QAC1D,IAAI,OAAO,EAAE;AACX,YAAA,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAA,MAAA,EAAS,IAAI,CAAA,CAAA,CAAG,CAAC;QAC1D;aAAO;YACL,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA,MAAA,EAAS,IAAI,CAAA,CAAA,CAAG,CAAC;QACvC;IACF;IAEQ,UAAU,CAAC,QAAgB,EAAE,OAA2B,EAAA;QAC9D,IAAI,OAAO,EAAE;AACX,YAAA,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAA,UAAA,EAAa,QAAQ,CAAA,CAAA,CAAG,CAAC;QACtE;aAAO;YACL,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA,UAAA,EAAa,QAAQ,CAAA,CAAA,CAAG,CAAC;QAC/C;IACF;AAEQ,IAAA,QAAQ,CAAC,IAAkB,EAAA;QACjC,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,OAAO,CAAC,SAAS;YAAE;AAC/C,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI;QAC1B,IAAI,IAAI,GAAG,IAAI,CAAC,aAAa,CAAkB,uBAAuB,CAAC;AACvE,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,IAAI,CAAC,IAAI,EAAE;gBACT,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC;AACrC,gBAAA,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC;AACrC,gBAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YACxB;YACA,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;QAC3C;aAAO,IAAI,IAAI,EAAE;YACf,IAAI,CAAC,MAAM,EAAE;QACf;IACF;uGA3MW,MAAM,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,OAAA,EAAA,CAAA;wGAAN,MAAM,EAAA,CAAA;;2FAAN,MAAM,EAAA,UAAA,EAAA,CAAA;kBADlB;;;ACjDD;;;;;AAKG;AAOH;;;;;;;;;;;AAWG;MAEU,aAAa,CAAA;IACf,MAAM,GAAG,KAAK,CAAC,QAAQ;+EAAgB;AAE/B,IAAA,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;IACrC,MAAM,GAAwB,IAAI;AAE1C,IAAA,WAAA,GAAA;QACE,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE;;;;;;YAM1B,SAAS,CAAC,MAAK;AACb,gBAAA,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;gBAClB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;AAC3C,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;AACF,QAAA,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC;IACxD;uGApBW,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAb,aAAa,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAb,aAAa,EAAA,UAAA,EAAA,CAAA;kBADzB,SAAS;mBAAC,EAAE,QAAQ,EAAE,UAAU,EAAE;;;ACxBnC;;;;;AAKG;AAOH;;;;;;;;;;;;;;;;;;;AAmBG;AACG,SAAU,aAAa,CAAC,QAAA,GAAyB,EAAE,EAAA;AACvD,IAAA,OAAO,wBAAwB,CAAC,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;AACtF;;AClCA;;AAEG;;;;"}
1
+ {"version":3,"file":"ngwr-meta.mjs","sources":["../../../projects/lib/meta/tokens.ts","../../../projects/lib/meta/wr-meta.ts","../../../projects/lib/meta/wr-meta-binding.ts","../../../projects/lib/meta/provide-wr-meta.ts","../../../projects/lib/meta/ngwr-meta.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 { InjectionToken } from '@angular/core';\n\nimport type { WrMetaConfig } from './interfaces';\n\n/** App-wide defaults registered via {@link provideWrMeta}. */\nexport const WR_META_DEFAULTS = new InjectionToken<WrMetaConfig>('WR_META_DEFAULTS', {\n factory: (): WrMetaConfig => ({}),\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 { DOCUMENT } from '@angular/common';\nimport { Injector, Service, computed, effect, inject, signal, untracked } from '@angular/core';\nimport { Meta, Title } from '@angular/platform-browser';\n\nimport type { WrMetaConfig, WrMetaHandle } from './interfaces';\nimport { WR_META_DEFAULTS } from './tokens';\n\n/** Deep-merge two `WrMetaConfig` layers — later wins for scalars + nested groups. */\nfunction merge(base: WrMetaConfig, top: WrMetaConfig): WrMetaConfig {\n return {\n ...base,\n ...top,\n og: { ...base.og, ...top.og },\n twitter: { ...base.twitter, ...top.twitter },\n };\n}\n\n/**\n * Centralised `<head>` metadata manager — title, description, keywords,\n * canonical, Open Graph and Twitter Card tags.\n *\n * Stack-based: `push(config)` adds a layer (returned handle pops it),\n * `set(config)` replaces the current top, `reset()` clears all overrides.\n * Layers merge via shallow merge for scalars and a one-level deep merge\n * for `og` / `twitter` groups.\n *\n * The title and the canonical link are diffed against the last applied\n * snapshot and only rewritten when they actually change; the `<meta>` tags\n * are re-resolved by selector on every apply, so an existing tag is updated\n * in place rather than duplicated.\n *\n * @example\n * ```ts\n * const meta = inject(WrMeta);\n * meta.set({ title: 'Pricing', description: 'Plans for every team.' });\n *\n * // From a route component — auto-pop on destroy via the directive:\n * <div [wrMeta]=\"{ title: 'Pricing' }\">\n * ```\n *\n * @see https://ngwr.dev/reference/services/meta\n */\n@Service()\nexport class WrMeta {\n private readonly title = inject(Title);\n private readonly meta = inject(Meta);\n private readonly doc = inject(DOCUMENT);\n private readonly defaults = inject(WR_META_DEFAULTS);\n private readonly injector = inject(Injector);\n\n /** Stack of meta layers. Bottom = defaults, top = currently applied. */\n private readonly stack = signal<readonly WrMetaConfig[]>([this.defaults]);\n\n /** Resolved (merged) metadata at the top of the stack. */\n readonly resolved = computed(() => this.stack().reduce((acc, layer) => merge(acc, layer), {} as WrMetaConfig));\n\n /** Last applied snapshot — used to diff against the next resolution. */\n private applied: WrMetaConfig = {};\n\n constructor() {\n // Apply defaults immediately on construction.\n this.apply();\n }\n\n /** Snapshot of the resolved metadata currently in the DOM. */\n current(): Readonly<WrMetaConfig> {\n return this.applied;\n }\n\n /** Replace the top layer (or create one if only defaults are present). */\n set(config: WrMetaConfig): void {\n this.stack.update(stack => {\n if (stack.length <= 1) return [...stack, config];\n return [...stack.slice(0, -1), config];\n });\n this.apply();\n }\n\n /** Push a new layer. Returns a handle whose `.pop()` removes it. */\n push(config: WrMetaConfig): WrMetaHandle {\n // Copied so the layer has an identity of its own: the handle finds it by\n // reference, and pushing one shared config object twice would otherwise\n // give two layers the same identity — the first handle to pop would take\n // the second one's layer with it.\n const target: WrMetaConfig = { ...config };\n this.stack.update(stack => [...stack, target]);\n this.apply();\n return {\n pop: () => {\n this.stack.update(stack => {\n const idx = stack.lastIndexOf(target);\n if (idx <= 0) return stack;\n return [...stack.slice(0, idx), ...stack.slice(idx + 1)];\n });\n this.apply();\n },\n };\n }\n\n /**\n * Reactive layer. Runs `factory` inside an effect and re-applies the\n * resolved metadata whenever any signal it reads changes — so a title\n * (or any field) built from {@link WrI18n}'s `t()` updates live on\n * locale switch, with no manual re-`set()`.\n *\n * Returns a handle whose `.pop()` removes the layer and stops the effect.\n * Safe to call outside an injection context.\n *\n * @example Locale-aware title\n * ```ts\n * const meta = inject(WrMeta);\n * const i18n = inject(WrI18n);\n *\n * // `i18n.t(...)` tracks the active locale, so the title re-renders\n * // every time `i18n.use(...)` switches languages.\n * meta.bind(() => ({\n * title: i18n.t('home.title'),\n * description: i18n.t('home.description'),\n * }));\n * ```\n */\n bind(factory: () => WrMetaConfig): WrMetaHandle {\n let current: WrMetaConfig | null = null;\n\n const ref = effect(\n () => {\n // Copied for the same reason as in `push`: the layer is located by\n // reference, so it must not share one with anybody else's.\n const next: WrMetaConfig = { ...factory() };\n // Recompute is reactive; the stack write + DOM apply are not, so\n // the effect only re-runs on `factory`'s own dependencies.\n untracked(() => {\n this.stack.update(stack => {\n if (current === null) return [...stack, next];\n const idx = stack.lastIndexOf(current);\n return idx < 0 ? [...stack, next] : [...stack.slice(0, idx), next, ...stack.slice(idx + 1)];\n });\n current = next;\n this.apply();\n });\n },\n { injector: this.injector }\n );\n\n return {\n pop: () => {\n ref.destroy();\n if (current === null) return;\n const target = current;\n current = null;\n this.stack.update(stack => {\n const idx = stack.lastIndexOf(target);\n if (idx <= 0) return stack;\n return [...stack.slice(0, idx), ...stack.slice(idx + 1)];\n });\n this.apply();\n },\n };\n }\n\n /** Pop the most recently pushed layer (defaults remain). */\n pop(): void {\n this.stack.update(stack => (stack.length <= 1 ? stack : stack.slice(0, -1)));\n this.apply();\n }\n\n /** Clear all overrides, restore the defaults registered via `provideWrMeta`. */\n reset(): void {\n this.stack.set([this.defaults]);\n this.apply();\n }\n\n // Internals\n\n private apply(): void {\n const next = this.resolved();\n this.diffTitle(next);\n this.diffMeta(next);\n this.diffLink(next);\n this.applied = next;\n }\n\n private diffTitle(next: WrMetaConfig): void {\n if (next.title === this.applied.title && next.titleTemplate === this.applied.titleTemplate) return;\n if (next.title) {\n // `{{ title }}` reads like Angular; `%s` stays for printf fans.\n const formatted = next.titleTemplate\n ? next.titleTemplate.replace(/\\{\\{\\s*title\\s*\\}\\}/g, next.title).replace('%s', next.title)\n : next.title;\n this.title.setTitle(formatted);\n } else if (this.applied.title) {\n this.title.setTitle('');\n }\n }\n\n private diffMeta(next: WrMetaConfig): void {\n this.updateName('description', next.description);\n this.updateName('keywords', next.keywords?.join(', '));\n this.updateName('theme-color', next.themeColor);\n\n // Open Graph.\n this.updateProp('og:title', next.og?.title ?? next.title);\n this.updateProp('og:description', next.og?.description ?? next.description);\n this.updateProp('og:image', next.og?.image);\n this.updateProp('og:url', next.og?.url ?? next.canonical);\n this.updateProp('og:type', next.og?.type);\n this.updateProp('og:site_name', next.og?.siteName);\n\n // Twitter.\n this.updateName('twitter:card', next.twitter?.card);\n this.updateName('twitter:title', next.twitter?.title ?? next.title);\n this.updateName('twitter:description', next.twitter?.description ?? next.description);\n this.updateName('twitter:image', next.twitter?.image ?? next.og?.image);\n this.updateName('twitter:creator', next.twitter?.creator);\n }\n\n private updateName(name: string, content: string | undefined): void {\n if (content) {\n this.meta.updateTag({ name, content }, `name='${name}'`);\n } else {\n this.meta.removeTag(`name='${name}'`);\n }\n }\n\n private updateProp(property: string, content: string | undefined): void {\n if (content) {\n this.meta.updateTag({ property, content }, `property='${property}'`);\n } else {\n this.meta.removeTag(`property='${property}'`);\n }\n }\n\n private diffLink(next: WrMetaConfig): void {\n if (next.canonical === this.applied.canonical) return;\n const head = this.doc.head;\n let link = head.querySelector<HTMLLinkElement>(\"link[rel='canonical']\");\n if (next.canonical) {\n if (!link) {\n link = this.doc.createElement('link');\n link.setAttribute('rel', 'canonical');\n head.appendChild(link);\n }\n link.setAttribute('href', next.canonical);\n } else if (link) {\n link.remove();\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 { DestroyRef, Directive, effect, inject, input, untracked } from '@angular/core';\n\nimport type { WrMetaConfig, WrMetaHandle } from './interfaces';\nimport { WrMeta } from './wr-meta';\n\n/**\n * Declarative wrapper around {@link WrMeta}.\n *\n * - Pushes the bound config on init.\n * - Re-pushes (replacing) when the config reference changes.\n * - Pops the layer on destroy — perfect for route-level meta overrides.\n *\n * @example\n * ```html\n * <div [wrMeta]=\"{ title: 'Pricing', description: 'Plans for every team.' }\">\n * ```\n */\n@Directive({ selector: '[wrMeta]' })\nexport class WrMetaBinding {\n readonly wrMeta = input.required<WrMetaConfig>();\n\n private readonly metaService = inject(WrMeta);\n private handle: WrMetaHandle | null = null;\n\n constructor() {\n effect(() => {\n const next = this.wrMeta();\n // Only the INPUT is read reactively. `push` / `pop` write the service's\n // layer stack and then re-apply, and applying reads that same stack through\n // `resolved()` — so without this the effect depends on a signal it writes\n // and re-runs forever. `WrMeta.bind()` guards the identical pair the same\n // way; this directive was missing it.\n untracked(() => {\n this.handle?.pop();\n this.handle = this.metaService.push(next);\n });\n });\n inject(DestroyRef).onDestroy(() => this.handle?.pop());\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 type { WrMetaConfig } from './interfaces';\nimport { WR_META_DEFAULTS } from './tokens';\n\n/**\n * Register app-wide defaults for {@link WrMeta}. Use to set a\n * consistent baseline `title` / `titleTemplate` / `og` / `twitter` for every\n * route — individual routes / components can override via\n * `metaService.push(...)` or the `[wrMeta]` directive.\n *\n * @example\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [\n * provideWrMeta({\n * titleTemplate: '{{ title }} · NGWR',\n * description: 'Angular UI components library',\n * og: { siteName: 'NGWR', type: 'website' },\n * twitter: { card: 'summary_large_image', creator: '@thekhegay' },\n * }),\n * ],\n * });\n * ```\n */\nexport function provideWrMeta(defaults: WrMetaConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: WR_META_DEFAULTS, useValue: defaults }]);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -12,8 +12,9 @@ const SLICE_WIDTH = /(?:^|;)\s*width\s*:\s*([\d.]+)%/;
12
12
  * Test harness for `<wr-meter-group>` — one bar divided into labelled bands.
13
13
  *
14
14
  * **The bar is a single `progressbar`, and its value is the TOTAL.** The bands
15
- * themselves announce nothing: they carry a `title` for a mouse and their share as an
16
- * inline width, and the legend is where their labels and values are readable. So a
15
+ * themselves announce nothing: they carry a hover tooltip (or, with `tooltip` off, a
16
+ * `title`) for a mouse and their share as an inline width, and the legend is where
17
+ * their labels and values are readable. So a
17
18
  * spec that wants "how much of each" reads {@link getSlices} for the shares or
18
19
  * {@link getLegendLabels} / {@link getLegendValues} for what is printed, and one that
19
20
  * wants "how full" reads {@link getValue}.
@@ -62,7 +63,10 @@ class WrMeterGroupHarness extends ComponentHarness {
62
63
  async getSlices() {
63
64
  const slices = await this.locatorForAll('.wr-meter-group__slice')();
64
65
  return Promise.all(slices.map(async (slice) => {
65
- const label = await slice.getAttribute('title');
66
+ // `data-label`, which the band carries whatever `tooltip` says. The `title`
67
+ // this used to read is written only while the tooltip is off, so reading it
68
+ // would answer `null` for every band of a default meter.
69
+ const label = await slice.getAttribute('data-label');
66
70
  return { label, percent: WrMeterGroupHarness.percentOf(label, await slice.getAttribute('style')) };
67
71
  }));
68
72
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-meter-group-testing.mjs","sources":["../../../projects/lib/meter-group/testing/wr-meter-group-harness.ts","../../../projects/lib/meter-group/testing/ngwr-meter-group-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 type { WrMeterGroupHarnessFilters, WrMeterGroupSlice } from './interfaces';\n\n/** The `width: <n>%` the component writes onto a band, out of its inline `style`. */\nconst SLICE_WIDTH = /(?:^|;)\\s*width\\s*:\\s*([\\d.]+)%/;\n\n/**\n * Test harness for `<wr-meter-group>` — one bar divided into labelled bands.\n *\n * **The bar is a single `progressbar`, and its value is the TOTAL.** The bands\n * themselves announce nothing: they carry a `title` for a mouse and their share as an\n * inline width, and the legend is where their labels and values are readable. So a\n * spec that wants \"how much of each\" reads {@link getSlices} for the shares or\n * {@link getLegendLabels} / {@link getLegendValues} for what is printed, and one that\n * wants \"how full\" reads {@link getValue}.\n *\n * **A band's share is read off the `style` ATTRIBUTE, not through `getCssValue()`**,\n * and the difference is not cosmetic: `getCssValue()` is `getComputedStyle()`, and\n * `width` resolves to the USED value — so the declared `30%` comes straight back in\n * jsdom and arrives as `180px` on a 600px bar in a real browser, and the same harness\n * answered 30 here and 180 under a browser runner with nothing to say which one you\n * got.\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrMeterGroupHarness extends ComponentHarness {\n static hostSelector = 'wr-meter-group';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrMeterGroupHarnessFilters = {}): HarnessPredicate<WrMeterGroupHarness> {\n return new HarnessPredicate(WrMeterGroupHarness, options)\n .addOption('ariaLabel', options.ariaLabel, (harness, label) =>\n HarnessPredicate.stringMatches(harness.getAccessibleName(), label)\n )\n .addOption('sliceLabel', options.sliceLabel, async (harness, label) => {\n for (const printed of await harness.getLegendLabels()) {\n if (await HarnessPredicate.stringMatches(printed, label)) return true;\n }\n return false;\n });\n }\n\n private readonly bar = this.locatorFor('.wr-meter-group__bar');\n\n /** The role the bar announces — `progressbar`, for the total. */\n async getRole(): Promise<string | null> {\n return (await this.bar()).getAttribute('role');\n }\n\n /** The bar's accessible name. */\n async getAccessibleName(): Promise<string | null> {\n return (await this.bar()).getAttribute('aria-label');\n }\n\n /** The total the bands add up to, from `aria-valuenow`. */\n async getValue(): Promise<number> {\n return Number(await (await this.bar()).getAttribute('aria-valuenow'));\n }\n\n /** The full capacity, from `aria-valuemax` — given, or the sum of the bands. */\n async getMax(): Promise<number> {\n return Number(await (await this.bar()).getAttribute('aria-valuemax'));\n }\n\n /** The bands, in order, with the share of the bar each takes. */\n async getSlices(): Promise<WrMeterGroupSlice[]> {\n const slices = await this.locatorForAll('.wr-meter-group__slice')();\n\n return Promise.all(\n slices.map(async slice => {\n const label = await slice.getAttribute('title');\n return { label, percent: WrMeterGroupHarness.percentOf(label, await slice.getAttribute('style')) };\n })\n );\n }\n\n /** Parse one band's declared share. See the class note on why this is not `getCssValue()`. */\n private static percentOf(label: string | null, style: string | null): number {\n const match = SLICE_WIDTH.exec(style ?? '');\n if (!match) {\n throw new Error(\n `WrMeterGroupHarness.getSlices(): the band ${label === null ? '(untitled)' : `\"${label}\"`} carries no ` +\n `inline width percentage (style: \"${style ?? ''}\"). The component writes one for every band, since the ` +\n 'total always falls back to 1 — so its absence is the bug, and reporting 0 would read as an empty band.'\n );\n }\n return Number.parseFloat(match[1]);\n }\n\n /** Whether the legend is rendered (`showLegend`, and at least one band). */\n async hasLegend(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-meter-group__legend')()) !== null;\n }\n\n /** The legend's labels, in order. */\n async getLegendLabels(): Promise<string[]> {\n const labels = await this.locatorForAll('.wr-meter-group__legend-label')();\n return Promise.all(labels.map(label => label.text()));\n }\n\n /** The legend's values, in order — empty when `showValues` is off. */\n async getLegendValues(): Promise<string[]> {\n const values = await this.locatorForAll('.wr-meter-group__legend-value')();\n return Promise.all(values.map(value => value.text()));\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAMH;AACA,MAAM,WAAW,GAAG,iCAAiC;AAErD;;;;;;;;;;;;;;;;;;AAkBG;AACG,MAAO,mBAAoB,SAAQ,gBAAgB,CAAA;AACvD,IAAA,OAAO,YAAY,GAAG,gBAAgB;;AAGtC,IAAA,OAAO,IAAI,CAAC,OAAA,GAAsC,EAAE,EAAA;AAClD,QAAA,OAAO,IAAI,gBAAgB,CAAC,mBAAmB,EAAE,OAAO;aACrD,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,KAAK,KACxD,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,KAAK,CAAC;AAEnE,aAAA,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,OAAO,EAAE,KAAK,KAAI;YACpE,KAAK,MAAM,OAAO,IAAI,MAAM,OAAO,CAAC,eAAe,EAAE,EAAE;gBACrD,IAAI,MAAM,gBAAgB,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC;AAAE,oBAAA,OAAO,IAAI;YACvE;AACA,YAAA,OAAO,KAAK;AACd,QAAA,CAAC,CAAC;IACN;AAEiB,IAAA,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,sBAAsB,CAAC;;AAG9D,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,MAAM,CAAC;IAChD;;AAGA,IAAA,MAAM,iBAAiB,GAAA;AACrB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,YAAY,CAAC;IACtD;;AAGA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IACvE;;AAGA,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IACvE;;AAGA,IAAA,MAAM,SAAS,GAAA;QACb,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,wBAAwB,CAAC,EAAE;AAEnE,QAAA,OAAO,OAAO,CAAC,GAAG,CAChB,MAAM,CAAC,GAAG,CAAC,OAAM,KAAK,KAAG;YACvB,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC;YAC/C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,EAAE;QACpG,CAAC,CAAC,CACH;IACH;;AAGQ,IAAA,OAAO,SAAS,CAAC,KAAoB,EAAE,KAAoB,EAAA;QACjE,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAC3C,IAAI,CAAC,KAAK,EAAE;AACV,YAAA,MAAM,IAAI,KAAK,CACb,CAAA,0CAAA,EAA6C,KAAK,KAAK,IAAI,GAAG,YAAY,GAAG,CAAA,CAAA,EAAI,KAAK,GAAG,CAAA,YAAA,CAAc;gBACrG,CAAA,iCAAA,EAAoC,KAAK,IAAI,EAAE,CAAA,uDAAA,CAAyD;AACxG,gBAAA,wGAAwG,CAC3G;QACH;QACA,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACpC;;AAGA,IAAA,MAAM,SAAS,GAAA;AACb,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,yBAAyB,CAAC,EAAE,MAAM,IAAI;IAC9E;;AAGA,IAAA,MAAM,eAAe,GAAA;QACnB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,+BAA+B,CAAC,EAAE;AAC1E,QAAA,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACvD;;AAGA,IAAA,MAAM,eAAe,GAAA;QACnB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,+BAA+B,CAAC,EAAE;AAC1E,QAAA,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACvD;;;AChHF;;AAEG;;;;"}
1
+ {"version":3,"file":"ngwr-meter-group-testing.mjs","sources":["../../../projects/lib/meter-group/testing/wr-meter-group-harness.ts","../../../projects/lib/meter-group/testing/ngwr-meter-group-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 type { WrMeterGroupHarnessFilters, WrMeterGroupSlice } from './interfaces';\n\n/** The `width: <n>%` the component writes onto a band, out of its inline `style`. */\nconst SLICE_WIDTH = /(?:^|;)\\s*width\\s*:\\s*([\\d.]+)%/;\n\n/**\n * Test harness for `<wr-meter-group>` — one bar divided into labelled bands.\n *\n * **The bar is a single `progressbar`, and its value is the TOTAL.** The bands\n * themselves announce nothing: they carry a hover tooltip (or, with `tooltip` off, a\n * `title`) for a mouse and their share as an inline width, and the legend is where\n * their labels and values are readable. So a\n * spec that wants \"how much of each\" reads {@link getSlices} for the shares or\n * {@link getLegendLabels} / {@link getLegendValues} for what is printed, and one that\n * wants \"how full\" reads {@link getValue}.\n *\n * **A band's share is read off the `style` ATTRIBUTE, not through `getCssValue()`**,\n * and the difference is not cosmetic: `getCssValue()` is `getComputedStyle()`, and\n * `width` resolves to the USED value — so the declared `30%` comes straight back in\n * jsdom and arrives as `180px` on a 600px bar in a real browser, and the same harness\n * answered 30 here and 180 under a browser runner with nothing to say which one you\n * got.\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrMeterGroupHarness extends ComponentHarness {\n static hostSelector = 'wr-meter-group';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrMeterGroupHarnessFilters = {}): HarnessPredicate<WrMeterGroupHarness> {\n return new HarnessPredicate(WrMeterGroupHarness, options)\n .addOption('ariaLabel', options.ariaLabel, (harness, label) =>\n HarnessPredicate.stringMatches(harness.getAccessibleName(), label)\n )\n .addOption('sliceLabel', options.sliceLabel, async (harness, label) => {\n for (const printed of await harness.getLegendLabels()) {\n if (await HarnessPredicate.stringMatches(printed, label)) return true;\n }\n return false;\n });\n }\n\n private readonly bar = this.locatorFor('.wr-meter-group__bar');\n\n /** The role the bar announces — `progressbar`, for the total. */\n async getRole(): Promise<string | null> {\n return (await this.bar()).getAttribute('role');\n }\n\n /** The bar's accessible name. */\n async getAccessibleName(): Promise<string | null> {\n return (await this.bar()).getAttribute('aria-label');\n }\n\n /** The total the bands add up to, from `aria-valuenow`. */\n async getValue(): Promise<number> {\n return Number(await (await this.bar()).getAttribute('aria-valuenow'));\n }\n\n /** The full capacity, from `aria-valuemax` — given, or the sum of the bands. */\n async getMax(): Promise<number> {\n return Number(await (await this.bar()).getAttribute('aria-valuemax'));\n }\n\n /** The bands, in order, with the share of the bar each takes. */\n async getSlices(): Promise<WrMeterGroupSlice[]> {\n const slices = await this.locatorForAll('.wr-meter-group__slice')();\n\n return Promise.all(\n slices.map(async slice => {\n // `data-label`, which the band carries whatever `tooltip` says. The `title`\n // this used to read is written only while the tooltip is off, so reading it\n // would answer `null` for every band of a default meter.\n const label = await slice.getAttribute('data-label');\n return { label, percent: WrMeterGroupHarness.percentOf(label, await slice.getAttribute('style')) };\n })\n );\n }\n\n /** Parse one band's declared share. See the class note on why this is not `getCssValue()`. */\n private static percentOf(label: string | null, style: string | null): number {\n const match = SLICE_WIDTH.exec(style ?? '');\n if (!match) {\n throw new Error(\n `WrMeterGroupHarness.getSlices(): the band ${label === null ? '(untitled)' : `\"${label}\"`} carries no ` +\n `inline width percentage (style: \"${style ?? ''}\"). The component writes one for every band, since the ` +\n 'total always falls back to 1 — so its absence is the bug, and reporting 0 would read as an empty band.'\n );\n }\n return Number.parseFloat(match[1]);\n }\n\n /** Whether the legend is rendered (`showLegend`, and at least one band). */\n async hasLegend(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-meter-group__legend')()) !== null;\n }\n\n /** The legend's labels, in order. */\n async getLegendLabels(): Promise<string[]> {\n const labels = await this.locatorForAll('.wr-meter-group__legend-label')();\n return Promise.all(labels.map(label => label.text()));\n }\n\n /** The legend's values, in order — empty when `showValues` is off. */\n async getLegendValues(): Promise<string[]> {\n const values = await this.locatorForAll('.wr-meter-group__legend-value')();\n return Promise.all(values.map(value => value.text()));\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion';
2
2
  import * as i0 from '@angular/core';
3
- import { input, computed, ViewEncapsulation, Component } from '@angular/core';
3
+ import { input, viewChildren, computed, ViewEncapsulation, Component } from '@angular/core';
4
4
  import { useI18nText } from 'ngwr/i18n';
5
+ import { useChartTooltip } from 'ngwr/popover';
5
6
 
6
7
  /**
7
8
  * @license
@@ -47,6 +48,14 @@ class WrMeterGroup {
47
48
  showLegend = input(true, { ...(ngDevMode ? { debugName: "showLegend" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
48
49
  /** Show each segment's value in the legend, next to its label. @default true */
49
50
  showValues = input(true, { ...(ngDevMode ? { debugName: "showValues" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
51
+ /**
52
+ * Show a tooltip with the segment's label and value on hover. It replaces the
53
+ * band's `title`, which is written only while this is off — or the browser would
54
+ * open a second copy a moment later. @default true
55
+ */
56
+ tooltip = input(true, { ...(ngDevMode ? { debugName: "tooltip" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
57
+ sliceEls = viewChildren('slice', /* @ts-ignore */
58
+ ...(ngDevMode ? [{ debugName: "sliceEls" }] : /* istanbul ignore next */ []));
50
59
  /**
51
60
  * A segment's contribution, floored at `0` and with anything non-finite read
52
61
  * as `0`. One `NaN` used to poison the whole bar: the sum is `NaN` as soon as
@@ -82,13 +91,24 @@ class WrMeterGroup {
82
91
  percent: (WrMeterGroup.amount(segment.value) / this.resolvedMax()) * 100,
83
92
  })), /* @ts-ignore */
84
93
  ...(ngDevMode ? [{ debugName: "slices" }] : /* istanbul ignore next */ []));
85
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrMeterGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
86
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrMeterGroup, isStandalone: true, selector: "wr-meter-group", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, segments: { classPropertyName: "segments", publicName: "segments", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, showLegend: { classPropertyName: "showLegend", publicName: "showLegend", isSignal: true, isRequired: false, transformFunction: null }, showValues: { classPropertyName: "showValues", publicName: "showValues", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-meter-group" }, ngImport: i0, template: "<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <span\n class=\"wr-meter-group__slice\"\n [title]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\n}\n", encapsulation: i0.ViewEncapsulation.None });
94
+ /**
95
+ * One tooltip for the whole bar, pointing at the hovered band, with the value as
96
+ * the legend prints it.
97
+ */
98
+ tip = useChartTooltip(this.tooltip, index => {
99
+ const slice = this.slices()[index];
100
+ const el = this.sliceEls()[index]?.nativeElement;
101
+ if (!slice || !el)
102
+ return null;
103
+ return { datum: { label: slice.label, value: String(slice.value), color: slice.color }, anchor: el };
104
+ });
105
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrMeterGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
106
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: WrMeterGroup, isStandalone: true, selector: "wr-meter-group", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, segments: { classPropertyName: "segments", publicName: "segments", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, showLegend: { classPropertyName: "showLegend", publicName: "showLegend", isSignal: true, isRequired: false, transformFunction: null }, showValues: { classPropertyName: "showValues", publicName: "showValues", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-meter-group" }, viewQueries: [{ propertyName: "sliceEls", predicate: ["slice"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <!-- `data-label` is what the harness reads a band's label from; the `title` it\n used to read is only written while the tooltip is off. -->\n <span\n #slice\n class=\"wr-meter-group__slice\"\n [attr.title]=\"tooltip() ? null : slice.label\"\n [attr.data-label]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n (mouseenter)=\"tip.enter($index)\"\n (mouseleave)=\"tip.leave($event)\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\n}\n", encapsulation: i0.ViewEncapsulation.None });
87
107
  }
88
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrMeterGroup, decorators: [{
108
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrMeterGroup, decorators: [{
89
109
  type: Component,
90
- args: [{ selector: 'wr-meter-group', encapsulation: ViewEncapsulation.None, host: { class: 'wr-meter-group' }, template: "<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <span\n class=\"wr-meter-group__slice\"\n [title]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\n}\n" }]
91
- }], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValues", required: false }] }] } });
110
+ args: [{ selector: 'wr-meter-group', encapsulation: ViewEncapsulation.None, host: { class: 'wr-meter-group' }, template: "<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <!-- `data-label` is what the harness reads a band's label from; the `title` it\n used to read is only written while the tooltip is off. -->\n <span\n #slice\n class=\"wr-meter-group__slice\"\n [attr.title]=\"tooltip() ? null : slice.label\"\n [attr.data-label]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n (mouseenter)=\"tip.enter($index)\"\n (mouseleave)=\"tip.leave($event)\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\n}\n" }]
111
+ }], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValues", required: false }] }], tooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltip", required: false }] }], sliceEls: [{ type: i0.ViewChildren, args: ['slice', { isSignal: true }] }] } });
92
112
 
93
113
  /**
94
114
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-meter-group.mjs","sources":["../../../projects/lib/meter-group/meter-group.ts","../../../projects/lib/meter-group/meter-group.html","../../../projects/lib/meter-group/ngwr-meter-group.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, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\nimport { useI18nText } from 'ngwr/i18n';\n\nimport type { WrMeterSegment } from './interfaces';\n\nconst FALLBACK_COLORS = [\n 'var(--wr-color-primary)',\n 'var(--wr-color-success)',\n 'var(--wr-color-warning)',\n 'var(--wr-color-danger)',\n 'var(--wr-color-medium)',\n];\n\n/**\n * Stacked-segment progress bar. Visualises a breakdown of a total —\n * disk usage, budget, vote share, etc. Each segment contributes a slice\n * proportional to its `value` relative to the sum (or the explicit `max`).\n *\n * @example\n * ```html\n * <wr-meter-group\n * [segments]=\"[\n * { label: 'Used', value: 60 },\n * { label: 'Reserved', value: 25, color: 'var(--wr-color-warning)' }\n * ]\"\n * [max]=\"100\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/meter-group\n */\n@Component({\n selector: 'wr-meter-group',\n templateUrl: './meter-group.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-meter-group' },\n})\nexport class WrMeterGroup {\n /** Accessible name — the role needs one. Falls back to `meterGroup.label`. */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'meterGroup.label', 'Meter');\n\n readonly segments = input<readonly WrMeterSegment[]>([]);\n\n /** Explicit total. When `0` (default), `max = sum(values)`. @default 0 */\n readonly max = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Show the labelled legend under the bar. @default true */\n readonly showLegend = input(true, { transform: coerceBooleanProperty });\n\n /** Show each segment's value in the legend, next to its label. @default true */\n readonly showValues = input(true, { transform: coerceBooleanProperty });\n\n /**\n * A segment's contribution, floored at `0` and with anything non-finite read\n * as `0`. One `NaN` used to poison the whole bar: the sum is `NaN` as soon as\n * one value is, so the total fell back to `1` and every OTHER segment was\n * asked for a width of `value * 100`%, while `aria-valuenow` announced `NaN`.\n */\n private static amount(raw: number): number {\n return Number.isFinite(raw) ? Math.max(0, raw) : 0;\n }\n\n protected readonly resolvedMax = computed(() => {\n const explicit = this.max();\n if (explicit > 0) return explicit;\n const sum = this.segments().reduce((acc, s) => acc + WrMeterGroup.amount(s.value), 0);\n return sum > 0 ? sum : 1;\n });\n\n /**\n * Sum of the segments, for `aria-valuenow`. `role=\"progressbar\"` without it\n * announces no value at all, so the bar was invisible to assistive tech.\n *\n * Capped at the total, because segments summing past an explicit `max` used\n * to announce a value outside the range they were announced against.\n */\n protected readonly totalValue = computed(() =>\n Math.min(\n this.resolvedMax(),\n this.segments().reduce((acc, s) => acc + WrMeterGroup.amount(s.value), 0)\n )\n );\n\n protected readonly slices = computed(() =>\n this.segments().map((segment, i) => ({\n label: segment.label,\n // The legend keeps a negative value visible — it is data the caller gave\n // us — but not a non-finite one, which reads as the literal text `NaN`.\n value: Number.isFinite(segment.value) ? segment.value : 0,\n color: segment.color ?? FALLBACK_COLORS[i % FALLBACK_COLORS.length],\n percent: (WrMeterGroup.amount(segment.value) / this.resolvedMax()) * 100,\n }))\n );\n}\n","<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <span\n class=\"wr-meter-group__slice\"\n [title]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\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-meter-group.mjs","sources":["../../../projects/lib/meter-group/meter-group.ts","../../../projects/lib/meter-group/meter-group.html","../../../projects/lib/meter-group/ngwr-meter-group.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, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, type ElementRef, ViewEncapsulation, computed, input, viewChildren } from '@angular/core';\n\nimport { useI18nText } from 'ngwr/i18n';\nimport { useChartTooltip } from 'ngwr/popover';\n\nimport type { WrMeterSegment } from './interfaces';\n\nconst FALLBACK_COLORS = [\n 'var(--wr-color-primary)',\n 'var(--wr-color-success)',\n 'var(--wr-color-warning)',\n 'var(--wr-color-danger)',\n 'var(--wr-color-medium)',\n];\n\n/**\n * Stacked-segment progress bar. Visualises a breakdown of a total —\n * disk usage, budget, vote share, etc. Each segment contributes a slice\n * proportional to its `value` relative to the sum (or the explicit `max`).\n *\n * @example\n * ```html\n * <wr-meter-group\n * [segments]=\"[\n * { label: 'Used', value: 60 },\n * { label: 'Reserved', value: 25, color: 'var(--wr-color-warning)' }\n * ]\"\n * [max]=\"100\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/meter-group\n */\n@Component({\n selector: 'wr-meter-group',\n templateUrl: './meter-group.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-meter-group' },\n})\nexport class WrMeterGroup {\n /** Accessible name — the role needs one. Falls back to `meterGroup.label`. */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'meterGroup.label', 'Meter');\n\n readonly segments = input<readonly WrMeterSegment[]>([]);\n\n /** Explicit total. When `0` (default), `max = sum(values)`. @default 0 */\n readonly max = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Show the labelled legend under the bar. @default true */\n readonly showLegend = input(true, { transform: coerceBooleanProperty });\n\n /** Show each segment's value in the legend, next to its label. @default true */\n readonly showValues = input(true, { transform: coerceBooleanProperty });\n\n /**\n * Show a tooltip with the segment's label and value on hover. It replaces the\n * band's `title`, which is written only while this is off — or the browser would\n * open a second copy a moment later. @default true\n */\n readonly tooltip = input(true, { transform: coerceBooleanProperty });\n\n private readonly sliceEls = viewChildren<ElementRef<HTMLElement>>('slice');\n\n /**\n * A segment's contribution, floored at `0` and with anything non-finite read\n * as `0`. One `NaN` used to poison the whole bar: the sum is `NaN` as soon as\n * one value is, so the total fell back to `1` and every OTHER segment was\n * asked for a width of `value * 100`%, while `aria-valuenow` announced `NaN`.\n */\n private static amount(raw: number): number {\n return Number.isFinite(raw) ? Math.max(0, raw) : 0;\n }\n\n protected readonly resolvedMax = computed(() => {\n const explicit = this.max();\n if (explicit > 0) return explicit;\n const sum = this.segments().reduce((acc, s) => acc + WrMeterGroup.amount(s.value), 0);\n return sum > 0 ? sum : 1;\n });\n\n /**\n * Sum of the segments, for `aria-valuenow`. `role=\"progressbar\"` without it\n * announces no value at all, so the bar was invisible to assistive tech.\n *\n * Capped at the total, because segments summing past an explicit `max` used\n * to announce a value outside the range they were announced against.\n */\n protected readonly totalValue = computed(() =>\n Math.min(\n this.resolvedMax(),\n this.segments().reduce((acc, s) => acc + WrMeterGroup.amount(s.value), 0)\n )\n );\n\n protected readonly slices = computed(() =>\n this.segments().map((segment, i) => ({\n label: segment.label,\n // The legend keeps a negative value visible — it is data the caller gave\n // us — but not a non-finite one, which reads as the literal text `NaN`.\n value: Number.isFinite(segment.value) ? segment.value : 0,\n color: segment.color ?? FALLBACK_COLORS[i % FALLBACK_COLORS.length],\n percent: (WrMeterGroup.amount(segment.value) / this.resolvedMax()) * 100,\n }))\n );\n\n /**\n * One tooltip for the whole bar, pointing at the hovered band, with the value as\n * the legend prints it.\n */\n protected readonly tip = useChartTooltip(this.tooltip, index => {\n const slice = this.slices()[index];\n const el = this.sliceEls()[index]?.nativeElement;\n if (!slice || !el) return null;\n return { datum: { label: slice.label, value: String(slice.value), color: slice.color }, anchor: el };\n });\n}\n","<div\n class=\"wr-meter-group__bar\"\n role=\"progressbar\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"resolvedMax()\"\n [attr.aria-valuenow]=\"totalValue()\"\n>\n @for (slice of slices(); track $index) {\n <!-- `data-label` is what the harness reads a band's label from; the `title` it\n used to read is only written while the tooltip is off. -->\n <span\n #slice\n class=\"wr-meter-group__slice\"\n [attr.title]=\"tooltip() ? null : slice.label\"\n [attr.data-label]=\"slice.label\"\n [style.width.%]=\"slice.percent\"\n [style.background]=\"slice.color\"\n (mouseenter)=\"tip.enter($index)\"\n (mouseleave)=\"tip.leave($event)\"\n ></span>\n }\n</div>\n\n@if (showLegend() && slices().length > 0) {\n <ul class=\"wr-meter-group__legend\">\n @for (slice of slices(); track $index) {\n <li class=\"wr-meter-group__legend-item\">\n <span class=\"wr-meter-group__swatch\" aria-hidden=\"true\" [style.background]=\"slice.color\"></span>\n <span class=\"wr-meter-group__legend-label\">{{ slice.label }}</span>\n @if (showValues()) {\n <span class=\"wr-meter-group__legend-value\">{{ slice.value }}</span>\n }\n </li>\n }\n </ul>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}