ngwr 14.3.1 → 14.5.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 (368) hide show
  1. package/README.md +4 -4
  2. package/avatar/styles/_index.scss +4 -2
  3. package/badge/styles/_index.scss +4 -1
  4. package/badge/styles/_tag.scss +3 -0
  5. package/cascader/styles/_rules.scss +3 -0
  6. package/command-palette/styles/_index.scss +23 -0
  7. package/context-menu/styles/_index.scss +13 -1
  8. package/fesm2022/ngwr-action-sheet.mjs +3 -3
  9. package/fesm2022/ngwr-affix.mjs +17 -4
  10. package/fesm2022/ngwr-affix.mjs.map +1 -1
  11. package/fesm2022/ngwr-alert.mjs +4 -4
  12. package/fesm2022/ngwr-alert.mjs.map +1 -1
  13. package/fesm2022/ngwr-anchor.mjs +3 -3
  14. package/fesm2022/ngwr-aurora.mjs +3 -3
  15. package/fesm2022/ngwr-avatar.mjs +3 -3
  16. package/fesm2022/ngwr-back-top.mjs +3 -3
  17. package/fesm2022/ngwr-badge.mjs +6 -6
  18. package/fesm2022/ngwr-bar-chart-testing.mjs +18 -2
  19. package/fesm2022/ngwr-bar-chart-testing.mjs.map +1 -1
  20. package/fesm2022/ngwr-bar-chart.mjs +3 -3
  21. package/fesm2022/ngwr-blur-text.mjs +3 -3
  22. package/fesm2022/ngwr-border-glow.mjs +3 -3
  23. package/fesm2022/ngwr-breadcrumbs.mjs +7 -7
  24. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  25. package/fesm2022/ngwr-burger.mjs +3 -3
  26. package/fesm2022/ngwr-button.mjs +6 -6
  27. package/fesm2022/ngwr-calendar-heatmap-testing.mjs +12 -9
  28. package/fesm2022/ngwr-calendar-heatmap-testing.mjs.map +1 -1
  29. package/fesm2022/ngwr-calendar-heatmap.mjs +35 -7
  30. package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
  31. package/fesm2022/ngwr-calendar.mjs +32 -4
  32. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  33. package/fesm2022/ngwr-card.mjs +9 -9
  34. package/fesm2022/ngwr-carousel.mjs +6 -6
  35. package/fesm2022/ngwr-cascader-testing.mjs +87 -17
  36. package/fesm2022/ngwr-cascader-testing.mjs.map +1 -1
  37. package/fesm2022/ngwr-cascader.mjs +76 -5
  38. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  39. package/fesm2022/ngwr-checkbox-testing.mjs +13 -2
  40. package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -1
  41. package/fesm2022/ngwr-checkbox.mjs +42 -7
  42. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  43. package/fesm2022/ngwr-circular-text.mjs +3 -3
  44. package/fesm2022/ngwr-click-spark.mjs +3 -3
  45. package/fesm2022/ngwr-clipboard.mjs +3 -3
  46. package/fesm2022/ngwr-collapse.mjs +9 -9
  47. package/fesm2022/ngwr-color-picker.mjs +24 -8
  48. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  49. package/fesm2022/ngwr-command-palette.mjs +16 -3
  50. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  51. package/fesm2022/ngwr-compare.mjs +3 -3
  52. package/fesm2022/ngwr-confetti.mjs +3 -3
  53. package/fesm2022/ngwr-context-menu.mjs +47 -15
  54. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  55. package/fesm2022/ngwr-cookie.mjs +3 -3
  56. package/fesm2022/ngwr-counter.mjs +6 -6
  57. package/fesm2022/ngwr-date-adapters-fns.mjs +3 -3
  58. package/fesm2022/ngwr-date-adapters-luxon.mjs +3 -3
  59. package/fesm2022/ngwr-date-picker.mjs +111 -28
  60. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  61. package/fesm2022/ngwr-date.mjs +3 -3
  62. package/fesm2022/ngwr-decrypt-text.mjs +3 -3
  63. package/fesm2022/ngwr-density.mjs +6 -6
  64. package/fesm2022/ngwr-descriptions.mjs +6 -6
  65. package/fesm2022/ngwr-dialog.mjs +27 -16
  66. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  67. package/fesm2022/ngwr-directives.mjs +12 -12
  68. package/fesm2022/ngwr-divider.mjs +3 -3
  69. package/fesm2022/ngwr-donut-chart-testing.mjs +18 -2
  70. package/fesm2022/ngwr-donut-chart-testing.mjs.map +1 -1
  71. package/fesm2022/ngwr-donut-chart.mjs +4 -4
  72. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  73. package/fesm2022/ngwr-drag-drop.mjs +7 -7
  74. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  75. package/fesm2022/ngwr-drawer.mjs +66 -20
  76. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  77. package/fesm2022/ngwr-dropdown.mjs +54 -16
  78. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  79. package/fesm2022/ngwr-empty.mjs +3 -3
  80. package/fesm2022/ngwr-event-calendar.mjs +6 -6
  81. package/fesm2022/ngwr-falling-text.mjs +3 -3
  82. package/fesm2022/ngwr-file-upload.mjs +18 -5
  83. package/fesm2022/ngwr-file-upload.mjs.map +1 -1
  84. package/fesm2022/ngwr-form.mjs +66 -14
  85. package/fesm2022/ngwr-form.mjs.map +1 -1
  86. package/fesm2022/ngwr-fuzzy-text.mjs +3 -3
  87. package/fesm2022/ngwr-gauge-testing.mjs +16 -2
  88. package/fesm2022/ngwr-gauge-testing.mjs.map +1 -1
  89. package/fesm2022/ngwr-gauge.mjs +3 -3
  90. package/fesm2022/ngwr-glitch-text.mjs +3 -3
  91. package/fesm2022/ngwr-gradient-text.mjs +3 -3
  92. package/fesm2022/ngwr-graph-testing.mjs +243 -0
  93. package/fesm2022/ngwr-graph-testing.mjs.map +1 -0
  94. package/fesm2022/ngwr-graph.mjs +1112 -0
  95. package/fesm2022/ngwr-graph.mjs.map +1 -0
  96. package/fesm2022/ngwr-hotkey.mjs +6 -6
  97. package/fesm2022/ngwr-i18n-ar.mjs +7 -0
  98. package/fesm2022/ngwr-i18n-ar.mjs.map +1 -1
  99. package/fesm2022/ngwr-i18n-cs.mjs +7 -0
  100. package/fesm2022/ngwr-i18n-cs.mjs.map +1 -1
  101. package/fesm2022/ngwr-i18n-de.mjs +7 -0
  102. package/fesm2022/ngwr-i18n-de.mjs.map +1 -1
  103. package/fesm2022/ngwr-i18n-en.mjs +23 -2
  104. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  105. package/fesm2022/ngwr-i18n-es.mjs +7 -0
  106. package/fesm2022/ngwr-i18n-es.mjs.map +1 -1
  107. package/fesm2022/ngwr-i18n-fr.mjs +7 -0
  108. package/fesm2022/ngwr-i18n-fr.mjs.map +1 -1
  109. package/fesm2022/ngwr-i18n-he.mjs +7 -0
  110. package/fesm2022/ngwr-i18n-he.mjs.map +1 -1
  111. package/fesm2022/ngwr-i18n-hi.mjs +7 -0
  112. package/fesm2022/ngwr-i18n-hi.mjs.map +1 -1
  113. package/fesm2022/ngwr-i18n-id.mjs +7 -0
  114. package/fesm2022/ngwr-i18n-id.mjs.map +1 -1
  115. package/fesm2022/ngwr-i18n-it.mjs +7 -0
  116. package/fesm2022/ngwr-i18n-it.mjs.map +1 -1
  117. package/fesm2022/ngwr-i18n-ja.mjs +7 -0
  118. package/fesm2022/ngwr-i18n-ja.mjs.map +1 -1
  119. package/fesm2022/ngwr-i18n-ko.mjs +7 -0
  120. package/fesm2022/ngwr-i18n-ko.mjs.map +1 -1
  121. package/fesm2022/ngwr-i18n-nl.mjs +7 -0
  122. package/fesm2022/ngwr-i18n-nl.mjs.map +1 -1
  123. package/fesm2022/ngwr-i18n-pl.mjs +7 -0
  124. package/fesm2022/ngwr-i18n-pl.mjs.map +1 -1
  125. package/fesm2022/ngwr-i18n-pt.mjs +7 -0
  126. package/fesm2022/ngwr-i18n-pt.mjs.map +1 -1
  127. package/fesm2022/ngwr-i18n-ru.mjs +7 -0
  128. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  129. package/fesm2022/ngwr-i18n-sv.mjs +7 -0
  130. package/fesm2022/ngwr-i18n-sv.mjs.map +1 -1
  131. package/fesm2022/ngwr-i18n-tr.mjs +7 -0
  132. package/fesm2022/ngwr-i18n-tr.mjs.map +1 -1
  133. package/fesm2022/ngwr-i18n-uk.mjs +7 -0
  134. package/fesm2022/ngwr-i18n-uk.mjs.map +1 -1
  135. package/fesm2022/ngwr-i18n-vi.mjs +7 -0
  136. package/fesm2022/ngwr-i18n-vi.mjs.map +1 -1
  137. package/fesm2022/ngwr-i18n-zh-TW.mjs +7 -0
  138. package/fesm2022/ngwr-i18n-zh-TW.mjs.map +1 -1
  139. package/fesm2022/ngwr-i18n-zh.mjs +7 -0
  140. package/fesm2022/ngwr-i18n-zh.mjs.map +1 -1
  141. package/fesm2022/ngwr-i18n.mjs +9 -9
  142. package/fesm2022/ngwr-icon.mjs +6 -6
  143. package/fesm2022/ngwr-image-cropper.mjs +3 -3
  144. package/fesm2022/ngwr-input-number.mjs +15 -6
  145. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  146. package/fesm2022/ngwr-input-otp.mjs +38 -6
  147. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  148. package/fesm2022/ngwr-input.mjs +15 -15
  149. package/fesm2022/ngwr-keyboard.mjs +3 -3
  150. package/fesm2022/ngwr-knob-testing.mjs +11 -3
  151. package/fesm2022/ngwr-knob-testing.mjs.map +1 -1
  152. package/fesm2022/ngwr-knob.mjs +19 -4
  153. package/fesm2022/ngwr-knob.mjs.map +1 -1
  154. package/fesm2022/ngwr-layout.mjs +15 -15
  155. package/fesm2022/ngwr-lightbox.mjs +27 -6
  156. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  157. package/fesm2022/ngwr-line-chart-testing.mjs +18 -2
  158. package/fesm2022/ngwr-line-chart-testing.mjs.map +1 -1
  159. package/fesm2022/ngwr-line-chart.mjs +22 -4
  160. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  161. package/fesm2022/ngwr-list.mjs +7 -7
  162. package/fesm2022/ngwr-list.mjs.map +1 -1
  163. package/fesm2022/ngwr-loading-bar.mjs +6 -6
  164. package/fesm2022/ngwr-markdown.mjs +6 -6
  165. package/fesm2022/ngwr-marquee.mjs +3 -3
  166. package/fesm2022/ngwr-media.mjs +3 -3
  167. package/fesm2022/ngwr-mention.mjs +24 -8
  168. package/fesm2022/ngwr-mention.mjs.map +1 -1
  169. package/fesm2022/ngwr-meta.mjs +6 -6
  170. package/fesm2022/ngwr-meter-group.mjs +3 -3
  171. package/fesm2022/ngwr-overlay.mjs +125 -10
  172. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  173. package/fesm2022/ngwr-page-header.mjs +3 -3
  174. package/fesm2022/ngwr-pagination.mjs +33 -6
  175. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  176. package/fesm2022/ngwr-pipes.mjs +21 -21
  177. package/fesm2022/ngwr-platform.mjs +9 -9
  178. package/fesm2022/ngwr-popconfirm.mjs +25 -9
  179. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  180. package/fesm2022/ngwr-popover-testing.mjs +22 -5
  181. package/fesm2022/ngwr-popover-testing.mjs.map +1 -1
  182. package/fesm2022/ngwr-popover.mjs +243 -37
  183. package/fesm2022/ngwr-popover.mjs.map +1 -1
  184. package/fesm2022/ngwr-progress.mjs +3 -3
  185. package/fesm2022/ngwr-pull-to-refresh.mjs +3 -3
  186. package/fesm2022/ngwr-qr.mjs +3 -3
  187. package/fesm2022/ngwr-radio.mjs +6 -6
  188. package/fesm2022/ngwr-rating-testing.mjs +12 -3
  189. package/fesm2022/ngwr-rating-testing.mjs.map +1 -1
  190. package/fesm2022/ngwr-rating.mjs +19 -4
  191. package/fesm2022/ngwr-rating.mjs.map +1 -1
  192. package/fesm2022/ngwr-result.mjs +13 -13
  193. package/fesm2022/ngwr-result.mjs.map +1 -1
  194. package/fesm2022/ngwr-rotating-text.mjs +3 -3
  195. package/fesm2022/ngwr-schema-form.mjs +3 -3
  196. package/fesm2022/ngwr-scroll.mjs +3 -3
  197. package/fesm2022/ngwr-segmented.mjs +37 -4
  198. package/fesm2022/ngwr-segmented.mjs.map +1 -1
  199. package/fesm2022/ngwr-select.mjs +24 -10
  200. package/fesm2022/ngwr-select.mjs.map +1 -1
  201. package/fesm2022/ngwr-shiny-text.mjs +6 -6
  202. package/fesm2022/ngwr-sidebar.mjs +3 -3
  203. package/fesm2022/ngwr-skeleton.mjs +3 -3
  204. package/fesm2022/ngwr-slider.mjs +18 -5
  205. package/fesm2022/ngwr-slider.mjs.map +1 -1
  206. package/fesm2022/ngwr-sparkline.mjs +3 -3
  207. package/fesm2022/ngwr-speed-dial.mjs +3 -3
  208. package/fesm2022/ngwr-spinner.mjs +3 -3
  209. package/fesm2022/ngwr-splash-cursor.mjs +3 -3
  210. package/fesm2022/ngwr-split-text.mjs +3 -3
  211. package/fesm2022/ngwr-splitter.mjs +3 -3
  212. package/fesm2022/ngwr-spotlight-card.mjs +6 -6
  213. package/fesm2022/ngwr-squircle.mjs +28 -9
  214. package/fesm2022/ngwr-squircle.mjs.map +1 -1
  215. package/fesm2022/ngwr-star-border.mjs +3 -3
  216. package/fesm2022/ngwr-statistic.mjs +20 -13
  217. package/fesm2022/ngwr-statistic.mjs.map +1 -1
  218. package/fesm2022/ngwr-stepper.mjs +6 -6
  219. package/fesm2022/ngwr-storage.mjs +3 -3
  220. package/fesm2022/ngwr-switch.mjs +3 -3
  221. package/fesm2022/ngwr-table.mjs +18 -18
  222. package/fesm2022/ngwr-tabs-router.mjs +3 -3
  223. package/fesm2022/ngwr-tabs.mjs +6 -6
  224. package/fesm2022/ngwr-textarea.mjs +3 -3
  225. package/fesm2022/ngwr-theme.mjs +3 -3
  226. package/fesm2022/ngwr-tilt-card.mjs +6 -6
  227. package/fesm2022/ngwr-timeline.mjs +6 -6
  228. package/fesm2022/ngwr-toast.mjs +29 -12
  229. package/fesm2022/ngwr-toast.mjs.map +1 -1
  230. package/fesm2022/ngwr-toolbar.mjs +3 -3
  231. package/fesm2022/ngwr-tour.mjs +26 -12
  232. package/fesm2022/ngwr-tour.mjs.map +1 -1
  233. package/fesm2022/ngwr-transfer.mjs +88 -11
  234. package/fesm2022/ngwr-transfer.mjs.map +1 -1
  235. package/fesm2022/ngwr-tree-testing.mjs +24 -0
  236. package/fesm2022/ngwr-tree-testing.mjs.map +1 -1
  237. package/fesm2022/ngwr-tree.mjs +81 -9
  238. package/fesm2022/ngwr-tree.mjs.map +1 -1
  239. package/fesm2022/ngwr-typewriter.mjs +3 -3
  240. package/fesm2022/ngwr-typography.mjs +3 -3
  241. package/fesm2022/ngwr-version.mjs +1 -1
  242. package/fesm2022/ngwr-version.mjs.map +1 -1
  243. package/fesm2022/ngwr-virtual-scroll.mjs +3 -3
  244. package/fesm2022/ngwr-waves.mjs +3 -3
  245. package/fesm2022/ngwr-window.mjs +30 -13
  246. package/fesm2022/ngwr-window.mjs.map +1 -1
  247. package/form/styles/_index.scss +63 -0
  248. package/graph/styles/_index.scss +113 -0
  249. package/i18n/ar.json +9 -2
  250. package/i18n/cs.json +9 -2
  251. package/i18n/de.json +9 -2
  252. package/i18n/en.json +11 -4
  253. package/i18n/es.json +9 -2
  254. package/i18n/fr.json +9 -2
  255. package/i18n/he.json +9 -2
  256. package/i18n/hi.json +9 -2
  257. package/i18n/id.json +9 -2
  258. package/i18n/it.json +9 -2
  259. package/i18n/ja.json +9 -2
  260. package/i18n/ko.json +9 -2
  261. package/i18n/nl.json +9 -2
  262. package/i18n/pl.json +9 -2
  263. package/i18n/pt.json +9 -2
  264. package/i18n/ru.json +9 -2
  265. package/i18n/sv.json +9 -2
  266. package/i18n/tr.json +9 -2
  267. package/i18n/uk.json +9 -2
  268. package/i18n/vi.json +9 -2
  269. package/i18n/zh-TW.json +9 -2
  270. package/i18n/zh.json +9 -2
  271. package/input-otp/styles/_index.scss +5 -1
  272. package/line-chart/styles/_index.scss +5 -3
  273. package/llms-full.txt +13 -3
  274. package/llms.txt +8 -6
  275. package/markdown/styles/_index.scss +4 -1
  276. package/mention/styles/_index.scss +22 -1
  277. package/package.json +10 -1
  278. package/radio/styles/_index.scss +3 -0
  279. package/result/styles/_index.scss +12 -0
  280. package/schematics/migrations/v14/index.js +6 -3
  281. package/schematics/migrations.json +1 -1
  282. package/schematics/ng-add/index.js +34 -5
  283. package/schematics/use/symbol-map.json +2 -0
  284. package/segmented/styles/_index.scss +12 -1
  285. package/select/styles/_index.scss +20 -1
  286. package/skills/ngwr/SKILL.md +1 -1
  287. package/skills/ngwr/references/catalog.md +2 -0
  288. package/statistic/styles/_index.scss +4 -0
  289. package/stepper/styles/_index.scss +36 -0
  290. package/styles.scss +1 -0
  291. package/switch/styles/_index.scss +3 -0
  292. package/table/styles/_index.scss +12 -0
  293. package/tabs/styles/_index.scss +4 -1
  294. package/textarea/styles/_index.scss +6 -1
  295. package/theme/styles/_colors.scss +11 -0
  296. package/theme/styles/_contrast.scss +136 -0
  297. package/theme/styles/_focus.scss +7 -0
  298. package/theme/styles/_index.scss +1 -0
  299. package/theme/styles/_mixins.scss +15 -8
  300. package/timeline/styles/_index.scss +28 -1
  301. package/toast/styles/_index.scss +11 -0
  302. package/tree/styles/_index.scss +27 -1
  303. package/types/ngwr-badge.d.ts +1 -1
  304. package/types/ngwr-bar-chart-testing.d.ts +11 -1
  305. package/types/ngwr-button.d.ts +1 -1
  306. package/types/ngwr-calendar-heatmap-testing.d.ts +10 -5
  307. package/types/ngwr-calendar-heatmap.d.ts +22 -0
  308. package/types/ngwr-calendar.d.ts +21 -0
  309. package/types/ngwr-cascader-testing.d.ts +74 -17
  310. package/types/ngwr-cascader.d.ts +35 -0
  311. package/types/ngwr-checkbox-testing.d.ts +12 -1
  312. package/types/ngwr-checkbox.d.ts +10 -0
  313. package/types/ngwr-clipboard.d.ts +1 -1
  314. package/types/ngwr-color-picker.d.ts +8 -0
  315. package/types/ngwr-confetti.d.ts +1 -1
  316. package/types/ngwr-context-menu.d.ts +10 -0
  317. package/types/ngwr-cookie.d.ts +1 -1
  318. package/types/ngwr-date-adapters-fns.d.ts +1 -1
  319. package/types/ngwr-date-adapters-luxon.d.ts +1 -1
  320. package/types/ngwr-date-picker.d.ts +16 -0
  321. package/types/ngwr-date.d.ts +9 -3
  322. package/types/ngwr-density.d.ts +1 -1
  323. package/types/ngwr-dialog.d.ts +2 -1
  324. package/types/ngwr-donut-chart-testing.d.ts +11 -1
  325. package/types/ngwr-drawer.d.ts +29 -1
  326. package/types/ngwr-dropdown.d.ts +25 -0
  327. package/types/ngwr-file-upload.d.ts +11 -0
  328. package/types/ngwr-form.d.ts +25 -0
  329. package/types/ngwr-gauge-testing.d.ts +9 -1
  330. package/types/ngwr-graph-testing.d.ts +190 -0
  331. package/types/ngwr-graph.d.ts +203 -0
  332. package/types/ngwr-hotkey.d.ts +1 -1
  333. package/types/ngwr-i18n.d.ts +1 -1
  334. package/types/ngwr-input-number.d.ts +12 -2
  335. package/types/ngwr-input-otp.d.ts +12 -0
  336. package/types/ngwr-knob-testing.d.ts +11 -3
  337. package/types/ngwr-knob.d.ts +13 -0
  338. package/types/ngwr-lightbox.d.ts +15 -0
  339. package/types/ngwr-line-chart-testing.d.ts +11 -1
  340. package/types/ngwr-line-chart.d.ts +18 -0
  341. package/types/ngwr-loading-bar.d.ts +1 -1
  342. package/types/ngwr-markdown.d.ts +1 -1
  343. package/types/ngwr-media.d.ts +1 -1
  344. package/types/ngwr-mention.d.ts +7 -0
  345. package/types/ngwr-meta.d.ts +1 -1
  346. package/types/ngwr-overlay.d.ts +64 -6
  347. package/types/ngwr-pagination.d.ts +16 -0
  348. package/types/ngwr-platform.d.ts +3 -3
  349. package/types/ngwr-popconfirm.d.ts +1 -0
  350. package/types/ngwr-popover-testing.d.ts +22 -5
  351. package/types/ngwr-popover.d.ts +44 -8
  352. package/types/ngwr-rating-testing.d.ts +12 -3
  353. package/types/ngwr-rating.d.ts +13 -0
  354. package/types/ngwr-scroll.d.ts +1 -1
  355. package/types/ngwr-segmented.d.ts +16 -0
  356. package/types/ngwr-select.d.ts +7 -0
  357. package/types/ngwr-squircle.d.ts +22 -3
  358. package/types/ngwr-statistic.d.ts +0 -1
  359. package/types/ngwr-storage.d.ts +1 -1
  360. package/types/ngwr-theme.d.ts +1 -1
  361. package/types/ngwr-toast.d.ts +3 -1
  362. package/types/ngwr-tour.d.ts +7 -1
  363. package/types/ngwr-transfer.d.ts +52 -0
  364. package/types/ngwr-tree-testing.d.ts +20 -0
  365. package/types/ngwr-tree.d.ts +43 -1
  366. package/types/ngwr-version.d.ts +1 -1
  367. package/types/ngwr-window.d.ts +2 -1
  368. package/typography/styles/_index.scss +26 -4
@@ -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 { 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 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 } 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 private readonly scrollStrategies = inject(ScrollStrategyOptions);\n private readonly destroyRef = inject(DestroyRef);\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 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.5", ngImport: i0, type: WrMeta, deps: [], target: i0.ɵɵFactoryTarget.Service });
251
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.5", ngImport: i0, type: WrMeta });
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 });
252
252
  }
253
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrMeta, decorators: [{
253
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", 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.5", ngImport: i0, type: WrMetaBinding, deps: [], target: i0.ɵɵFactoryTarget.Directive });
296
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.5", 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.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 });
297
297
  }
298
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrMetaBinding, decorators: [{
298
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", 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 }] }] } });
@@ -82,10 +82,10 @@ class WrMeterGroup {
82
82
  percent: (WrMeterGroup.amount(segment.value) / this.resolvedMax()) * 100,
83
83
  })), /* @ts-ignore */
84
84
  ...(ngDevMode ? [{ debugName: "slices" }] : /* istanbul ignore next */ []));
85
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrMeterGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
86
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", 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 });
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 });
87
87
  }
88
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrMeterGroup, decorators: [{
88
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrMeterGroup, decorators: [{
89
89
  type: Component,
90
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
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 }] }] } });
@@ -1,7 +1,8 @@
1
- import { DOCUMENT, isPlatformBrowser } from '@angular/common';
2
1
  import * as i0 from '@angular/core';
3
- import { inject, PLATFORM_ID, Service, InjectionToken, makeEnvironmentProviders, provideEnvironmentInitializer, EnvironmentInjector, Injector } from '@angular/core';
4
- import { Observable } from 'rxjs';
2
+ import { untracked, effect, inject, PLATFORM_ID, Service, InjectionToken, makeEnvironmentProviders, provideEnvironmentInitializer, EnvironmentInjector, Injector } from '@angular/core';
3
+ import { Subscription, Observable } from 'rxjs';
4
+ import { noop } from 'ngwr/utils';
5
+ import { DOCUMENT, isPlatformBrowser } from '@angular/common';
5
6
  import { OverlayContainer, Overlay } from '@angular/cdk/overlay';
6
7
  import { WrVisualViewport } from 'ngwr/platform';
7
8
 
@@ -76,6 +77,120 @@ function wrAppendOverlayClose(host, className, label, onClose) {
76
77
  return button;
77
78
  }
78
79
 
80
+ /**
81
+ * @license
82
+ *
83
+ * Use of this source code is governed by an MIT-style license that can be
84
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
85
+ */
86
+ /**
87
+ * Keep an OPEN overlay on the application's reading direction.
88
+ *
89
+ * The CDK reads the direction ONCE, as a string, when the overlay is created
90
+ * (`overlayConfig.direction ||= directionality.value`), writes it as the host's
91
+ * `dir` on attach, and never looks at it again — `updatePosition()` does not
92
+ * touch it and `setDirection()` is the only thing that does. So an application
93
+ * that flips direction while a panel is open mirrors the page and leaves the
94
+ * panel behind, still `ltr`, still resolving `start` to the left. This site's
95
+ * own LTR/RTL switch is the demonstration: it lives inside a `wr-dropdown`, and
96
+ * the `wr-segmented` it is built from reads `Directionality` live — so the thumb
97
+ * slides to the other slot while the pane around it still renders `ltr`, and
98
+ * parks under the wrong label.
99
+ *
100
+ * Call it once per `OverlayRef`, right after `overlay.create(...)`. The follower
101
+ * ends itself when that overlay detaches or is disposed, so a reopen — which is
102
+ * always a NEW ref in this library — needs a new call, and the returned teardown
103
+ * is only for stopping early.
104
+ *
105
+ * `onDirectionChange` is for the sites whose position LIST is itself
106
+ * direction-dependent (the four that pass their table through
107
+ * {@link wrMirrorOffsets}): it runs with the new direction already on the ref
108
+ * and before the overlay repositions, so the strategy is carrying the mirrored
109
+ * offsets by the time the CDK re-resolves them.
110
+ *
111
+ * SSR-safe: it touches no browser global of its own, and the CDK's position
112
+ * strategies no-op off the browser, so a flip on the server only rewrites the
113
+ * attribute.
114
+ *
115
+ * @param overlayRef The overlay to keep in step, freshly created.
116
+ * @param dir The `Directionality` the caller injected. `null` — an optional
117
+ * inject with no provider, i.e. a bare `TestBed` — means there is nothing
118
+ * ambient to follow and this does nothing at all.
119
+ * @param injector Owns the `valueSignal` watch; the caller's own is right.
120
+ * @param onDirectionChange Re-applies direction-dependent state, e.g.
121
+ * `strategy.withPositions(wrMirrorOffsets(TABLE, direction === 'rtl'))`.
122
+ * @returns Stops following. Idempotent, and unnecessary in the normal case.
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * this.overlayRef = this.overlay.create({ positionStrategy, ... });
127
+ * wrFollowDirection(this.overlayRef, this.dir, this.injector, direction =>
128
+ * positionStrategy.withPositions(
129
+ * wrMirrorOffsets(WR_POPCONFIRM_POSITIONS[this.position()], direction === 'rtl')
130
+ * )
131
+ * );
132
+ * ```
133
+ */
134
+ function wrFollowDirection(overlayRef, dir, injector, onDirectionChange) {
135
+ if (!dir)
136
+ return noop;
137
+ const apply = (next) => {
138
+ // Comparing against the REF rather than a direction captured up here does
139
+ // three jobs at once: the watch's mandatory first run is a no-op, a flip
140
+ // that arrives down both channels is applied once, and a same-value write
141
+ // never yanks a panel the user is reading.
142
+ if (next === overlayRef.getDirection())
143
+ return;
144
+ overlayRef.setDirection(next); // rewrites the host's `dir`; it does NOT reposition
145
+ onDirectionChange?.(next); // the caller re-mirrors its position list here
146
+ overlayRef.updatePosition(); // re-resolves start/end against the direction just set
147
+ };
148
+ // Two channels, because they are not the same thing. `valueSignal` is the
149
+ // state — `Directionality.value` is a getter over it, so nothing can change
150
+ // direction without writing it. `change` is an EventEmitter the root instance
151
+ // never emits: it reads the document once at construction and only completes
152
+ // the emitter on destroy, so it belongs to the `[dir]` directive (and to an
153
+ // app, like this site's header, that emits it by hand as a courtesy). Keying
154
+ // on `change` alone would be dead for an app that just writes the signal;
155
+ // keying on the signal alone would ignore the `{ value, change }` test double
156
+ // that a dozen of the library's RTL specs hand their component.
157
+ //
158
+ // `untracked` because of WHERE this is called from: half the call sites open
159
+ // their overlay out of an `effect(() => { if (this.isOpen()) … })`, and
160
+ // `effect()` refuses in dev mode to be created inside a reactive context.
161
+ // Laundering only the CREATION is exactly right — the watch below still
162
+ // depends on `valueSignal` and on nothing else.
163
+ const watch = untracked(() => effect(() => {
164
+ // Read as a plain optional function rather than as a `Signal`, because
165
+ // the case being guarded is a double that has no signal at all: falling
166
+ // back to `value` registers no dependency, so the watch simply never
167
+ // re-runs and `change` carries that case on its own.
168
+ const read = dir.valueSignal;
169
+ apply(read ? read() : dir.value);
170
+ }, { injector }));
171
+ // rxjs owns the teardown, and an `OverlayRef` is why. Open and close happen in
172
+ // an event handler or an effect, never in an injection context, so the idiom
173
+ // that suggests itself — `takeUntilDestroyed(destroyRef)` — would tie this to
174
+ // the DIRECTIVE's lifetime: a menu opened fifty times would leave fifty
175
+ // followers behind, each pinning a disposed ref. (`WrOutsideClick`'s JSDoc
176
+ // records that same mistake, made at ten call sites.) `detachments()` is the
177
+ // overlay's own lifetime and the one channel every dismissal goes through.
178
+ // And it is not hygiene: `setDirection()` writes through the host element
179
+ // `dispose()` nulls, so a watch that outlives its overlay THROWS on the next
180
+ // flip.
181
+ const teardown = new Subscription();
182
+ const stop = () => teardown.unsubscribe();
183
+ teardown.add(() => watch.destroy());
184
+ teardown.add(dir.change.subscribe(apply));
185
+ // Both handlers, for the reason `WrOutsideClick` gives: a live ref arrives
186
+ // through `next`, one already disposed before this call has only `complete`
187
+ // left to give.
188
+ teardown.add(overlayRef.detachments().subscribe({ next: stop, complete: stop }));
189
+ // `Subscription.unsubscribe()` is a no-op once closed, so the caller's copy of
190
+ // this and the automatic one cannot fight, and calling it twice is free.
191
+ return stop;
192
+ }
193
+
79
194
  /**
80
195
  * @license
81
196
  *
@@ -271,10 +386,10 @@ class WrOutsideClick {
271
386
  this.cleanup = null;
272
387
  this.pressOrigin = null;
273
388
  }
274
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrOutsideClick, deps: [], target: i0.ɵɵFactoryTarget.Service });
275
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.5", ngImport: i0, type: WrOutsideClick });
389
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrOutsideClick, deps: [], target: i0.ɵɵFactoryTarget.Service });
390
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.6", ngImport: i0, type: WrOutsideClick });
276
391
  }
277
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrOutsideClick, decorators: [{
392
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrOutsideClick, decorators: [{
278
393
  type: Service
279
394
  }] });
280
395
 
@@ -305,10 +420,10 @@ class WrOverlayContainer extends OverlayContainer {
305
420
  super._createContainer();
306
421
  this._containerElement?.classList.add('wr-overlay-container');
307
422
  }
308
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrOverlayContainer, deps: [], target: i0.ɵɵFactoryTarget.Service });
309
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.5", ngImport: i0, type: WrOverlayContainer });
423
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrOverlayContainer, deps: [], target: i0.ɵɵFactoryTarget.Service });
424
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.6", ngImport: i0, type: WrOverlayContainer });
310
425
  }
311
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrOverlayContainer, decorators: [{
426
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrOverlayContainer, decorators: [{
312
427
  type: Service
313
428
  }] });
314
429
 
@@ -490,5 +605,5 @@ function provideWrResponsiveOverlays(config) {
490
605
  * Generated bundle index. Do not edit.
491
606
  */
492
607
 
493
- export { WR_OVERLAY, WR_OVERLAY_CONTAINER, WR_RESPONSIVE_OVERLAYS, WrOutsideClick, WrOverlayContainer, provideWrOverlay, provideWrResponsiveOverlays, wrAppendOverlayClose, wrMirrorOffsets, wrPresentAsSheet };
608
+ export { WR_OVERLAY, WR_OVERLAY_CONTAINER, WR_RESPONSIVE_OVERLAYS, WrOutsideClick, WrOverlayContainer, provideWrOverlay, provideWrResponsiveOverlays, wrAppendOverlayClose, wrFollowDirection, wrMirrorOffsets, wrPresentAsSheet };
494
609
  //# sourceMappingURL=ngwr-overlay.mjs.map